(无意对编码风格展开宗教战争,我只需要解决手头的问题)
我刚刚被要求更改解决方案中的所有变量声明以使用显式输入,即:
Dim Result = 3 + 5
应转换为:
Dim Result As Integer = 3 + 5
显然,这不能通过查找/替换或甚至使用正则表达式来完成。我想到的另外两种可能性是:
是否有另一种方法可以自动完成这项繁琐的工作?该解决方案包含数十万行代码,因此手动执行操作不是一种选择。
这适用于VS2017社区。 p>
答案 0 :(得分:0)
最后,我能够使用多种技术解决我的问题。以下是我所做的事情,以防其他人在路上:
我与有关方面进行了交谈,我们同意在以下情况下不需要使用显式打字:
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
因此,实际上不太可读且需要明确打字的情况如下:
Dim X4 = SomeMethod() 'Cannot infer X4's type without peeking or using Go To Definition
然后,我使用以下RegEx来查找所有此类实例:
Dim \w+ = (?!(New|\d|"|DirectCast))
我只剩下几百个实例,但单独完成它们,找到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;
}
这个剧本对我来说很重要。然后,我可以为GoToFindResult1NextLocation
和GoToFindResult1PrevLocation
命令分配快捷键,并遍历查找结果,修复我需要的那些。
通过循环解决方案中的所有文件并自动修复所有这些行,可以改进此代码以提供更多自动化,但我认为对更多的线路进行更多控制是明智的。改变。
最后,我能够在几分钟内解决整个解决方案中的所有问题。此外,我也学到了很多关于Roslyn API的结构。