TypeSyntaxGeneratorVisitor.vb 11.1 KB
Newer Older
1
' Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Simplification
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions

    Friend Class TypeSyntaxGeneratorVisitor
        Inherits SymbolVisitor(Of TypeSyntax)

B
beep boop 已提交
18
        Private ReadOnly _addGlobal As Boolean
P
Pilchie 已提交
19

20 21 22 23
        Private Shared ReadOnly AddGlobalInstance As TypeSyntaxGeneratorVisitor = New TypeSyntaxGeneratorVisitor(addGlobal:=True)
        Private Shared ReadOnly NotAddGlobalInstance As TypeSyntaxGeneratorVisitor = New TypeSyntaxGeneratorVisitor(addGlobal:=False)

        Private Sub New(addGlobal As Boolean)
B
beep boop 已提交
24
            Me._addGlobal = addGlobal
P
Pilchie 已提交
25 26
        End Sub

27 28 29 30
        Public Shared Function Create(addGlobal As Boolean) As TypeSyntaxGeneratorVisitor
            Return If(addGlobal, AddGlobalInstance, NotAddGlobalInstance)
        End Function

P
Pilchie 已提交
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
        Public Overrides Function DefaultVisit(node As ISymbol) As TypeSyntax
            Throw New NotImplementedException()
        End Function

        Private Function AddInformationTo(Of TTypeSyntax As TypeSyntax)(type As TTypeSyntax, symbol As ISymbol) As TTypeSyntax
            type = type.WithPrependedLeadingTrivia(SyntaxFactory.ElasticMarker).WithAppendedTrailingTrivia(SyntaxFactory.ElasticMarker)
            type = type.WithAdditionalAnnotations(SymbolAnnotation.Create(symbol))
            Return type
        End Function

        Public Overrides Function VisitAlias(symbol As IAliasSymbol) As TypeSyntax
            Return AddInformationTo(symbol.Name.ToIdentifierName, symbol)
        End Function

        Public Overrides Function VisitArrayType(symbol As IArrayTypeSymbol) As TypeSyntax
            Dim underlyingNonArrayType = symbol.ElementType
            While underlyingNonArrayType.Kind = SymbolKind.ArrayType
                underlyingNonArrayType = (DirectCast(underlyingNonArrayType, IArrayTypeSymbol)).ElementType
            End While

            Dim elementTypeSyntax = underlyingNonArrayType.Accept(Me)
            Dim ranks = New List(Of ArrayRankSpecifierSyntax)()
            Dim arrayType = symbol
            While arrayType IsNot Nothing
                Dim commaCount = Math.Max(0, arrayType.Rank - 1)
                Dim commas = SyntaxFactory.TokenList(Enumerable.Repeat(SyntaxFactory.Token(SyntaxKind.CommaToken), commaCount))
                ranks.Add(SyntaxFactory.ArrayRankSpecifier(SyntaxFactory.Token(SyntaxKind.OpenParenToken), commas, SyntaxFactory.Token(SyntaxKind.CloseParenToken)))
                arrayType = TryCast(arrayType.ElementType, IArrayTypeSymbol)
            End While

            Dim arrayTypeSyntax = SyntaxFactory.ArrayType(elementTypeSyntax, SyntaxFactory.List(ranks))
            Return AddInformationTo(arrayTypeSyntax, symbol)
        End Function

        Public Overrides Function VisitDynamicType(symbol As IDynamicTypeSymbol) As TypeSyntax
            Return AddInformationTo(SyntaxFactory.IdentifierName("dynamic"), symbol)
        End Function

        Public Function CreateSimpleTypeSyntax(symbol As INamedTypeSymbol) As TypeSyntax
            Select Case symbol.SpecialType
                Case SpecialType.System_Object
B
Basoundr_ms 已提交
72
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Object"))
P
Pilchie 已提交
73
                Case SpecialType.System_Boolean
B
Basoundr_ms 已提交
74
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Boolean"))
P
Pilchie 已提交
75
                Case SpecialType.System_Char
B
Basoundr_ms 已提交
76
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Char"))
P
Pilchie 已提交
77
                Case SpecialType.System_SByte
B
Basoundr_ms 已提交
78
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("SByte"))
P
Pilchie 已提交
79
                Case SpecialType.System_Byte
B
Basoundr_ms 已提交
80
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Byte"))
P
Pilchie 已提交
81
                Case SpecialType.System_Int16
B
Basoundr_ms 已提交
82
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Int16"))
P
Pilchie 已提交
83
                Case SpecialType.System_UInt16
B
Basoundr_ms 已提交
84
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("UInt16"))
P
Pilchie 已提交
85
                Case SpecialType.System_Int32
B
Basoundr_ms 已提交
86
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Int32"))
P
Pilchie 已提交
87
                Case SpecialType.System_Int64
B
Basoundr_ms 已提交
88
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Int64"))
P
Pilchie 已提交
89
                Case SpecialType.System_UInt32
B
Basoundr_ms 已提交
90
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("UInt32"))
P
Pilchie 已提交
91
                Case SpecialType.System_UInt64
B
Basoundr_ms 已提交
92
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("UInt64"))
P
Pilchie 已提交
93
                Case SpecialType.System_Decimal
B
Basoundr_ms 已提交
94
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Decimal"))
P
Pilchie 已提交
95
                Case SpecialType.System_Single
B
Basoundr_ms 已提交
96
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Single"))
P
Pilchie 已提交
97
                Case SpecialType.System_Double
