将所有变量更改为显式键入

时间:2018-01-11 08:02:49

标签: vb.net visual-studio automation

(无意对编码风格展开宗教战争,我只需要解决手头的问题)

我刚刚被要求更改解决方案中的所有变量声明以使用显式输入,即:

Dim Result = 3 + 5

应转换为:

Dim Result As Integer = 3 + 5

显然,这不能通过查找/替换或甚至使用正则表达式来完成。我想到的另外两种可能性是:

  1. Resharper:我刚才发现的只能用于C#,而不是VB.NET。
  2. 宏:自VS2012以来已被删除(对我来说是个新闻)。
  3. 是否有另一种方法可以自动完成这项繁琐的工作?该解决方案包含数十万行代码,因此手动执行操作不是一种选择。

    这适用于VS2017社区。

1 个答案:

答案 0 :(得分:0)

最后,我能够使用多种技术解决我的问题。以下是我所做的事情,以防其他人在路上:

  1. 我与有关方面进行了交谈,我们同意在以下情况下不需要使用显式打字:

    Dim X1 = 45 + 43 'Type can be inferred by the reader easily
    Dim X2 = DirectCast(obj, DataReader) 'Type explicitly mentioned on RHS        
    Dim X3 = New SomeClass() 'Type explicitly mentioned on RHS
    
  2. 因此,实际上不太可读且需要明确打字的情况如下:

    Dim X4 = SomeMethod() 'Cannot infer X4's type without peeking or using Go To Definition
    
  3. 然后,我使用以下RegEx来查找所有此类实例:

    Dim \w+ = (?!(New|\d|"|DirectCast))
    
  4. 我只剩下几百个实例,但单独完成它们,找到RHS方法的类型然后在LHS上输入它仍然是一项艰巨的任务。所以我搜索了VS扩展,发现Visual Commander允许我们在C#或VB.NET中编写,猜测什么,宏,并使用Roslyn API以我们想要的任何方式操作代码元素。所以我安装它并在玩了一段时间后,我能够编写以下宏来提取RHS方法的返回类型,然后将其注入LHS:

    using Microsoft.CodeAnalysis;
    using Microsoft.CodeAnalysis.Text;
    using System.Linq;
    using Microsoft.CodeAnalysis.VisualBasic;
    using Microsoft.CodeAnalysis.VisualBasic.Syntax;
    
    public class C : VisualCommanderExt.ICommand
    {
      public void Run(EnvDTE80.DTE2 DTE, Microsoft.VisualStudio.Shell.Package package)
      {
        serviceProvider = package as System.IServiceProvider;
        Microsoft.VisualStudio.Text.Editor.IWpfTextView textView = GetTextView();
    
        Microsoft.VisualStudio.Text.SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition;
        Microsoft.CodeAnalysis.Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
        Microsoft.CodeAnalysis.VisualBasic.Syntax.LocalDeclarationStatementSyntax invocationExpressionNode =
            document.GetSyntaxRootAsync().Result.FindToken(caretPosition).Parent.AncestorsAndSelf().
                OfType<Microsoft.CodeAnalysis.VisualBasic.Syntax.LocalDeclarationStatementSyntax>().FirstOrDefault();
    
        if (invocationExpressionNode != null)
        {
          Microsoft.CodeAnalysis.SemanticModel semanticModel = document.GetSemanticModelAsync().Result;
    
          var VD = invocationExpressionNode.ChildNodes().FirstOrDefault(c => c.IsKind(SyntaxKind.VariableDeclarator));
    
          if (VD != null)
          {
            var EV = VD.ChildNodes().FirstOrDefault(c => c.IsKind(SyntaxKind.EqualsValue) || c.IsKind(SyntaxKind.EqualsExpression));
    
            if (EV != null)
            {
              object IE = EV.ChildNodes().FirstOrDefault(c => c.IsKind(SyntaxKind.InvocationExpression));
    
              if (IE != null)
              {
                Microsoft.CodeAnalysis.IMethodSymbol methodSymbol =
                  semanticModel.GetSymbolInfo((InvocationExpressionSyntax)IE).Symbol as Microsoft.CodeAnalysis.IMethodSymbol;
    
                string TypeName = methodSymbol.ReturnType.ToString();
                string ToInsert = " As " + TypeName;
                textView.TextBuffer.Insert(((InvocationExpressionSyntax)IE).SpanStart - 2, ToInsert);
              }
            }
          }
        }
      }
    
      private Microsoft.VisualStudio.Text.Editor.IWpfTextView GetTextView()
      {
        Microsoft.VisualStudio.TextManager.Interop.IVsTextManager textManager =
            (Microsoft.VisualStudio.TextManager.Interop.IVsTextManager)serviceProvider.GetService(
                typeof(Microsoft.VisualStudio.TextManager.Interop.SVsTextManager));
        Microsoft.VisualStudio.TextManager.Interop.IVsTextView textView;
        textManager.GetActiveView(1, null, out textView);
        return GetEditorAdaptersFactoryService().GetWpfTextView(textView);
      }
    
      private Microsoft.VisualStudio.Editor.IVsEditorAdaptersFactoryService GetEditorAdaptersFactoryService()
      {
        Microsoft.VisualStudio.ComponentModelHost.IComponentModel componentModel =
            (Microsoft.VisualStudio.ComponentModelHost.IComponentModel)serviceProvider.GetService(
                typeof(Microsoft.VisualStudio.ComponentModelHost.SComponentModel));
        return componentModel.GetService<Microsoft.VisualStudio.Editor.IVsEditorAdaptersFactoryService>();
      }
    
      private System.IServiceProvider serviceProvider;
    }
    
  5. 这个剧本对我来说很重要。然后,我可以为GoToFindResult1NextLocationGoToFindResult1PrevLocation命令分配快捷键,并遍历查找结果,修复我需要的那些。

  6. 通过循环解决方案中的所有文件并自动修复所有这些行,可以改进此代码以提供更多自动化,但我认为对更多的线路进行更多控制是明智的。改变。

  7. 最后,我能够在几分钟内解决整个解决方案中的所有问题。此外,我也学到了很多关于Roslyn API的结构。