代码之家  ›  专栏  ›  技术社区  ›  dotNET

将所有变量更改为显式类型

  •  4
  • dotNET  · 技术社区  · 7 年前

    (无意对编码风格发起宗教战争,我只需要解决眼前的问题)

    我刚刚被要求更改整个解决方案中的所有变量声明,以使用显式类型,例如:

    Dim Result = 3 + 5
    

    应转换为:

    Dim Result As Integer = 3 + 5
    

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

    1. Resharper:我刚刚发现它只能用于C#,不能用于VB。网。
    2. 宏:自VS2012以来已被删除(对我来说是个新闻)。

    有没有其他方法可以自动化这项繁琐的工作?该解决方案包含数十万行代码,因此手工操作不是一种选择。

    这是针对VS2017社区的。

    1 回复  |  直到 7 年前
        1
  •  1
  •   dotNET    7 年前

    最后,我能够使用多种技术解决我的问题。以下是我所做的,以防这对其他人有所帮助:

    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. 然后,我使用以下正则表达式查找所有此类实例:

      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. 这个剧本为我起了很大的作用。然后,我可以将快捷键分配给 GoToFindResult1NextLocation GoToFindResult1PrevLocation 命令并遍历查找结果,修复我需要的结果。

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

    最后,我能够在几分钟内解决整个解决方案中的所有问题。此外,我还对Roslyn API的结构了解了很多。