如何使用Roslyn将函数插入VB.NET中的类

问题描述 投票:0回答:1

我有一些逻辑,可以使用Roslyn向类添加函数,该函数适用于C#项目,但不适用于VB项目。我正在使用DocumentEditor编辑器类(Microsoft.CodeAnalysis.Editing.DocumentEditor)执行更新。

我首先找到与类定义相对应的SyntaxNode

在C#中,这是一个[[ClassDeclarationSyntax元素。

Screenshot of Syntax Visualizer for VB class

在VB中,这是

ClassBlockSyntax

元素。Screenshot of Syntax Visualizer for VB class

我在字符串变量中生成新函数的完整文本,然后从该文本创建SyntaxNode。

对于C#,我使用方法

CSharpSyntaxTree.ParseText

,大致如下:var Tree = CSharpSyntaxTree.ParseText ( Code, CSharpParseOptions.Default ) ; var Root = await Tree.GetRootAsync() as CompilationUnitSyntax ; var Expr = Root.Members.FirstOrDefault() .WithAdditionalAnnotations ( Formatter.Annotation ) ;
然后,Expr的类型为

MethodDeclarationSyntax

对于VB,我使用方法

VisualBasicSyntaxTree.ParseText

,其代码几乎相同:var Tree = VisualBasicSyntaxTree.ParseText ( Code ) ; var Root = await Tree.GetRootAsync() as CompilationUnitSyntax ; var Expr = Root.Members.FirstOrDefault() ;
在这种情况下,Expr的类型为

MethodBlockSyntax

然后我尝试将新节点插入类。

对于C#,我使用

RoslynDocEditor.InsertAfter ( RoslynClass.ChildNodes.Last, Expr )

其中RoslynClass是ClassBlockSyntax节点,以及稍后……

RootNode = RoslynDocEditor.GetChangedRoot() RootNode = Formatter.Format ( RootNode, Formatter.Annotation, VSWorkspace ) RoslynDoc = RoslynDoc.WithSyntaxRoot ( RootNode ) ApplyOK = VSWorkspace.TryApplyChanges ( RoslynDoc.Project.Solution )

这将在类末尾添加新功能。

如果我对VB进行同样的操作,则会在该行生成

InvalidOperationException

RootNode = RoslynDocEditor.GetChangedRoot()
带有描述

“指定的项目不是列表的元素”和堆栈跟踪:

at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.NodeListEditor.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitClassBlock(ClassBlockSyntax node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.ClassBlockSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.BaseListEditor.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.NodeListEditor.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitListElement[TNode](TNode node) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitList[TNode](SyntaxList`1 list) at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.NodeListEditor.VisitList[TNode](SyntaxList`1 list) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.VisitCompilationUnit(CompilationUnitSyntax node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.CompilationUnitSyntax.Accept[TResult](VisualBasicSyntaxVisitor`1 visitor) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxRewriter.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.BaseListEditor.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.NodeListEditor.Visit(SyntaxNode node) at Microsoft.CodeAnalysis.VisualBasic.Syntax.SyntaxReplacer.InsertNodeInList(SyntaxNode root, SyntaxNode nodeInList, IEnumerable`1 nodesToInsert, Boolean insertBefore) at Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode.InsertNodesInListCore(SyntaxNode nodeInList, IEnumerable`1 nodesToInsert, Boolean insertBefore) at Microsoft.CodeAnalysis.SyntaxNodeExtensions.InsertNodesBefore[TRoot](TRoot root, SyntaxNode nodeInList, IEnumerable`1 newNodes) at Microsoft.CodeAnalysis.VisualBasic.CodeGeneration.VisualBasicSyntaxGenerator.InsertDeclarationsBeforeInternal(SyntaxNode root, SyntaxNode declaration, IEnumerable`1 newDeclarations) at Microsoft.CodeAnalysis.VisualBasic.CodeGeneration.VisualBasicSyntaxGenerator._Closure$__310-0._Lambda$__0(SyntaxNode r) at Microsoft.CodeAnalysis.Editing.SyntaxGenerator.PreserveTrivia[TNode](TNode node, Func`2 nodeChanger) at Microsoft.CodeAnalysis.VisualBasic.CodeGeneration.VisualBasicSyntaxGenerator.InsertNodesBefore(SyntaxNode root, SyntaxNode declaration, IEnumerable`1 newDeclarations) at Microsoft.CodeAnalysis.Editing.SyntaxEditor.InsertChange.Apply(SyntaxNode root, SyntaxGenerator generator) at Microsoft.CodeAnalysis.Editing.SyntaxEditor.GetChangedRoot() at MultiLang.frmLanguageSwitching.VB$StateMachine_133_btAdd_Click.MoveNext() in C:\VSPackage_Version_7_1\Project\MultiLang\Forms\frmLanguageSwitching.vb:line 944
从语法可视化器的屏幕快照中,您可以看到ClassBlock的最后一个子元素是

EndClassStatement

,因此使用起来更有意义RoslynDocEditor.InsertBefore ( RoslynClass.ChildNodes.Last, NewFunctionNode )
但是会产生与上面完全相同的错误。

是否可以通过类似的方式在VB类中插入函数,或者仅在C#中有效?

roslyn code-analysis visual-studio-extensions
1个回答
0
投票
它适用于VB,如果我将ClassNode从

SyntaxNode(返回)转换为ClassBlockSyntax,然后使用Members集合

var cbs = ClassNode as Microsoft.CodeAnalysis.VisualBasic.Syntax.ClassBlockSyntax ; RoslynDocEditor.InsertAfter ( cbs.Members.Last(), Expr ) ;
如果我将ClassNode强制转换为

ClassDeclarationSyntax

,则对C#同样有效”>var cds = ClassNode as Microsoft.CodeAnalysis.CSharp.Syntax.ClassDeclarationSyntax ; RoslynDocEditor.InsertAfter ( cds.Members.Last(), NewFunction ) ;
但如上所述,对于C#,它也可以与]一起使用>

RoslynDocEditor.InsertAfter ( RoslynClass.ChildNodes.Last, NewFunction ) ;

所以看起来

SyntaxNode.ChildNodes

等同于C#的ClassDeclarationSyntax.Members
,但不等同于VB的ClassBlockSyntax.Members
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.