|
' 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.Threading
Imports Microsoft.CodeAnalysis.CodeGeneration
Imports Microsoft.CodeAnalysis.CodeGeneration.CodeGenerationHelpers
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGeneration
Friend Module NamespaceGenerator
Public Function AddNamespaceTo(service As ICodeGenerationService,
destination As CompilationUnitSyntax,
[namespace] As INamespaceSymbol,
options As CodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As CompilationUnitSyntax
Dim declaration = GenerateNamespaceDeclaration(service, [namespace], options, cancellationToken)
If Not TypeOf declaration Is NamespaceBlockSyntax Then
Throw New ArgumentException(WorkspaceExtensionsResources.Namespace_can_not_be_added_in_this_destination)
End If
Dim members = Insert(destination.Members, DirectCast(declaration, StatementSyntax), options, availableIndices)
Return destination.WithMembers(members)
End Function
Public Function AddNamespaceTo(service As ICodeGenerationService,
destination As NamespaceBlockSyntax,
[namespace] As INamespaceSymbol,
options As CodeGenerationContextInfo,
availableIndices As IList(Of Boolean),
cancellationToken As CancellationToken) As NamespaceBlockSyntax
Dim declaration = GenerateNamespaceDeclaration(service, [namespace], options, cancellationToken)
If Not TypeOf declaration Is NamespaceBlockSyntax Then
Throw New ArgumentException(WorkspaceExtensionsResources.Namespace_can_not_be_added_in_this_destination)
End If
Dim members = Insert(destination.Members, DirectCast(declaration, StatementSyntax), options, availableIndices)
Return destination.WithMembers(members)
End Function
Public Function GenerateNamespaceDeclaration(service As ICodeGenerationService, [namespace] As INamespaceSymbol, options As CodeGenerationContextInfo, cancellationToken As CancellationToken) As SyntaxNode
Dim name As String = Nothing
Dim innermostNamespace As INamespaceSymbol = Nothing
GetNameAndInnermostNamespace([namespace], options, name, innermostNamespace)
Dim declaration = GetDeclarationSyntaxWithoutMembers([namespace], innermostNamespace, name, options)
declaration = If(options.Context.GenerateMembers,
service.AddMembers(declaration, innermostNamespace.GetMembers().AsEnumerable(), options, cancellationToken),
declaration)
Return AddFormatterAndCodeGeneratorAnnotationsTo(declaration)
End Function
Public Function UpdateCompilationUnitOrNamespaceDeclaration(service As ICodeGenerationService,
declaration As SyntaxNode,
newMembers As IList(Of ISymbol),
options As CodeGenerationContextInfo,
cancellationToken As CancellationToken) As SyntaxNode
declaration = RemoveAllMembers(declaration)
declaration = service.AddMembers(declaration, newMembers, options, cancellationToken)
Return AddFormatterAndCodeGeneratorAnnotationsTo(declaration)
End Function
Private Function GetDeclarationSyntaxWithoutMembers([namespace] As INamespaceSymbol, innermostNamespace As INamespaceSymbol, name As String, options As CodeGenerationContextInfo) As SyntaxNode
Dim reusableSyntax = GetReuseableSyntaxNodeForSymbol(Of SyntaxNode)([namespace], options)
If reusableSyntax Is Nothing Then
Return GenerateNamespaceDeclarationWorker(name, innermostNamespace)
End If
Return RemoveAllMembers(reusableSyntax)
End Function
Private Function RemoveAllMembers(declaration As SyntaxNode) As SyntaxNode
Select Case declaration.Kind
Case SyntaxKind.CompilationUnit
Return DirectCast(declaration, CompilationUnitSyntax).WithMembers(Nothing)
Case SyntaxKind.NamespaceBlock
Return DirectCast(declaration, NamespaceBlockSyntax).WithMembers(Nothing)
Case Else
Return declaration
End Select
End Function
Private Function GenerateNamespaceDeclarationWorker(name As String, [namespace] As INamespaceSymbol) As SyntaxNode
If name = String.Empty Then
Return SyntaxFactory.CompilationUnit().WithImports(GenerateImportsStatements([namespace]))
Else
Return SyntaxFactory.NamespaceBlock(
SyntaxFactory.NamespaceStatement(SyntaxFactory.ParseName(name)))
End If
End Function
Private Function GenerateImportsStatements([namespace] As INamespaceSymbol) As SyntaxList(Of ImportsStatementSyntax)
Dim statements =
CodeGenerationNamespaceInfo.GetImports([namespace]).
Select(AddressOf GenerateImportsStatement).
WhereNotNull().ToList()
Return If(statements.Count = 0, Nothing, SyntaxFactory.List(statements))
End Function
Private Function GenerateImportsStatement(import As ISymbol) As ImportsStatementSyntax
If TypeOf import Is IAliasSymbol Then
Dim [alias] = DirectCast(import, IAliasSymbol)
Dim name = GenerateName([alias].Target)
If name IsNot Nothing Then
Return SyntaxFactory.ImportsStatement(
SyntaxFactory.SingletonSeparatedList(Of ImportsClauseSyntax)(
SyntaxFactory.SimpleImportsClause(SyntaxFactory.ImportAliasClause([alias].Name.ToIdentifierToken), name)))
End If
ElseIf TypeOf import Is INamespaceOrTypeSymbol Then
Dim name = GenerateName(DirectCast(import, INamespaceOrTypeSymbol))
If name IsNot Nothing Then
Return SyntaxFactory.ImportsStatement(
SyntaxFactory.SingletonSeparatedList(Of ImportsClauseSyntax)(
SyntaxFactory.SimpleImportsClause(name)))
End If
End If
Return Nothing
End Function
Private Function GenerateName(symbol As INamespaceOrTypeSymbol) As NameSyntax
If TypeOf symbol Is ITypeSymbol Then
Return TryCast(DirectCast(symbol, ITypeSymbol).GenerateTypeSyntax(), NameSyntax)
Else
Return SyntaxFactory.ParseName(symbol.ToDisplayString(SymbolDisplayFormat.FullyQualifiedFormat))
End If
End Function
End Module
End Namespace
|