У меня есть логика c для добавления функции в класс с помощью Roslyn, которая работает с проектом C#, но не с проектом VB. Я использую DocumentEditor класс редактора ( Microsoft.CodeAnalysis.Editing.DocumentEditor ) для выполнения обновления.
Я начинаю с поиска SyntaxNode соответствует определению класса.
В C# это элемент ClassDeclarationSyntax .
В VB это ClassBlockSyntax element.
Я генерирую полный текст новой функции в строковой переменной, а затем создаю 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#.