/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Tools/CompilerGeneratorTools/Source/VisualBasicSyntaxGenerator/GreenNodes/GreenNodeWriter.vb
724 строки
30 KB
Copilot
Remove superfluous `src/Tools/Source` directory level (#83484)
30 апр 2026, 06:54
Не верифицирован
30 апр 2026, 06:54
2933275
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. '----------------------------------------------------------------------------------------------------------- ' This is the code that actually outputs the VB code that defines the tree. It is passed a read and validated ' ParseTree, and outputs the code to defined the node classes for that tree, and also additional data ' structures like the kinds, visitor, etc. '----------------------------------------------------------------------------------------------------------- Imports System.IO ' Class to write out the code for the code tree. Friend Class GreenNodeWriter Inherits WriteUtils Private _writer As TextWriter 'output is sent here. Private ReadOnly _nonterminalsWithOneChild As List(Of String) = New List(Of String) Private ReadOnly _nonterminalsWithTwoChildren As List(Of String) = New List(Of String) ' Initialize the class with the parse tree to write. Public Sub New(parseTree As ParseTree) MyBase.New(parseTree) End Sub ' Write out the code defining the tree to the give file. Public Sub WriteTreeAsCode(writer As TextWriter) _writer = writer GenerateFile() End Sub Private Sub GenerateFile() GenerateNamespace() End Sub Private Sub GenerateNamespace() _writer.WriteLine() If Not String.IsNullOrEmpty(_parseTree.NamespaceName) Then _writer.WriteLine("Namespace {0}", Ident(_parseTree.NamespaceName) + ".Syntax.InternalSyntax") _writer.WriteLine() End If GenerateNodeStructures() If Not String.IsNullOrEmpty(_parseTree.VisitorName) Then GenerateVisitorClass() End If If Not String.IsNullOrEmpty(_parseTree.RewriteVisitorName) Then GenerateRewriteVisitorClass() End If If Not String.IsNullOrEmpty(_parseTree.NamespaceName) Then _writer.WriteLine("End Namespace") End If 'DumpNames("Nodes with One Child", _nonterminalsWithOneChild) 'DumpNames("Nodes with Two Children", _nonterminalsWithTwoChildren) End Sub #Disable Warning IDE0051 ' Remove unused private members Private Sub DumpNames(title As String, names As List(Of String)) #Enable Warning IDE0051 ' Remove unused private members Console.WriteLine(title) Console.WriteLine("=======================================") Dim sortedNames = From n In names Order By n For Each name In sortedNames Console.WriteLine(name) Next Console.WriteLine() End Sub Private Sub GenerateNodeStructures() For Each nodeStructure In _parseTree.NodeStructures.Values If Not nodeStructure.NoFactory Then GenerateNodeStructureClass(nodeStructure) End If Next End Sub ' Generate a class declaration for a node structure. Private Sub GenerateNodeStructureClass(nodeStructure As ParseNodeStructure) ' XML comment GenerateXmlComment(_writer, nodeStructure, 4, includeRemarks:=False) ' Class name _writer.Write(" ") If (nodeStructure.PartialClass) Then _writer.Write("Partial ") End If Dim visibility As String = "Friend" If _parseTree.IsAbstract(nodeStructure) Then _writer.WriteLine("{0} MustInherit Class {1}", visibility, StructureTypeName(nodeStructure)) ElseIf Not nodeStructure.HasDerivedStructure Then _writer.WriteLine("{0} NotInheritable Class {1}", visibility, StructureTypeName(nodeStructure)) Else _writer.WriteLine("{0} Class {1}", visibility, StructureTypeName(nodeStructure)) End If ' Base class If Not IsRoot(nodeStructure) Then _writer.WriteLine(" Inherits {0}", StructureTypeName(nodeStructure.ParentStructure)) End If _writer.WriteLine() 'Create members GenerateNodeStructureMembers(nodeStructure) ' Create the constructor. GenerateNodeStructureConstructor(nodeStructure, noExtra:=True) GenerateNodeStructureConstructor(nodeStructure, noExtra:=True, contextual:=True) GenerateNodeStructureConstructor(nodeStructure) GenerateCreateRed(nodeStructure) ' Create the property accessor for each of the fields Dim fields = nodeStructure.Fields For i = 0 To fields.Count - 1 GenerateNodeFieldProperty(fields(i), i, fields(i).ContainingStructure IsNot nodeStructure) Next ' Create the property accessor for each of the children Dim children = nodeStructure.Children For i = 0 To children.Count - 1 GenerateNodeChildProperty(nodeStructure, children(i), i) GenerateNodeWithChildProperty(children(i), i, nodeStructure) Next If Not (_parseTree.IsAbstract(nodeStructure) OrElse nodeStructure.IsToken) Then If children.Count = 1 Then If Not children(0).IsList AndAlso Not KindTypeStructure(children(0).ChildKind).Name = "ExpressionSyntax" Then _nonterminalsWithOneChild.Add(nodeStructure.Name) End If ElseIf children.Count = 2 Then If Not children(0).IsList AndAlso Not KindTypeStructure(children(0).ChildKind).Name = "ExpressionSyntax" AndAlso Not children(1).IsList AndAlso Not KindTypeStructure(children(1).ChildKind).Name = "ExpressionSyntax" Then _nonterminalsWithTwoChildren.Add(nodeStructure.Name) End If End If End If 'Create GetChild GenerateGetChild(nodeStructure) GenerateWithTrivia(nodeStructure) GenerateSetDiagnostics(nodeStructure) GenerateSetAnnotations(nodeStructure) ' Visitor accept method If Not String.IsNullOrEmpty(_parseTree.VisitorName) Then GenerateAccept(nodeStructure) End If ' Special methods for the root node. If IsRoot(nodeStructure) Then GenerateRootNodeSpecialMethods(nodeStructure) End If ' End the class _writer.WriteLine(" End Class") _writer.WriteLine() End Sub ' Generate CreateRed method Private Sub GenerateCreateRed(nodeStructure As ParseNodeStructure) If _parseTree.IsAbstract(nodeStructure) OrElse nodeStructure.IsToken OrElse nodeStructure.IsTrivia Then Return End If _writer.WriteLine(" Friend Overrides Function CreateRed(ByVal parent As SyntaxNode, ByVal startLocation As Integer) As SyntaxNode") _writer.WriteLine(" Return new {0}.Syntax.{1}(Me, parent, startLocation)", _parseTree.NamespaceName, StructureTypeName(nodeStructure)) _writer.WriteLine(" End Function") _writer.WriteLine() End Sub ' Generate SetDiagnostics method Private Sub GenerateSetDiagnostics(nodeStructure As ParseNodeStructure) If _parseTree.IsAbstract(nodeStructure) Then Return End If _writer.WriteLine(" Friend Overrides Function SetDiagnostics(ByVal newErrors As DiagnosticInfo()) As GreenNode") _writer.Write(" Return new {0}", StructureTypeName(nodeStructure)) GenerateNodeStructureConstructorParameters(nodeStructure, "newErrors", "GetAnnotations", "GetLeadingTrivia", "GetTrailingTrivia") _writer.WriteLine(" End Function") _writer.WriteLine() End Sub ' Generate SetAnnotations method Private Sub GenerateSetAnnotations(nodeStructure As ParseNodeStructure) If _parseTree.IsAbstract(nodeStructure) Then Return End If _writer.WriteLine(" Friend Overrides Function SetAnnotations(ByVal annotations As SyntaxAnnotation()) As GreenNode") _writer.Write(" Return new {0}", StructureTypeName(nodeStructure)) GenerateNodeStructureConstructorParameters(nodeStructure, "GetDiagnostics", "annotations", "GetLeadingTrivia", "GetTrailingTrivia") _writer.WriteLine(" End Function") _writer.WriteLine() End Sub ' Generate WithTrivia method s Private Sub GenerateWithTrivia(nodeStructure As ParseNodeStructure) If _parseTree.IsAbstract(nodeStructure) OrElse Not nodeStructure.IsToken Then Return End If _writer.WriteLine(" Public Overrides Function WithLeadingTrivia(ByVal trivia As GreenNode) As GreenNode") _writer.Write(" Return new {0}", StructureTypeName(nodeStructure)) GenerateNodeStructureConstructorParameters(nodeStructure, "GetDiagnostics", "GetAnnotations", "trivia", "GetTrailingTrivia") _writer.WriteLine(" End Function") _writer.WriteLine() _writer.WriteLine(" Public Overrides Function WithTrailingTrivia(ByVal trivia As GreenNode) As GreenNode") _writer.Write(" Return new {0}", StructureTypeName(nodeStructure)) GenerateNodeStructureConstructorParameters(nodeStructure, "GetDiagnostics", "GetAnnotations", "GetLeadingTrivia", "trivia") _writer.WriteLine(" End Function") _writer.WriteLine() End Sub ' Generate GetChild, GetChildrenCount so members can be accessed by index Private Sub GenerateGetChild(nodeStructure As ParseNodeStructure) If _parseTree.IsAbstract(nodeStructure) OrElse nodeStructure.IsToken Then Return End If Dim allChildren = GetAllChildrenOfStructure(nodeStructure) Dim childrenCount = allChildren.Count If childrenCount = 0 Then Return End If _writer.WriteLine(" Friend Overrides Function GetSlot(i as Integer) as GreenNode") ' Create the property accessor for each of the children Dim children = allChildren If childrenCount <> 1 Then _writer.WriteLine(" Select case i") For i = 0 To childrenCount - 1 _writer.WriteLine(" Case {0}", i) _writer.WriteLine(" Return Me.{0}", ChildVarName(children(i))) Next _writer.WriteLine(" Case Else") _writer.WriteLine(" Debug.Assert(false, ""child index out of range"")") _writer.WriteLine(" Return Nothing") _writer.WriteLine(" End Select") Else _writer.WriteLine(" If i = 0 Then") _writer.WriteLine(" Return Me.{0}", ChildVarName(children(0))) _writer.WriteLine(" Else") _writer.WriteLine(" Debug.Assert(false, ""child index out of range"")") _writer.WriteLine(" Return Nothing") _writer.WriteLine(" End If") End If _writer.WriteLine(" End Function") _writer.WriteLine() '_writer.WriteLine(" Friend Overrides ReadOnly Property SlotCount() As Integer") '_writer.WriteLine(" Get") '_writer.WriteLine(" Return {0}", childrenCount) '_writer.WriteLine(" End Get") '_writer.WriteLine(" End Property") _writer.WriteLine() End Sub Private Sub GenerateNodeStructureMembers(nodeStructure As ParseNodeStructure) Dim fields = nodeStructure.Fields For Each field In fields _writer.WriteLine(" Friend ReadOnly {0} as {1}", FieldVarName(field), FieldTypeRef(field)) Next Dim children = nodeStructure.Children For Each child In children _writer.WriteLine(" Friend ReadOnly {0} as {1}", ChildVarName(child), ChildFieldTypeRef(child, True)) Next _writer.WriteLine() End Sub ' Generate constructor for a node structure Private Sub GenerateNodeStructureConstructor(nodeStructure As ParseNodeStructure, Optional noExtra As Boolean = False, Optional contextual As Boolean = False) ' these constructors are hardcoded If nodeStructure.IsTokenRoot OrElse nodeStructure.IsTriviaRoot OrElse nodeStructure.Name = "StructuredTriviaSyntax" Then Return End If If nodeStructure.ParentStructure Is Nothing Then Return End If Dim allFields = GetAllFieldsOfStructure(nodeStructure) _writer.Write(" Friend Sub New(") ' Generate each of the field parameters _writer.Write("ByVal kind As {0}", NodeKindType()) If Not noExtra Then _writer.Write(", ByVal errors as DiagnosticInfo(), ByVal annotations as SyntaxAnnotation()", NodeKindType()) End If If nodeStructure.IsTerminal Then ' terminals have a text _writer.Write(", text as String") End If If nodeStructure.IsToken Then ' tokens have trivia _writer.Write(", leadingTrivia As GreenNode, trailingTrivia As GreenNode", StructureTypeName(_parseTree.RootStructure)) End If For Each field In allFields _writer.Write(", ") GenerateNodeStructureFieldParameter(field) Next For Each child In GetAllChildrenOfStructure(nodeStructure) _writer.Write(", ") GenerateNodeStructureChildParameter(child, Nothing, True) Next If contextual Then _writer.Write(", context As ISyntaxFactoryContext") End If _writer.WriteLine(")") ' Generate each of the field parameters _writer.Write(" MyBase.New(kind", NodeKindType()) If Not noExtra Then _writer.Write(", errors, annotations") End If If nodeStructure.IsToken AndAlso Not nodeStructure.IsTokenRoot Then ' nonterminals have text. _writer.Write(", text") If Not nodeStructure.IsTrivia Then ' tokens have trivia, but only if they are not trivia. _writer.Write(", leadingTrivia, trailingTrivia") End If End If Dim baseClass = nodeStructure.ParentStructure If baseClass IsNot Nothing Then For Each child In GetAllChildrenOfStructure(baseClass) _writer.Write(", {0}", ChildParamName(child)) Next End If _writer.WriteLine(")") If Not nodeStructure.Abstract Then Dim allChildren = GetAllChildrenOfStructure(nodeStructure) Dim childrenCount = allChildren.Count If childrenCount <> 0 Then _writer.WriteLine(" Me.SlotCount = {0}", childrenCount) End If End If ' Generate code to initialize this class If contextual Then _writer.WriteLine(" Me.SetFactoryContext(context)") End If If allFields.Count > 0 Then For i = 0 To allFields.Count - 1 _writer.WriteLine(" Me.{0} = {1}", FieldVarName(allFields(i)), FieldParamName(allFields(i))) Next End If If nodeStructure.Children.Count > 0 Then '_writer.WriteLine(" Dim fullWidth as integer") _writer.WriteLine() For Each child In nodeStructure.Children Dim indent = "" If child.IsOptional OrElse child.IsList Then 'If endKeyword IsNot Nothing Then _writer.WriteLine(" If {0} IsNot Nothing Then", ChildParamName(child)) indent = " " End If '_writer.WriteLine("{0} fullWidth += {1}.FullWidth", indent, ChildParamName(child)) _writer.WriteLine("{0} AdjustFlagsAndWidth({1})", indent, ChildParamName(child)) _writer.WriteLine("{0} Me.{1} = {2}", indent, ChildVarName(child), ChildParamName(child)) If child.IsOptional OrElse child.IsList Then 'If endKeyword IsNot Nothing Then _writer.WriteLine(" End If", ChildParamName(child)) End If Next '_writer.WriteLine(" Me._fullWidth += fullWidth") _writer.WriteLine() End If 'TODO: BLUE If StructureTypeName(nodeStructure) = "DirectiveTriviaSyntax" Then _writer.WriteLine(" SetFlags(NodeFlags.ContainsDirectives)") End If If StructureTypeName(nodeStructure) = "AttributeSyntax" Then _writer.WriteLine(" SetFlags(NodeFlags.ContainsAttributes)") End If ' Generate End Sub _writer.WriteLine(" End Sub") _writer.WriteLine() End Sub Private Sub GenerateNodeStructureConstructorParameters(nodeStructure As ParseNodeStructure, errorParam As String, annotationParam As String, precedingTriviaParam As String, followingTriviaParam As String) ' Generate each of the field parameters _writer.Write("(Me.Kind") _writer.Write(", {0}", errorParam) _writer.Write(", {0}", annotationParam) If nodeStructure.IsToken Then ' nonterminals have text. _writer.Write(", text") If Not nodeStructure.IsTrivia Then ' tokens have trivia, but only if they are not trivia. _writer.Write(", {0}, {1}", precedingTriviaParam, followingTriviaParam) End If ElseIf nodeStructure.IsTrivia AndAlso nodeStructure.IsTriviaRoot Then _writer.Write(", Me.Text") End If For Each field In GetAllFieldsOfStructure(nodeStructure) _writer.Write(", {0}", FieldVarName(field)) Next For Each child In GetAllChildrenOfStructure(nodeStructure) _writer.Write(", {0}", ChildVarName(child)) Next _writer.WriteLine(")") End Sub ' Generate a parameter corresponding to a node structure field Private Sub GenerateNodeStructureFieldParameter(field As ParseNodeField, Optional conflictName As String = Nothing) _writer.Write("{0} As {1}", FieldParamName(field, conflictName), FieldTypeRef(field)) End Sub ' Generate a parameter corresponding to a node structure child Private Sub GenerateNodeStructureChildParameter(child As ParseNodeChild, Optional conflictName As String = Nothing, Optional isGreen As Boolean = False) _writer.Write("{0} As {1}", ChildParamName(child, conflictName), ChildConstructorTypeRef(child, isGreen)) End Sub ' Get modifiers Private Function GetModifiers(containingStructure As ParseNodeStructure, isOverride As Boolean, name As String) As String ' Is this overridable or an override? Dim modifiers = "" 'If isOverride Then ' modifiers = "Overrides " 'ElseIf containingStructure.HasDerivedStructure Then ' modifiers = "Overridable " 'End If ' Put Shadows modifier on if useful. ' Object has Equals and GetType ' root name has members for every kind and structure (factory methods) If (name = "Equals" OrElse name = "GetType") Then 'OrElse _parseTree.NodeKinds.ContainsKey(name) OrElse _parseTree.NodeStructures.ContainsKey(name)) Then modifiers = "Shadows " + modifiers End If Return modifiers End Function ' Generate a public property for a node field Private Sub GenerateNodeFieldProperty(field As ParseNodeField, fieldIndex As Integer, isOverride As Boolean) ' XML comment GenerateXmlComment(_writer, field, 8) _writer.WriteLine(" Friend {2}ReadOnly Property {0} As {1}", FieldPropertyName(field), FieldTypeRef(field), GetModifiers(field.ContainingStructure, isOverride, field.Name)) _writer.WriteLine(" Get") _writer.WriteLine(" Return Me.{0}", FieldVarName(field)) _writer.WriteLine(" End Get") _writer.WriteLine(" End Property") _writer.WriteLine("") End Sub ' Generate a public property for a child Private Sub GenerateNodeChildProperty(node As ParseNodeStructure, child As ParseNodeChild, childIndex As Integer) ' XML comment GenerateXmlComment(_writer, child, 8) Dim isToken = KindTypeStructure(child.ChildKind).IsToken _writer.WriteLine(" Friend {2}ReadOnly Property {0} As {1}", ChildPropertyName(child), ChildPropertyTypeRef(node, child, True), GetModifiers(child.ContainingStructure, False, child.Name)) _writer.WriteLine(" Get") If Not child.IsList Then _writer.WriteLine(" Return Me.{0}", ChildVarName(child)) ElseIf child.IsSeparated Then _writer.WriteLine(" Return new {0}(New Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(of {1})(Me.{2}))", ChildPropertyTypeRef(node, child, True), BaseTypeReference(child), ChildVarName(child)) ElseIf KindTypeStructure(child.ChildKind).IsToken Then _writer.WriteLine(" Return New Microsoft.CodeAnalysis.Syntax.InternalSyntax.SyntaxList(of GreenNode)(Me.{1})", BaseTypeReference(child), ChildVarName(child)) Else _writer.WriteLine(" Return new {0}(Me.{1})", ChildPropertyTypeRef(node, child, True), ChildVarName(child)) End If _writer.WriteLine(" End Get") _writer.WriteLine(" End Property") _writer.WriteLine("") End Sub ' Generate a public property for a child Private Sub GenerateNodeWithChildProperty(withChild As ParseNodeChild, childIndex As Integer, nodeStructure As ParseNodeStructure) Dim isOverride As Boolean = withChild.ContainingStructure IsNot nodeStructure If withChild.GenerateWith Then Dim isAbstract As Boolean = _parseTree.IsAbstract(nodeStructure) If Not isAbstract Then ' XML comment GenerateWithXmlComment(_writer, withChild, 8) _writer.WriteLine(" Friend {2}Function {0}({3} as {4}) As {1}", ChildWithFunctionName(withChild), StructureTypeName(withChild.ContainingStructure), GetModifiers(withChild.ContainingStructure, isOverride, withChild.Name), Ident(UpperFirstCharacter(withChild.Name)), ChildConstructorTypeRef(withChild)) _writer.WriteLine(" Ensures(Result(Of {0}) IsNot Nothing)", StructureTypeName(withChild.ContainingStructure)) _writer.Write(" return New {0}(", StructureTypeName(nodeStructure)) _writer.Write("Kind, Green.Errors") Dim allFields = GetAllFieldsOfStructure(nodeStructure) If allFields.Count > 0 Then For i = 0 To allFields.Count - 1 _writer.Write(", {0}", FieldParamName(allFields(i))) Next End If For Each child In nodeStructure.Children If child IsNot withChild Then _writer.Write(", {0}", ChildParamName(child)) Else _writer.Write(", {0}", Ident(UpperFirstCharacter(child.Name))) End If Next _writer.WriteLine(")") _writer.WriteLine(" End Function") ElseIf nodeStructure.Children.Contains(withChild) Then ' XML comment GenerateWithXmlComment(_writer, withChild, 8) _writer.WriteLine(" Friend {2} Function {0}({3} as {4}) As {1}", ChildWithFunctionName(withChild), StructureTypeName(withChild.ContainingStructure), "MustOverride", Ident(UpperFirstCharacter(withChild.Name)), ChildConstructorTypeRef(withChild)) End If _writer.WriteLine("") End If End Sub ' Generate public properties for a child that is a separated list Private Sub GenerateAccept(nodeStructure As ParseNodeStructure) If nodeStructure.ParentStructure IsNot Nothing AndAlso (_parseTree.IsAbstract(nodeStructure) OrElse nodeStructure.IsToken OrElse nodeStructure.IsTrivia) Then Return End If _writer.WriteLine(" Public {0} Function Accept(ByVal visitor As {1}) As VisualBasicSyntaxNode", If(IsRoot(nodeStructure), "Overridable", "Overrides"), _parseTree.VisitorName) _writer.WriteLine(" Return visitor.{0}(Me)", VisitorMethodName(nodeStructure)) _writer.WriteLine(" End Function") _writer.WriteLine() End Sub ' Generate special methods and properties for the root node. These only appear in the root node. Private Sub GenerateRootNodeSpecialMethods(nodeStructure As ParseNodeStructure) _writer.WriteLine() End Sub ' Generate the Visitor class definition Private Sub GenerateVisitorClass() _writer.WriteLine(" Friend MustInherit Class {0}", Ident(_parseTree.VisitorName)) ' Basic Visit method that dispatches. _writer.WriteLine(" Public Overridable Function Visit(ByVal node As {0}) As VisualBasicSyntaxNode", StructureTypeName(_parseTree.RootStructure)) _writer.WriteLine(" If node IsNot Nothing") _writer.WriteLine(" Return node.Accept(Me)") _writer.WriteLine(" Else") _writer.WriteLine(" Return Nothing") _writer.WriteLine(" End If") _writer.WriteLine(" End Function") For Each nodeStructure In _parseTree.NodeStructures.Values GenerateVisitorMethod(nodeStructure) Next _writer.WriteLine(" End Class") _writer.WriteLine() End Sub ' Generate a method in the Visitor class Private Sub GenerateVisitorMethod(nodeStructure As ParseNodeStructure) If nodeStructure.IsToken OrElse nodeStructure.IsTrivia Then Return End If Dim methodName = VisitorMethodName(nodeStructure) Dim structureName = StructureTypeName(nodeStructure) _writer.WriteLine(" Public Overridable Function {0}(ByVal node As {1}) As VisualBasicSyntaxNode", methodName, structureName) _writer.WriteLine(" Debug.Assert(node IsNot Nothing)") If Not IsRoot(nodeStructure) Then _writer.WriteLine(" Return {0}(node)", VisitorMethodName(nodeStructure.ParentStructure)) Else _writer.WriteLine(" Return node") End If _writer.WriteLine(" End Function") End Sub ' Generate the RewriteVisitor class definition Private Sub GenerateRewriteVisitorClass() _writer.WriteLine(" Friend MustInherit Class {0}", Ident(_parseTree.RewriteVisitorName)) _writer.WriteLine(" Inherits {0}", Ident(_parseTree.VisitorName), StructureTypeName(_parseTree.RootStructure)) _writer.WriteLine() For Each nodeStructure In _parseTree.NodeStructures.Values GenerateRewriteVisitorMethod(nodeStructure) Next _writer.WriteLine(" End Class") _writer.WriteLine() End Sub ' Generate a method in the RewriteVisitor class Private Sub GenerateRewriteVisitorMethod(nodeStructure As ParseNodeStructure) If nodeStructure.IsToken OrElse nodeStructure.IsTrivia Then Return End If If nodeStructure.Abstract Then ' do nothing for abstract nodes Return End If Dim methodName = VisitorMethodName(nodeStructure) Dim structureName = StructureTypeName(nodeStructure) _writer.WriteLine(" Public Overrides Function {0}(ByVal node As {1}) As {2}", methodName, structureName, StructureTypeName(_parseTree.RootStructure)) ' non-abstract non-terminals need to rewrite their children and recreate as needed. Dim allFields = GetAllFieldsOfStructure(nodeStructure) Dim allChildren = GetAllChildrenOfStructure(nodeStructure) ' create anyChanges variable _writer.WriteLine(" Dim anyChanges As Boolean = False") _writer.WriteLine() ' visit all children For i = 0 To allChildren.Count - 1 If allChildren(i).IsList Then _writer.WriteLine(" Dim {0} = VisitList(node.{1})" + Environment.NewLine + " If node.{2} IsNot {0}.Node Then anyChanges = True", ChildNewVarName(allChildren(i)), ChildPropertyName(allChildren(i)), ChildVarName(allChildren(i))) ElseIf KindTypeStructure(allChildren(i).ChildKind).IsToken Then _writer.WriteLine(" Dim {0} = DirectCast(Visit(node.{2}), {1})" + Environment.NewLine + " If node.{3} IsNot {0} Then anyChanges = True", ChildNewVarName(allChildren(i)), BaseTypeReference(allChildren(i)), ChildPropertyName(allChildren(i)), ChildVarName(allChildren(i))) Else _writer.WriteLine(" Dim {0} = DirectCast(Visit(node.{2}), {1})" + Environment.NewLine + " If node.{2} IsNot {0} Then anyChanges = True", ChildNewVarName(allChildren(i)), ChildPropertyTypeRef(nodeStructure, allChildren(i)), ChildVarName(allChildren(i))) End If Next _writer.WriteLine() ' check if any changes. _writer.WriteLine(" If anyChanges Then") _writer.Write(" Return New {0}(node.Kind", StructureTypeName(nodeStructure)) _writer.Write(", node.GetDiagnostics, node.GetAnnotations") For Each field In allFields _writer.Write(", node.{0}", FieldPropertyName(field)) Next For Each child In allChildren If child.IsList Then _writer.Write(", {0}.Node", ChildNewVarName(child)) ElseIf KindTypeStructure(child.ChildKind).IsToken Then _writer.Write(", {0}", ChildNewVarName(child)) Else _writer.Write(", {0}", ChildNewVarName(child)) End If Next _writer.WriteLine(")") _writer.WriteLine(" Else") _writer.WriteLine(" Return node") _writer.WriteLine(" End If") _writer.WriteLine(" End Function") _writer.WriteLine() End Sub End Class