B
Basoundr_ms 已提交
98
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Double"))
P
Pilchie 已提交
99
                Case SpecialType.System_String
B
Basoundr_ms 已提交
100
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("String"))
P
Pilchie 已提交
101
                Case SpecialType.System_DateTime
B
Basoundr_ms 已提交
102
                    Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("DateTime"))
P
Pilchie 已提交
103 104
            End Select

105 106 107 108
            If symbol.IsTupleType Then
                Return CreateTupleTypeSyntax(symbol)
            End If

P
Pilchie 已提交
109
            If symbol.Name = String.Empty OrElse symbol.IsAnonymousType Then
B
Basoundr_ms 已提交
110
                Return SyntaxFactory.QualifiedName(SyntaxFactory.IdentifierName("System"), SyntaxFactory.IdentifierName("Object"))
P
Pilchie 已提交
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
            End If

            If symbol.OriginalDefinition.SpecialType = SpecialType.System_Nullable_T Then
                Return AddInformationTo(SyntaxFactory.NullableType(symbol.TypeArguments.First().Accept(Me)), symbol)
            End If

            If symbol.TypeParameters.Length = 0 Then
                Return symbol.Name.ToIdentifierName
            End If

            Return SyntaxFactory.GenericName(
                symbol.Name.ToIdentifierToken,
                SyntaxFactory.TypeArgumentList(SyntaxFactory.SeparatedList(symbol.TypeArguments.[Select](Function(t) t.Accept(Me)))))
        End Function

126 127 128 129 130 131
        Private Shared Function CreateTupleTypeSyntax(symbol As INamedTypeSymbol) As TypeSyntax
            Dim types = symbol.TupleElementTypes
            Dim names = symbol.TupleElementNames
            Dim hasNames = Not names.IsDefault

            Return SyntaxFactory.TupleType(SyntaxFactory.SeparatedList(
132 133 134 135 136 137 138 139 140
                types.Select(Function(t, i) If(hasNames AndAlso names(i) IsNot Nothing,
                                                        SyntaxFactory.NamedTupleElement(
                                                                        SyntaxFactory.IdentifierName(names(i)),
                                                                        SyntaxFactory.SimpleAsClause(
                                                                                    SyntaxFactory.Token(SyntaxKind.AsKeyword),
                                                                                    Nothing,
                                                                                    t.GenerateTypeSyntax())),
                                                        DirectCast(SyntaxFactory.TypedTupleElement(
                                                                        t.GenerateTypeSyntax()), TupleElementSyntax)))))
141 142
        End Function

P
Pilchie 已提交
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
        Public Overrides Function VisitNamedType(symbol As INamedTypeSymbol) As TypeSyntax
            Dim typeSyntax = CreateSimpleTypeSyntax(symbol)
            If Not (TypeOf typeSyntax Is SimpleNameSyntax) Then
                Return typeSyntax
            End If

            Dim simpleNameSyntax = DirectCast(typeSyntax, SimpleNameSyntax)
            If symbol.ContainingType IsNot Nothing Then
                If symbol.ContainingType.TypeKind = TypeKind.Submission Then
                    Return typeSyntax
                Else
                    Return AddInformationTo(SyntaxFactory.QualifiedName(DirectCast(symbol.ContainingType.Accept(Me), NameSyntax), simpleNameSyntax), symbol)
                End If
            ElseIf symbol.ContainingNamespace IsNot Nothing Then
                If symbol.ContainingNamespace.IsGlobalNamespace Then
B
beep boop 已提交
158
                    If _addGlobal AndAlso symbol.TypeKind <> TypeKind.[Error] Then
P
Pilchie 已提交
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
                        Return AddInformationTo(SyntaxFactory.QualifiedName(SyntaxFactory.GlobalName(), simpleNameSyntax), symbol)
                    End If
                Else
                    Dim container = symbol.ContainingNamespace.Accept(Me)
                    Return AddInformationTo(SyntaxFactory.QualifiedName(DirectCast(container, NameSyntax), simpleNameSyntax), symbol)
                End If
            End If

            Return simpleNameSyntax
        End Function

        Public Overrides Function VisitNamespace(symbol As INamespaceSymbol) As TypeSyntax
            Dim result = AddInformationTo(symbol.Name.ToIdentifierName, symbol)
            If symbol.ContainingNamespace Is Nothing Then
                Return result
            End If

            If symbol.ContainingNamespace.IsGlobalNamespace Then
B
beep boop 已提交
177
                If _addGlobal Then
P
Pilchie 已提交
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
                    Return AddInformationTo(SyntaxFactory.QualifiedName(SyntaxFactory.GlobalName(), result), symbol)
                Else
                    Return result
                End If
            Else
                Dim container = symbol.ContainingNamespace.Accept(Me)
                Return AddInformationTo(SyntaxFactory.QualifiedName(DirectCast(container, NameSyntax), result), symbol)
            End If
        End Function

        Public Overrides Function VisitPointerType(symbol As IPointerTypeSymbol) As TypeSyntax
            ' TODO(cyrusn): What to do here?  Maybe object would be better instead?
            Return symbol.PointedAtType.Accept(Me)
        End Function

        Public Overrides Function VisitTypeParameter(symbol As ITypeParameterSymbol) As TypeSyntax
            Return AddInformationTo(symbol.Name.ToIdentifierName, symbol)
        End Function
    End Class
197
End Namespace