|
' 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.
Imports System.Collections.Immutable
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeGeneration
Imports Microsoft.CodeAnalysis.Editing
Imports Microsoft.CodeAnalysis.Host
Imports Microsoft.CodeAnalysis.LanguageService
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.LanguageService
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Friend NotInheritable Class VisualBasicCodeGenerationService
Inherits AbstractCodeGenerationService(Of VisualBasicCodeGenerationContextInfo)
Public Sub New(languageServices As LanguageServices)
MyBase.New(languageServices)
End Sub
Public Overrides ReadOnly Property DefaultOptions As CodeGenerationOptions
Get
Return VisualBasicCodeGenerationOptions.Default
End Get
End Property
Public Overrides Function GetCodeGenerationOptions(options As IOptionsReader) As CodeGenerationOptions
Return New VisualBasicCodeGenerationOptions(options)
End Function
Public Overrides Function GetInfo(context As CodeGenerationContext, options As CodeGenerationOptions, parseOptions As ParseOptions) As VisualBasicCodeGenerationContextInfo
Return New VisualBasicCodeGenerationContextInfo(context, DirectCast(options, VisualBasicCodeGenerationOptions), Me)
End Function
Public Overloads Overrides Function GetDestination(containerNode As SyntaxNode) As CodeGenerationDestination
Return VisualBasicCodeGenerationHelpers.GetDestination(containerNode)
End Function
Protected Overrides Function GetMemberComparer() As IComparer(Of SyntaxNode)
Return VisualBasicDeclarationComparer.WithoutNamesInstance
End Function
Protected Overrides Function GetAvailableInsertionIndices(destination As SyntaxNode, cancellationToken As CancellationToken) As IList(Of Boolean)
' NOTE(cyrusn): We know that the destination overlaps some hidden regions.
If TypeOf destination Is TypeBlockSyntax Then
Return DirectCast(destination, TypeBlockSyntax).GetInsertionIndices(cancellationToken)
End If
If TypeOf destination Is CompilationUnitSyntax Then
Return GetAvailableInsertionIndices(DirectCast(destination, CompilationUnitSyntax), cancellationToken)
End If
' TODO(cyrusn): This will exclude all non-type-blocks if they overlap a hidden region.
' For example, for enums or namespaces. We could consider relaxing that and actually
' attempting to determine where in the destination are viable, if we think it's worth
' it.
Return Nothing
End Function
Private Overloads Shared Function GetAvailableInsertionIndices(destination As CompilationUnitSyntax, cancellationToken As CancellationToken) As IList(Of Boolean)
Dim members = destination.Members
Dim indices = New List(Of Boolean)
If members.Count >= 1 Then
' First, see if we can insert between the start of the typeblock, and it's first
' member.
indices.Add(Not destination.OverlapsHiddenPosition(TextSpan.FromBounds(0, destination.Members.First.SpanStart), cancellationToken))
' Now, walk between each member and see if something can be inserted between it and
' the next member
For i = 0 To members.Count - 2
Dim member1 = members(i)
Dim member2 = members(i + 1)
indices.Add(Not destination.OverlapsHiddenPosition(member1, member2, cancellationToken))
Next
' Last, see if we can insert between the last member and the end of the typeblock
indices.Add(Not destination.OverlapsHiddenPosition(
TextSpan.FromBounds(destination.Members.Last.Span.End, destination.EndOfFileToken.SpanStart), cancellationToken))
End If
Return indices
End Function
Protected Overrides Function AddEvent(Of TDeclarationNode As SyntaxNode)(
destinationType As TDeclarationNode,
[event] As IEventSymbol,
options As VisualBasicCodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As TDeclarationNode
CheckDeclarationNode(Of TypeBlockSyntax)(destinationType)
Return Cast(Of TDeclarationNode)(AddEventTo(Cast(Of TypeBlockSyntax)(destinationType), [event], options, availableIndices))
End Function
Protected Overrides Function AddField(Of TDeclarationNode As SyntaxNode)(
destinationType As TDeclarationNode,
field As IFieldSymbol,
options As VisualBasicCodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As TDeclarationNode
CheckDeclarationNode(Of EnumBlockSyntax, TypeBlockSyntax, CompilationUnitSyntax)(destinationType)
If TypeOf destinationType Is EnumBlockSyntax Then
Return Cast(Of TDeclarationNode)(EnumMemberGenerator.AddEnumMemberTo(Cast(Of EnumBlockSyntax)(destinationType), field, options))
ElseIf TypeOf destinationType Is TypeBlockSyntax Then
Return Cast(Of TDeclarationNode)(FieldGenerator.AddFieldTo(Cast(Of TypeBlockSyntax)(destinationType), field, options, availableIndices))
Else
Return Cast(Of TDeclarationNode)(FieldGenerator.AddFieldTo(Cast(Of CompilationUnitSyntax)(destinationType), field, options, availableIndices))
End If
End Function
Protected Overrides Function AddProperty(Of TDeclarationNode As SyntaxNode)(
destinationType As TDeclarationNode,
[property] As IPropertySymbol,
options As VisualBasicCodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As TDeclarationNode
CheckDeclarationNode(Of TypeBlockSyntax, CompilationUnitSyntax)(destinationType)
If TypeOf destinationType Is TypeBlockSyntax Then
Return Cast(Of TDeclarationNode)(PropertyGenerator.AddPropertyTo(Cast(Of TypeBlockSyntax)(destinationType), [property], options, availableIndices))
Else
Return Cast(Of TDeclarationNode)(PropertyGenerator.AddPropertyTo(Cast(Of CompilationUnitSyntax)(destinationType), [property], options, availableIndices))
End If
End Function
Protected Overrides Function AddMethod(Of TDeclarationNode As SyntaxNode)(
destination As TDeclarationNode,
method As IMethodSymbol,
options As VisualBasicCodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As TDeclarationNode
CheckDeclarationNode(Of TypeBlockSyntax, CompilationUnitSyntax, NamespaceBlockSyntax)(destination)
' Synthesized methods for properties/events are not things we actually generate
' declarations for.
If method.AssociatedSymbol IsNot Nothing Then
Return destination
End If
Dim typeDeclaration As TypeBlockSyntax = TryCast(destination, TypeBlockSyntax)
If typeDeclaration IsNot Nothing Then
If method.IsConstructor() Then
Return Cast(Of TDeclarationNode)(ConstructorGenerator.AddConstructorTo(typeDeclaration, method, options, availableIndices))
End If
If method.MethodKind = MethodKind.UserDefinedOperator Then
Return Cast(Of TDeclarationNode)(OperatorGenerator.AddOperatorTo(typeDeclaration, method, options, availableIndices))
End If
If method.MethodKind = MethodKind.Conversion Then
Return Cast(Of TDeclarationNode)(ConversionGenerator.AddConversionTo(typeDeclaration, method, options, availableIndices))
End If
Return Cast(Of TDeclarationNode)(MethodGenerator.AddMethodTo(typeDeclaration, method, options, availableIndices))
End If
If method.IsConstructor() Then
Return destination
End If
Dim compilationUnit = TryCast(destination, CompilationUnitSyntax)
If compilationUnit IsNot Nothing Then
Return Cast(Of TDeclarationNode)(MethodGenerator.AddMethodTo(compilationUnit, method, options, availableIndices))
End If
Dim ns = Cast(Of NamespaceBlockSyntax)(destination)
Return Cast(Of TDeclarationNode)(MethodGenerator.AddMethodTo(ns, method, options, availableIndices))
End Function
Protected Overloads Overrides Function AddNamedType(Of TDeclarationNode As SyntaxNode)(
destination As TDeclarationNode,
namedType As INamedTypeSymbol,
options As VisualBasicCodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As TDeclarationNode
CheckDeclarationNode(Of TypeBlockSyntax, NamespaceBlockSyntax, CompilationUnitSyntax)(destination)
If TypeOf destination Is TypeBlockSyntax Then
Return Cast(Of TDeclarationNode)(NamedTypeGenerator.AddNamedTypeTo(Me, Cast(Of TypeBlockSyntax)(destination), namedType, options, availableIndices, cancellationToken))
ElseIf TypeOf destination Is NamespaceBlockSyntax Then
Return Cast(Of TDeclarationNode)(NamedTypeGenerator.AddNamedTypeTo(Me, Cast(Of NamespaceBlockSyntax)(destination), namedType, options, availableIndices, cancellationToken))
Else
Return Cast(Of TDeclarationNode)(NamedTypeGenerator.AddNamedTypeTo(Me, Cast(Of CompilationUnitSyntax)(destination), namedType, options, availableIndices, cancellationToken))
End If
End Function
Protected Overrides Function AddNamespace(Of TDeclarationNode As SyntaxNode)(
destination As TDeclarationNode,
[namespace] As INamespaceSymbol,
options As VisualBasicCodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As TDeclarationNode
CheckDeclarationNode(Of CompilationUnitSyntax, NamespaceBlockSyntax)(destination)
If TypeOf destination Is CompilationUnitSyntax Then
Return Cast(Of TDeclarationNode)(NamespaceGenerator.AddNamespaceTo(Me, Cast(Of CompilationUnitSyntax)(destination), [namespace], options, availableIndices, cancellationToken))
Else
Return Cast(Of TDeclarationNode)(NamespaceGenerator.AddNamespaceTo(Me, Cast(Of NamespaceBlockSyntax)(destination), [namespace], options, availableIndices, cancellationToken))
End If
End Function
Public Overrides Function AddParameters(Of TDeclarationNode As SyntaxNode)(
destinationMember As TDeclarationNode,
parameters As IEnumerable(Of IParameterSymbol),
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TDeclarationNode
Dim methodBlock = TryCast(destinationMember, MethodBlockBaseSyntax)
Dim methodStatement = If(methodBlock IsNot Nothing,
methodBlock.BlockStatement,
TryCast(destinationMember, MethodBaseSyntax))
If methodStatement IsNot Nothing Then
Select Case methodStatement.Kind
Case SyntaxKind.GetAccessorStatement, SyntaxKind.SetAccessorStatement
' Don't allow adding parameters to Property Getter/Setter
Return destinationMember
Case Else
Return AddParametersToMethod(Of TDeclarationNode)(methodStatement, methodBlock, parameters, options, cancellationToken)
End Select
Else
Dim propertyBlock = TryCast(destinationMember, PropertyBlockSyntax)
If propertyBlock IsNot Nothing Then
Return AddParametersToProperty(Of TDeclarationNode)(propertyBlock, parameters, options, cancellationToken)
End If
End If
Return destinationMember
End Function
Protected Overrides Function AddMembers(Of TDeclarationNode As SyntaxNode)(destination As TDeclarationNode, members As IEnumerable(Of SyntaxNode)) As TDeclarationNode
CheckDeclarationNode(Of EnumBlockSyntax, TypeBlockSyntax, NamespaceBlockSyntax, CompilationUnitSyntax)(destination)
If TypeOf destination Is EnumBlockSyntax Then
Return Cast(Of TDeclarationNode)(Cast(Of EnumBlockSyntax)(destination).AddMembers(members.Cast(Of EnumMemberDeclarationSyntax).ToArray()))
ElseIf TypeOf destination Is TypeBlockSyntax Then
Return Cast(Of TDeclarationNode)(Cast(Of TypeBlockSyntax)(destination).AddMembers(members.Cast(Of StatementSyntax).ToArray()))
ElseIf TypeOf destination Is NamespaceBlockSyntax Then
Return Cast(Of TDeclarationNode)(Cast(Of NamespaceBlockSyntax)(destination).AddMembers(members.Cast(Of StatementSyntax).ToArray()))
Else
Return Cast(Of TDeclarationNode)(Cast(Of CompilationUnitSyntax)(destination).AddMembers(members.Cast(Of StatementSyntax).ToArray()))
End If
End Function
Private Overloads Function AddParametersToMethod(Of TDeclarationNode As SyntaxNode)(
methodStatement As MethodBaseSyntax,
methodBlock As MethodBlockBaseSyntax,
parameters As IEnumerable(Of IParameterSymbol),
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TDeclarationNode
Dim finalStatement = AddParameterToMethodBase(methodStatement, parameters, options, cancellationToken)
Dim result As StatementSyntax
If methodBlock IsNot Nothing Then
Select Case methodBlock.Kind
Case SyntaxKind.SubBlock,
SyntaxKind.FunctionBlock
result = DirectCast(methodBlock, MethodBlockSyntax).WithBlockStatement(DirectCast(finalStatement, MethodStatementSyntax))
Case SyntaxKind.ConstructorBlock
result = DirectCast(methodBlock, ConstructorBlockSyntax).WithBlockStatement(DirectCast(finalStatement, SubNewStatementSyntax))
Case SyntaxKind.GetAccessorBlock,
SyntaxKind.SetAccessorBlock,
SyntaxKind.AddHandlerAccessorBlock,
SyntaxKind.RemoveHandlerAccessorBlock,
SyntaxKind.RaiseEventAccessorBlock
result = DirectCast(methodBlock, AccessorBlockSyntax).WithBlockStatement(DirectCast(finalStatement, AccessorStatementSyntax))
Case Else
result = DirectCast(methodBlock, OperatorBlockSyntax).WithBlockStatement(DirectCast(finalStatement, OperatorStatementSyntax))
End Select
Else
result = finalStatement
End If
Return DirectCast(DirectCast(result, Object), TDeclarationNode)
End Function
Private Overloads Function AddParametersToProperty(Of TDeclarationNode As SyntaxNode)(
propertyBlock As PropertyBlockSyntax,
parameters As IEnumerable(Of IParameterSymbol),
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TDeclarationNode
Dim propertyStatement = propertyBlock.PropertyStatement
Dim newPropertyStatement = AddParameterToMethodBase(propertyStatement, parameters, options, cancellationToken)
Dim newPropertyBlock As SyntaxNode = propertyBlock.WithPropertyStatement(newPropertyStatement)
Return DirectCast(newPropertyBlock, TDeclarationNode)
End Function
Private Overloads Function AddParameterToMethodBase(Of TMethodBase As MethodBaseSyntax)(
methodBase As TMethodBase,
parameters As IEnumerable(Of IParameterSymbol),
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TMethodBase
Dim parameterList = methodBase.ParameterList
Dim parameterCount = If(parameterList IsNot Nothing, parameterList.Parameters.Count, 0)
Dim seenOptional = parameterCount > 0 AndAlso parameterList.Parameters(parameterCount - 1).Default IsNot Nothing
Dim editor = New SyntaxEditor(methodBase, Me.LanguageServices.SolutionServices)
For Each parameter In parameters
Dim parameterSyntax = ParameterGenerator.GenerateParameter(parameter, seenOptional, options)
AddParameterEditor.AddParameter(
VisualBasicSyntaxFacts.Instance,
editor,
methodBase,
parameterCount,
parameterSyntax,
cancellationToken)
seenOptional = seenOptional OrElse parameterSyntax.Default IsNot Nothing
parameterCount += 1
Next
Return DirectCast(editor.GetChangedRoot(), TMethodBase)
End Function
Public Overrides Function AddAttributes(Of TDeclarationNode As SyntaxNode)(
destination As TDeclarationNode,
attributes As IEnumerable(Of AttributeData),
target As SyntaxToken?,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TDeclarationNode
If target.HasValue AndAlso Not target.Value.IsValidAttributeTarget() Then
Throw New ArgumentException(NameOf(target))
End If
Dim attributeSyntaxList = AttributeGenerator.GenerateAttributeBlocks(attributes.ToImmutableArray(), options, target)
' Handle most cases
Dim member = TryCast(destination, StatementSyntax)
If member IsNot Nothing Then
Return Cast(Of TDeclarationNode)(member.AddAttributeLists(attributeSyntaxList.ToArray()))
End If
' Handle global attributes
Dim compilationUnit = TryCast(destination, CompilationUnitSyntax)
If compilationUnit IsNot Nothing Then
Return Cast(Of TDeclarationNode)(compilationUnit.AddAttributes(SyntaxFactory.AttributesStatement(attributeSyntaxList)))
End If
' Handle parameters
Dim parameter = TryCast(destination, ParameterSyntax)
If parameter IsNot Nothing Then
Return Cast(Of TDeclarationNode)(parameter.AddAttributeLists(attributeSyntaxList.ToArray()))
End If
Return destination
End Function
Public Overrides Function RemoveAttribute(Of TDeclarationNode As SyntaxNode)(destination As TDeclarationNode, attributeToRemove As AttributeData, options As VisualBasicCodeGenerationContextInfo, cancellationToken As CancellationToken) As TDeclarationNode
If attributeToRemove.ApplicationSyntaxReference Is Nothing Then
Throw New ArgumentException(NameOf(attributeToRemove))
End If
Dim attributeSyntaxToRemove = attributeToRemove.ApplicationSyntaxReference.GetSyntax(cancellationToken)
Return RemoveAttribute(destination, attributeSyntaxToRemove, options, cancellationToken)
End Function
Public Overrides Function RemoveAttribute(Of TDeclarationNode As SyntaxNode)(destination As TDeclarationNode, attributeToRemove As SyntaxNode, options As VisualBasicCodeGenerationContextInfo, cancellationToken As CancellationToken) As TDeclarationNode
If attributeToRemove Is Nothing Then
Throw New ArgumentException(NameOf(attributeToRemove))
End If
' Removed node could be AttributeSyntax or AttributeListSyntax.
Dim attributeRemoved As Boolean = False
Dim positionOfRemovedNode As Integer = -1
Dim triviaOfRemovedNode As SyntaxTriviaList = Nothing
' Handle most cases
Dim member = TryCast(destination, StatementSyntax)
If member IsNot Nothing Then
Dim newAttributeLists = RemoveAttributeFromAttributeLists(member.GetAttributes(), attributeToRemove, attributeRemoved, positionOfRemovedNode, triviaOfRemovedNode)
VerifyAttributeRemoved(attributeRemoved)
Dim newMember = member.WithAttributeLists(newAttributeLists)
Return Cast(Of TDeclarationNode)(AppendTriviaAtPosition(newMember, positionOfRemovedNode - destination.FullSpan.Start, triviaOfRemovedNode))
End If
' Handle global attributes
Dim compilationUnit = TryCast(destination, CompilationUnitSyntax)
If compilationUnit IsNot Nothing Then
Dim attributeStatements = compilationUnit.Attributes
Dim newAttributeStatements = RemoveAttributeFromAttributeStatements(attributeStatements, attributeToRemove, attributeRemoved, positionOfRemovedNode, triviaOfRemovedNode)
VerifyAttributeRemoved(attributeRemoved)
Dim newCompilationUnit = compilationUnit.WithAttributes(newAttributeStatements)
Return Cast(Of TDeclarationNode)(AppendTriviaAtPosition(newCompilationUnit, positionOfRemovedNode - destination.FullSpan.Start, triviaOfRemovedNode))
End If
' Handle parameters
Dim parameter = TryCast(destination, ParameterSyntax)
If parameter IsNot Nothing Then
Dim newAttributeLists = RemoveAttributeFromAttributeLists(parameter.AttributeLists, attributeToRemove, attributeRemoved, positionOfRemovedNode, triviaOfRemovedNode)
VerifyAttributeRemoved(attributeRemoved)
Dim newParameter = parameter.WithAttributeLists(newAttributeLists)
Return Cast(Of TDeclarationNode)(AppendTriviaAtPosition(newParameter, positionOfRemovedNode - destination.FullSpan.Start, triviaOfRemovedNode))
End If
Return destination
End Function
Private Shared Function RemoveAttributeFromAttributeLists(attributeLists As SyntaxList(Of AttributeListSyntax), attributeToRemove As SyntaxNode,
<Out> ByRef attributeRemoved As Boolean, <Out> ByRef positionOfRemovedNode As Integer, <Out> ByRef triviaOfRemovedNode As SyntaxTriviaList) As SyntaxList(Of AttributeListSyntax)
For Each attributeList In attributeLists
Dim attributes = attributeList.Attributes
If attributes.Any(Function(a) a Is attributeToRemove) Then
attributeRemoved = True
Dim trivia As IEnumerable(Of SyntaxTrivia) = Nothing
Dim newAttributeLists As IEnumerable(Of AttributeListSyntax) = Nothing
If attributes.Count = 1 Then
' Remove the entire attribute list.
ComputePositionAndTriviaForRemoveAttributeList(attributeList, Function(t As SyntaxTrivia) t.IsKind(SyntaxKind.EndOfLineTrivia), positionOfRemovedNode, trivia)
newAttributeLists = attributeLists.Where(Function(aList) aList IsNot attributeList)
Else
' Remove just the given attribute from the attribute list.
ComputePositionAndTriviaForRemoveAttributeFromAttributeList(attributeToRemove, Function(t As SyntaxToken) t.IsKind(SyntaxKind.CommaToken), positionOfRemovedNode, trivia)
Dim newAttributes = SyntaxFactory.SeparatedList(attributes.Where(Function(a) a IsNot attributeToRemove))
Dim newAttributeList = attributeList.WithAttributes(newAttributes)
newAttributeLists = attributeLists.Select(Function(attrList) If(attrList Is attributeList, newAttributeList, attrList))
End If
triviaOfRemovedNode = trivia.ToSyntaxTriviaList()
Return SyntaxFactory.List(newAttributeLists)
End If
Next
attributeRemoved = False
Return attributeLists
End Function
Private Shared Function RemoveAttributeFromAttributeStatements(attributeStatements As SyntaxList(Of AttributesStatementSyntax), attributeToRemove As SyntaxNode,
<Out> ByRef attributeRemoved As Boolean, <Out> ByRef positionOfRemovedNode As Integer, <Out> ByRef triviaOfRemovedNode As SyntaxTriviaList) As SyntaxList(Of AttributesStatementSyntax)
For Each attributeStatement In attributeStatements
Dim attributeLists = attributeStatement.AttributeLists
Dim newAttributeLists = RemoveAttributeFromAttributeLists(attributeLists, attributeToRemove, attributeRemoved, positionOfRemovedNode, triviaOfRemovedNode)
If attributeRemoved Then
Dim newAttributeStatement = attributeStatement.WithAttributeLists(newAttributeLists)
Return SyntaxFactory.List(attributeStatements.Select(Function(attrStatement) If(attrStatement Is attributeStatement, newAttributeStatement, attrStatement)))
End If
Next
attributeRemoved = False
Return attributeStatements
End Function
Private Shared Sub VerifyAttributeRemoved(attributeRemoved As Boolean)
If Not attributeRemoved Then
Throw New ArgumentException("attributeToRemove")
End If
End Sub
Public Overrides Function AddStatements(Of TDeclarationNode As SyntaxNode)(
destinationMember As TDeclarationNode,
statements As IEnumerable(Of SyntaxNode),
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TDeclarationNode
Dim methodBlock = TryCast(destinationMember, MethodBlockBaseSyntax)
If methodBlock IsNot Nothing Then
Dim allStatements = methodBlock.Statements.Concat(StatementGenerator.GenerateStatements(statements))
Dim result As Object
Select Case methodBlock.Kind
Case SyntaxKind.SubBlock,
SyntaxKind.FunctionBlock
result = DirectCast(methodBlock, MethodBlockSyntax).WithStatements(SyntaxFactory.List(allStatements))
Case SyntaxKind.ConstructorBlock
result = DirectCast(methodBlock, ConstructorBlockSyntax).WithStatements(SyntaxFactory.List(allStatements))
Case SyntaxKind.OperatorBlock
result = DirectCast(methodBlock, OperatorBlockSyntax).WithStatements(SyntaxFactory.List(allStatements))
Case Else
result = DirectCast(methodBlock, AccessorBlockSyntax).WithStatements(SyntaxFactory.List(allStatements))
End Select
Return DirectCast(DirectCast(result, Object), TDeclarationNode)
Else
Return AddStatementsWorker(destinationMember, statements, options, cancellationToken)
End If
End Function
Private Shared Function AddStatementsWorker(Of TDeclarationNode As SyntaxNode)(
destinationMember As TDeclarationNode,
statements As IEnumerable(Of SyntaxNode),
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As TDeclarationNode
Dim location = options.Context.BestLocation
CheckLocation(destinationMember, location)
Dim token = location.FindToken(cancellationToken)
Dim oldBlock = token.Parent.GetContainingMultiLineExecutableBlocks().First
Dim oldBlockStatements = oldBlock.GetExecutableBlockStatements()
Dim oldBlockStatementsSet = oldBlockStatements.ToSet()
Dim oldStatement = token.Parent.GetAncestorsOrThis(Of StatementSyntax)().First(AddressOf oldBlockStatementsSet.Contains)
Dim oldStatementIndex = oldBlockStatements.IndexOf(oldStatement)
Dim statementArray = statements.OfType(Of StatementSyntax).ToArray()
Dim newBlock As SyntaxNode
If options.Context.BeforeThisLocation IsNot Nothing Then
Dim strippedTrivia As ImmutableArray(Of SyntaxTrivia) = Nothing
Dim newStatement = VisualBasicFileBannerFacts.Instance.GetNodeWithoutLeadingBannerAndPreprocessorDirectives(
oldStatement, strippedTrivia)
statementArray(0) = statementArray(0).WithLeadingTrivia(strippedTrivia)
newBlock = oldBlock.ReplaceNode(oldStatement, newStatement)
newBlock = newBlock.ReplaceStatements(newBlock.GetExecutableBlockStatements().InsertRange(oldStatementIndex, statementArray))
Else
newBlock = oldBlock.ReplaceStatements(oldBlockStatements.InsertRange(oldStatementIndex + 1, statementArray))
End If
Return destinationMember.ReplaceNode(oldBlock, newBlock)
End Function
' TODO Change to Not return null (https://github.com/dotnet/roslyn/issues/58243)
Public Overrides Function CreateMethodDeclaration(method As IMethodSymbol,
destination As CodeGenerationDestination,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
' Synthesized methods for properties/events are not things we actually generate
' declarations for.
If method.AssociatedSymbol IsNot Nothing Then
Return Nothing
End If
If method.IsConstructor() Then
Return ConstructorGenerator.GenerateConstructorDeclaration(method, destination, options)
ElseIf method.IsUserDefinedOperator() Then
Return OperatorGenerator.GenerateOperatorDeclaration(method, options)
ElseIf method.IsConversion() Then
Return ConversionGenerator.GenerateConversionDeclaration(method, options)
Else
Return MethodGenerator.GenerateMethodDeclaration(method, destination, options)
End If
End Function
Public Overrides Function CreateEventDeclaration([event] As IEventSymbol,
destination As CodeGenerationDestination,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
Return EventGenerator.GenerateEventDeclaration([event], destination, options)
End Function
Public Overrides Function CreateFieldDeclaration(field As IFieldSymbol,
destination As CodeGenerationDestination,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
If destination = CodeGenerationDestination.EnumType Then
Return EnumMemberGenerator.GenerateEnumMemberDeclaration(field, Nothing, options)
Else
Return FieldGenerator.GenerateFieldDeclaration(field, destination, options)
End If
End Function
Public Overrides Function CreatePropertyDeclaration([property] As IPropertySymbol,
destination As CodeGenerationDestination,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
Return PropertyGenerator.GeneratePropertyDeclaration([property], destination, options)
End Function
Public Overrides Function CreateNamedTypeDeclaration(namedType As INamedTypeSymbol,
destination As CodeGenerationDestination,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
Return NamedTypeGenerator.GenerateNamedTypeDeclaration(Me, namedType, options, cancellationToken)
End Function
Public Overrides Function CreateNamespaceDeclaration([namespace] As INamespaceSymbol,
destination As CodeGenerationDestination,
options As VisualBasicCodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
Return NamespaceGenerator.GenerateNamespaceDeclaration(Me, [namespace], options, cancellationToken)
End Function
Private Overloads Shared Function UpdateDeclarationModifiers(Of TDeclarationNode As SyntaxNode)(declaration As TDeclarationNode, computeNewModifiersList As Func(Of SyntaxTokenList, SyntaxTokenList)) As TDeclarationNode
' Handle type declarations
Dim typeStatementSyntax = TryCast(declaration, TypeStatementSyntax)
If typeStatementSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(typeStatementSyntax.WithModifiers(computeNewModifiersList(typeStatementSyntax.Modifiers)))
End If
' Handle enum declarations
Dim enumStatementSyntax = TryCast(declaration, EnumStatementSyntax)
If enumStatementSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(enumStatementSyntax.WithModifiers(computeNewModifiersList(enumStatementSyntax.Modifiers)))
End If
' Handle methods
Dim methodBaseSyntax = TryCast(declaration, MethodBaseSyntax)
If methodBaseSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(methodBaseSyntax.WithModifiers(computeNewModifiersList(methodBaseSyntax.Modifiers)))
End If
' Handle Incomplete Members
Dim incompleteMemberSyntax = TryCast(declaration, IncompleteMemberSyntax)
If incompleteMemberSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(incompleteMemberSyntax.WithModifiers(computeNewModifiersList(incompleteMemberSyntax.Modifiers)))
End If
' Handle fields
Dim fieldDeclarationSyntax = TryCast(declaration, FieldDeclarationSyntax)
If fieldDeclarationSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(fieldDeclarationSyntax.WithModifiers(computeNewModifiersList(fieldDeclarationSyntax.Modifiers)))
End If
' Handle parameters
Dim parameterSyntax = TryCast(declaration, ParameterSyntax)
If parameterSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(parameterSyntax.WithModifiers(computeNewModifiersList(parameterSyntax.Modifiers)))
End If
' Handle local declarations
Dim localDeclarationStatementSyntax = TryCast(declaration, LocalDeclarationStatementSyntax)
If localDeclarationStatementSyntax IsNot Nothing Then
Return Cast(Of TDeclarationNode)(localDeclarationStatementSyntax.WithModifiers(computeNewModifiersList(localDeclarationStatementSyntax.Modifiers)))
End If
Return declaration
End Function
Public Overrides Function UpdateDeclarationModifiers(Of TDeclarationNode As SyntaxNode)(declaration As TDeclarationNode, newModifiers As IEnumerable(Of SyntaxToken), options As VisualBasicCodeGenerationContextInfo, cancellationToken As CancellationToken) As TDeclarationNode
Dim computeNewModifiersList As Func(Of SyntaxTokenList, SyntaxTokenList) = Function(modifiersList As SyntaxTokenList)
Return SyntaxFactory.TokenList(newModifiers)
End Function
Return UpdateDeclarationModifiers(declaration, computeNewModifiersList)
End Function
Public Overrides Function UpdateDeclarationAccessibility(Of TDeclarationNode As SyntaxNode)(declaration As TDeclarationNode, newAccessibility As Accessibility, options As VisualBasicCodeGenerationContextInfo, cancellationToken As CancellationToken) As TDeclarationNode
Dim computeNewModifiersList As Func(Of SyntaxTokenList, SyntaxTokenList) = Function(modifiersList As SyntaxTokenList)
Return UpdateDeclarationAccessibility(modifiersList, newAccessibility, options)
End Function
Return UpdateDeclarationModifiers(declaration, computeNewModifiersList)
End Function
Private Overloads Shared Function UpdateDeclarationAccessibility(modifiersList As SyntaxTokenList, newAccessibility As Accessibility, options As VisualBasicCodeGenerationContextInfo) As SyntaxTokenList
Dim newModifierTokens As ArrayBuilder(Of SyntaxToken) = Nothing
Using x = ArrayBuilder(Of SyntaxToken).GetInstance(newModifierTokens)
AddAccessibilityModifiers(newAccessibility, newModifierTokens, CodeGenerationDestination.Unspecified, options, Accessibility.NotApplicable)
If newModifierTokens.Count = 0 Then
Return modifiersList
End If
Return GetUpdatedDeclarationAccessibilityModifiers(
newModifierTokens, modifiersList,
Function(modifier) SyntaxFacts.IsAccessibilityModifier(modifier.Kind()))
End Using
End Function
Private Shared Function UpdateSimpleAsClause(asClause As SimpleAsClauseSyntax, newType As ITypeSymbol) As SimpleAsClauseSyntax
Dim newTypeSyntax = newType.GenerateTypeSyntax().
WithLeadingTrivia(asClause.GetLeadingTrivia()).
WithTrailingTrivia(asClause.GetTrailingTrivia())
Return DirectCast(asClause, SimpleAsClauseSyntax).WithType(newTypeSyntax)
End Function
Private Shared Function UpdateAsClause(asClause As AsClauseSyntax, newType As ITypeSymbol) As AsClauseSyntax
Dim newTypeSyntax = newType.GenerateTypeSyntax().
WithLeadingTrivia(asClause.GetLeadingTrivia()).
WithTrailingTrivia(asClause.GetTrailingTrivia())
Select Case asClause.Kind
Case SyntaxKind.SimpleAsClause
Return DirectCast(asClause, SimpleAsClauseSyntax).WithType(newTypeSyntax)
Case Else
Dim asNewClause = DirectCast(asClause, AsNewClauseSyntax)
Dim newExpression = asNewClause.NewExpression
Dim updatedNewExpression As NewExpressionSyntax
Select Case newExpression.Kind
Case SyntaxKind.ArrayCreationExpression
updatedNewExpression = DirectCast(newExpression, ArrayCreationExpressionSyntax).WithType(newTypeSyntax)
Case SyntaxKind.ObjectCreationExpression
updatedNewExpression = DirectCast(newExpression, ObjectCreationExpressionSyntax).WithType(newTypeSyntax)
Case Else
Return asClause
End Select
Return asNewClause.WithNewExpression(updatedNewExpression)
End Select
End Function
Public Overrides Function UpdateDeclarationType(Of TDeclarationNode As SyntaxNode)(declaration As TDeclarationNode, newType As ITypeSymbol, options As VisualBasicCodeGenerationContextInfo, cancellationToken As CancellationToken) As TDeclarationNode
Dim syntaxNode = TryCast(declaration, VisualBasicSyntaxNode)
If syntaxNode Is Nothing Then
Return declaration
End If
Select Case syntaxNode.Kind
Case SyntaxKind.SubStatement, SyntaxKind.FunctionStatement
Dim methodStatementSyntax = DirectCast(syntaxNode, MethodStatementSyntax)
Dim newAsClause = UpdateSimpleAsClause(methodStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(methodStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.DeclareSubStatement, SyntaxKind.DeclareFunctionStatement
Dim declareStatementSyntax = DirectCast(syntaxNode, DeclareStatementSyntax)
Dim newAsClause = UpdateSimpleAsClause(declareStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(declareStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.DelegateSubStatement, SyntaxKind.DelegateFunctionStatement
Dim delegateStatementSyntax = DirectCast(syntaxNode, DelegateStatementSyntax)
Dim newAsClause = UpdateSimpleAsClause(delegateStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(delegateStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.EventStatement
Dim eventStatementSyntax = DirectCast(syntaxNode, EventStatementSyntax)
Dim newAsClause = UpdateSimpleAsClause(eventStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(eventStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.OperatorStatement
Dim operatorStatementSyntax = DirectCast(syntaxNode, OperatorStatementSyntax)
Dim newAsClause = UpdateSimpleAsClause(operatorStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(operatorStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.PropertyStatement
Dim propertyStatementSyntax = DirectCast(syntaxNode, PropertyStatementSyntax)
Dim newAsClause = UpdateAsClause(propertyStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(propertyStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.VariableDeclarator
Dim variableDeclaratorSyntax = DirectCast(syntaxNode, VariableDeclaratorSyntax)
Dim newAsClause = UpdateAsClause(variableDeclaratorSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(variableDeclaratorSyntax.WithAsClause(newAsClause))
Case SyntaxKind.Parameter
Dim parameterSyntax = DirectCast(syntaxNode, ParameterSyntax)
Dim newAsClause = UpdateSimpleAsClause(parameterSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(parameterSyntax.WithAsClause(newAsClause))
Case SyntaxKind.CatchStatement
Dim catchStatementSyntax = DirectCast(syntaxNode, CatchStatementSyntax)
Dim newAsClause = UpdateSimpleAsClause(catchStatementSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(catchStatementSyntax.WithAsClause(newAsClause))
Case SyntaxKind.FunctionLambdaHeader, SyntaxKind.SubLambdaHeader
Dim lambdaHeaderSyntax = DirectCast(syntaxNode, LambdaHeaderSyntax)
Dim newAsClause = UpdateSimpleAsClause(lambdaHeaderSyntax.AsClause, newType)
Return Cast(Of TDeclarationNode)(lambdaHeaderSyntax.WithAsClause(newAsClause))
Case Else
Return declaration
End Select
End Function
Public Overrides Function UpdateDeclarationMembers(Of TDeclarationNode As SyntaxNode)(declaration As TDeclarationNode, newMembers As IList(Of ISymbol), options As VisualBasicCodeGenerationContextInfo, cancellationToken As CancellationToken) As TDeclarationNode
Dim syntaxNode = TryCast(declaration, VisualBasicSyntaxNode)
If syntaxNode IsNot Nothing Then
Select Case syntaxNode.Kind
Case SyntaxKind.EnumBlock, SyntaxKind.StructureBlock, SyntaxKind.InterfaceBlock, SyntaxKind.ClassBlock
Return Cast(Of TDeclarationNode)(NamedTypeGenerator.UpdateNamedTypeDeclaration(Me, DirectCast(syntaxNode, StatementSyntax), newMembers, options, cancellationToken))
Case SyntaxKind.CompilationUnit, SyntaxKind.NamespaceBlock
Return Cast(Of TDeclarationNode)(NamespaceGenerator.UpdateCompilationUnitOrNamespaceDeclaration(Me, syntaxNode, newMembers, options, cancellationToken))
End Select
End If
Return declaration
End Function
End Class
End Namespace
|