|
' 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.PooledObjects
Imports Microsoft.CodeAnalysis.RuntimeMembers
Imports Microsoft.CodeAnalysis.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Namespace Microsoft.CodeAnalysis.VisualBasic
Partial Public Class VisualBasicCompilation
Private ReadOnly _wellKnownMemberSignatureComparer As New WellKnownMembersSignatureComparer(Me)
''' <summary>
''' An array of cached well known types available for use in this Compilation.
''' Lazily filled by GetWellKnownType method.
''' </summary>
''' <remarks></remarks>
Private _lazyWellKnownTypes() As NamedTypeSymbol
''' <summary>
''' Lazy cache of well known members.
''' Not yet known value is represented by ErrorTypeSymbol.UnknownResultType
''' </summary>
Private _lazyWellKnownTypeMembers() As Symbol
Private _lazyExtensionAttributeConstructor As Symbol = ErrorTypeSymbol.UnknownResultType ' Not yet known.
Private _lazyExtensionAttributeConstructorErrorInfo As Object 'Actually, DiagnosticInfo
#Region "Synthesized Attributes"
Friend Function GetExtensionAttributeConstructor(<Out> ByRef useSiteInfo As UseSiteInfo(Of AssemblySymbol)) As MethodSymbol
Dim attributeCtor As MethodSymbol = Nothing
Dim ctorError As DiagnosticInfo = Nothing
If _lazyExtensionAttributeConstructor Is ErrorTypeSymbol.UnknownResultType Then
Dim system_Runtime_CompilerServices = Me.GlobalNamespace.LookupNestedNamespace(ImmutableArray.Create(MetadataHelpers.SystemString, "Runtime", "CompilerServices"))
Dim attributeType As NamedTypeSymbol = Nothing
Dim sourceModuleSymbol = DirectCast(Me.SourceModule, SourceModuleSymbol)
Dim sourceModuleBinder As Binder = BinderBuilder.CreateSourceModuleBinder(sourceModuleSymbol)
If system_Runtime_CompilerServices IsNot Nothing Then
Dim candidates = system_Runtime_CompilerServices.GetTypeMembers(AttributeDescription.CaseInsensitiveExtensionAttribute.Name, 0)
Dim ambiguity As Boolean = False
For Each candidate As NamedTypeSymbol In candidates
If Not sourceModuleBinder.IsAccessible(candidate, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) Then
Continue For
End If
If candidate.ContainingModule Is sourceModuleSymbol Then
' Type from this module always better.
attributeType = candidate
ambiguity = False
Exit For
End If
If attributeType Is Nothing Then
Debug.Assert(Not ambiguity)
attributeType = candidate
ElseIf candidate.ContainingAssembly Is Me.Assembly Then
If attributeType.ContainingAssembly Is Me.Assembly Then
ambiguity = True
Else
attributeType = candidate
ambiguity = False
End If
ElseIf attributeType.ContainingAssembly IsNot Me.Assembly Then
Debug.Assert(candidate.ContainingAssembly IsNot Me.Assembly)
ambiguity = True
End If
Next
If ambiguity Then
Debug.Assert(attributeType IsNot Nothing)
attributeType = Nothing
End If
End If
If attributeType IsNot Nothing AndAlso
Not attributeType.IsStructureType AndAlso
Not attributeType.IsMustInherit AndAlso
GetWellKnownType(WellKnownType.System_Attribute).IsBaseTypeOf(attributeType, CompoundUseSiteInfo(Of AssemblySymbol).Discarded) AndAlso
sourceModuleBinder.IsAccessible(attributeType, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) Then
For Each ctor In attributeType.InstanceConstructors
If ctor.ParameterCount = 0 Then
If sourceModuleBinder.IsAccessible(ctor, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded) Then
attributeCtor = ctor
End If
Exit For
End If
Next
End If
If attributeCtor Is Nothing Then
' TODO (tomat): It is not clear under what circumstances is this error reported since the binder already reports errors when the conditions above are not satisfied.
ctorError = ErrorFactory.ErrorInfo(ERRID.ERR_MissingRuntimeHelper,
AttributeDescription.CaseInsensitiveExtensionAttribute.FullName & "." & WellKnownMemberNames.InstanceConstructorName)
Else
Dim attributeUsage As AttributeUsageInfo = attributeCtor.ContainingType.GetAttributeUsageInfo()
Debug.Assert(Not attributeUsage.IsNull)
Const requiredTargets As AttributeTargets = AttributeTargets.Assembly Or AttributeTargets.Class Or AttributeTargets.Method
If (attributeUsage.ValidTargets And requiredTargets) <> requiredTargets Then
ctorError = ErrorFactory.ErrorInfo(ERRID.ERR_ExtensionAttributeInvalid)
End If
End If
' Storing m_LazyExtensionAttributeConstructorErrorInfo first.
_lazyExtensionAttributeConstructorErrorInfo = ctorError
Interlocked.CompareExchange(_lazyExtensionAttributeConstructor,
DirectCast(attributeCtor, Symbol),
DirectCast(ErrorTypeSymbol.UnknownResultType, Symbol))
End If
attributeCtor = DirectCast(_lazyExtensionAttributeConstructor, MethodSymbol)
ctorError = DirectCast(Volatile.Read(_lazyExtensionAttributeConstructorErrorInfo), DiagnosticInfo)
If ctorError IsNot Nothing Then
useSiteInfo = New UseSiteInfo(Of AssemblySymbol)(ctorError)
Else
useSiteInfo = Binder.GetUseSiteInfoForMemberAndContainingType(attributeCtor)
End If
Return attributeCtor
End Function
''' <summary>
''' Synthesizes a custom attribute.
''' Returns Nothing if the <paramref name="constructor"/> symbol is missing,
''' or any of the members in <paramref name="namedArguments" /> are missing.
''' The attribute is synthesized only if present.
''' </summary>
''' <param name="namedArguments">
''' Takes a list of pairs of well-known members and constants. The constants
''' will be passed to the field/property referenced by the well-known member.
''' If the well-known member does Not exist in the compilation then no attribute
''' will be synthesized.
''' </param>
''' <param name="isOptionalUse">
''' Indicates if this particular attribute application should be considered optional.
''' </param>
Friend Function TrySynthesizeAttribute(
constructor As WellKnownMember,
Optional arguments As ImmutableArray(Of TypedConstant) = Nothing,
Optional namedArguments As ImmutableArray(Of KeyValuePair(Of WellKnownMember, TypedConstant)) = Nothing,
Optional isOptionalUse As Boolean = False
) As SynthesizedAttributeData
Dim constructorSymbol = TryCast(GetWellKnownTypeMember(constructor), MethodSymbol)
If constructorSymbol Is Nothing OrElse
Binder.GetUseSiteInfoForWellKnownTypeMember(constructorSymbol, constructor, False).DiagnosticInfo IsNot Nothing Then
Return ReturnNothingOrThrowIfAttributeNonOptional(constructor, isOptionalUse)
End If
If arguments.IsDefault Then
arguments = ImmutableArray(Of TypedConstant).Empty
End If
Dim namedStringArguments As ImmutableArray(Of KeyValuePair(Of String, TypedConstant))
If namedArguments.IsDefault Then
namedStringArguments = ImmutableArray(Of KeyValuePair(Of String, TypedConstant)).Empty
Else
Dim builder = New ArrayBuilder(Of KeyValuePair(Of String, TypedConstant))(namedArguments.Length)
For Each arg In namedArguments
Dim wellKnownMember = GetWellKnownTypeMember(arg.Key)
If wellKnownMember Is Nothing OrElse
TypeOf wellKnownMember Is ErrorTypeSymbol OrElse
Binder.GetUseSiteInfoForWellKnownTypeMember(wellKnownMember, arg.Key, False).DiagnosticInfo IsNot Nothing Then
Return ReturnNothingOrThrowIfAttributeNonOptional(constructor)
Else
builder.Add(New KeyValuePair(Of String, TypedConstant)(wellKnownMember.Name, arg.Value))
End If
Next
namedStringArguments = builder.ToImmutableAndFree()
End If
Return New SynthesizedAttributeData(Me, constructorSymbol, arguments, namedStringArguments)
End Function
Private Shared Function ReturnNothingOrThrowIfAttributeNonOptional(constructor As WellKnownMember, Optional isOptionalUse As Boolean = False) As SynthesizedAttributeData
If isOptionalUse OrElse WellKnownMembers.IsSynthesizedAttributeOptional(constructor) Then
Return Nothing
Else
Throw ExceptionUtilities.Unreachable
End If
End Function
Friend Function SynthesizeExtensionAttribute() As SynthesizedAttributeData
Dim constructor As MethodSymbol = GetExtensionAttributeConstructor(useSiteInfo:=Nothing)
Debug.Assert(constructor IsNot Nothing AndAlso
constructor.GetUseSiteInfo().DiagnosticInfo Is Nothing AndAlso
constructor.ContainingType.GetUseSiteInfo().DiagnosticInfo Is Nothing)
Return SynthesizedAttributeData.Create(Me, constructor, WellKnownMember.System_Runtime_CompilerServices_ExtensionAttribute__ctor)
End Function
Friend Function SynthesizeStateMachineAttribute(method As MethodSymbol, compilationState As ModuleCompilationState) As SynthesizedAttributeData
Debug.Assert(method.IsAsync OrElse method.IsIterator)
' The async state machine type is not synthesized until the async method body is rewritten. If we are
' only emitting metadata the method body will not have been rewritten, and the async state machine
' type will not have been created. In this case, omit the attribute.
Dim stateMachineType As NamedTypeSymbol = Nothing
If compilationState.TryGetStateMachineType(method, stateMachineType) Then
Dim ctor = If(method.IsAsync, WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor,
WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor)
Dim arg = New TypedConstant(GetWellKnownType(WellKnownType.System_Type),
TypedConstantKind.Type,
If(stateMachineType.IsGenericType, stateMachineType.ConstructUnboundGenericType(), stateMachineType))
Return TrySynthesizeAttribute(ctor, ImmutableArray.Create(arg))
End If
Return Nothing
End Function
Friend Function SynthesizeDecimalConstantAttribute(value As Decimal) As SynthesizedAttributeData
Dim isNegative As Boolean
Dim scale As Byte
Dim low, mid, high As UInteger
value.GetBits(isNegative, scale, low, mid, high)
Dim specialTypeByte = GetSpecialType(SpecialType.System_Byte)
Debug.Assert(specialTypeByte.GetUseSiteInfo().DiagnosticInfo Is Nothing)
Dim specialTypeUInt32 = GetSpecialType(SpecialType.System_UInt32)
Debug.Assert(specialTypeUInt32.GetUseSiteInfo().DiagnosticInfo Is Nothing)
Return TrySynthesizeAttribute(
WellKnownMember.System_Runtime_CompilerServices_DecimalConstantAttribute__ctor,
ImmutableArray.Create(
New TypedConstant(specialTypeByte, TypedConstantKind.Primitive, scale),
New TypedConstant(specialTypeByte, TypedConstantKind.Primitive, CByte(If(isNegative, 128, 0))),
New TypedConstant(specialTypeUInt32, TypedConstantKind.Primitive, high),
New TypedConstant(specialTypeUInt32, TypedConstantKind.Primitive, mid),
New TypedConstant(specialTypeUInt32, TypedConstantKind.Primitive, low)
))
End Function
Friend Function SynthesizeDebuggerBrowsableNeverAttribute() As SynthesizedAttributeData
If Options.OptimizationLevel <> OptimizationLevel.Debug Then
Return Nothing
End If
Return TrySynthesizeAttribute(
WellKnownMember.System_Diagnostics_DebuggerBrowsableAttribute__ctor,
ImmutableArray.Create(New TypedConstant(GetWellKnownType(WellKnownType.System_Diagnostics_DebuggerBrowsableState),
TypedConstantKind.Enum,
DebuggerBrowsableState.Never)))
End Function
Friend Function SynthesizeDebuggerHiddenAttribute() As SynthesizedAttributeData
If Options.OptimizationLevel <> OptimizationLevel.Debug Then
Return Nothing
End If
Return TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerHiddenAttribute__ctor)
End Function
Friend Function SynthesizeEditorBrowsableNeverAttribute() As SynthesizedAttributeData
Return TrySynthesizeAttribute(
WellKnownMember.System_ComponentModel_EditorBrowsableAttribute__ctor,
ImmutableArray.Create(New TypedConstant(GetWellKnownType(WellKnownType.System_ComponentModel_EditorBrowsableState),
TypedConstantKind.Enum,
System.ComponentModel.EditorBrowsableState.Never)))
End Function
Friend Function SynthesizeDebuggerNonUserCodeAttribute() As SynthesizedAttributeData
If Options.OptimizationLevel <> OptimizationLevel.Debug Then
Return Nothing
End If
Return TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerNonUserCodeAttribute__ctor)
End Function
Friend Function SynthesizeOptionalDebuggerStepThroughAttribute() As SynthesizedAttributeData
If Options.OptimizationLevel <> OptimizationLevel.Debug Then
Return Nothing
End If
Debug.Assert(
WellKnownMembers.IsSynthesizedAttributeOptional(
WellKnownMember.System_Diagnostics_DebuggerStepThroughAttribute__ctor))
Return TrySynthesizeAttribute(WellKnownMember.System_Diagnostics_DebuggerStepThroughAttribute__ctor)
End Function
#End Region
''' <summary>
''' Lookup member declaration in well known type used by this Compilation.
''' </summary>
Friend Function GetWellKnownTypeMember(member As WellKnownMember) As Symbol
Debug.Assert(member >= 0 AndAlso member < WellKnownMember.Count)
' Test hook If a member Is marked missing, Then Return null.
If IsMemberMissing(member) Then
Return Nothing
End If
If _lazyWellKnownTypeMembers Is Nothing OrElse _lazyWellKnownTypeMembers(member) Is ErrorTypeSymbol.UnknownResultType Then
If (_lazyWellKnownTypeMembers Is Nothing) Then
Dim wellKnownTypeMembers = New Symbol(WellKnownMember.Count - 1) {}
For i As Integer = 0 To wellKnownTypeMembers.Length - 1
wellKnownTypeMembers(i) = ErrorTypeSymbol.UnknownResultType
Next
Interlocked.CompareExchange(_lazyWellKnownTypeMembers, wellKnownTypeMembers, Nothing)
End If
Dim descriptor = WellKnownMembers.GetDescriptor(member)
Dim type = If(descriptor.IsSpecialTypeMember,
GetSpecialType(descriptor.DeclaringSpecialType),
GetWellKnownType(descriptor.DeclaringWellKnownType))
Dim result As Symbol = Nothing
If Not type.IsErrorType() Then
result = VisualBasicCompilation.GetRuntimeMember(type, descriptor, _wellKnownMemberSignatureComparer, accessWithinOpt:=Me.Assembly)
End If
Interlocked.CompareExchange(_lazyWellKnownTypeMembers(member), result, DirectCast(ErrorTypeSymbol.UnknownResultType, Symbol))
End If
Return _lazyWellKnownTypeMembers(member)
End Function
Friend Overrides Function IsSystemTypeReference(type As ITypeSymbolInternal) As Boolean
Return TypeSymbol.Equals(DirectCast(type, TypeSymbol), GetWellKnownType(WellKnownType.System_Type), TypeCompareKind.ConsiderEverything)
End Function
Friend Overrides Function CommonGetWellKnownTypeMember(member As WellKnownMember) As ISymbolInternal
Return GetWellKnownTypeMember(member)
End Function
Friend Overrides Function CommonGetWellKnownType(wellknownType As WellKnownType) As ITypeSymbolInternal
Return GetWellKnownType(wellknownType)
End Function
Friend Overrides Function IsAttributeType(type As ITypeSymbol) As Boolean
If type.Kind <> SymbolKind.NamedType Then
Return False
End If
Return DirectCast(type, NamedTypeSymbol).IsOrDerivedFromWellKnownClass(WellKnownType.System_Attribute, Me, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded)
End Function
''' <summary>
''' In case duplicate types are encountered, returns an error type.
''' But if the IgnoreCorLibraryDuplicatedTypes compilation option is set, any duplicate type found in corlib is ignored and doesn't count as a duplicate.
''' </summary>
Friend Function GetWellKnownType(type As WellKnownType) As NamedTypeSymbol
Debug.Assert(type.IsWellKnownType())
Dim index As Integer = type - WellKnownType.First
If _lazyWellKnownTypes Is Nothing OrElse _lazyWellKnownTypes(index) Is Nothing Then
If (_lazyWellKnownTypes Is Nothing) Then
Interlocked.CompareExchange(_lazyWellKnownTypes,
New NamedTypeSymbol(WellKnownTypes.Count - 1) {}, Nothing)
End If
Dim mdName As String = WellKnownTypes.GetMetadataName(type)
Dim result As NamedTypeSymbol
Dim conflicts As (AssemblySymbol, AssemblySymbol) = Nothing
If IsTypeMissing(type) Then
result = Nothing
Else
result = Me.Assembly.GetTypeByMetadataName(mdName, includeReferences:=True, isWellKnownType:=True, useCLSCompliantNameArityEncoding:=True, conflicts:=conflicts,
ignoreCorLibraryDuplicatedTypes:=Me.Options.IgnoreCorLibraryDuplicatedTypes)
Debug.Assert(If(Not result?.IsErrorType(), True))
End If
If result Is Nothing Then
Dim emittedName As MetadataTypeName = MetadataTypeName.FromFullName(mdName, useCLSCompliantNameArityEncoding:=True)
If type.IsValueTupleType() Then
Dim delayedErrorInfo As Func(Of MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo, DiagnosticInfo)
If conflicts.Item1 Is Nothing Then
Debug.Assert(conflicts.Item2 Is Nothing)
delayedErrorInfo = Function(t) ErrorFactory.ErrorInfo(ERRID.ERR_ValueTupleTypeRefResolutionError1, t)
Else
Dim capturedConflicts = conflicts
delayedErrorInfo = Function(t) ErrorFactory.ErrorInfo(ERRID.ERR_ValueTupleResolutionAmbiguous3, t, capturedConflicts.Item1, capturedConflicts.Item2)
End If
result = New MissingMetadataTypeSymbol.TopLevelWithCustomErrorInfo(Assembly.Modules(0), emittedName, delayedErrorInfo)
Else
result = New MissingMetadataTypeSymbol.TopLevel(Assembly.Modules(0), emittedName)
End If
End If
If (Interlocked.CompareExchange(_lazyWellKnownTypes(index), result, Nothing) IsNot Nothing) Then
Debug.Assert(result Is _lazyWellKnownTypes(index) OrElse
(_lazyWellKnownTypes(index).IsErrorType() AndAlso result.IsErrorType()))
End If
End If
Return _lazyWellKnownTypes(index)
End Function
Friend Shared Function GetRuntimeMember(
ByVal declaringType As NamedTypeSymbol,
ByRef descriptor As MemberDescriptor,
ByVal comparer As SignatureComparer(Of MethodSymbol, FieldSymbol, PropertySymbol, TypeSymbol, ParameterSymbol),
ByVal accessWithinOpt As AssemblySymbol
) As Symbol
Dim result As Symbol = Nothing
Dim targetSymbolKind As SymbolKind
Dim targetMethodKind As MethodKind = MethodKind.Ordinary
Dim isShared As Boolean = (descriptor.Flags And MemberFlags.Static) <> 0
Select Case descriptor.Flags And MemberFlags.KindMask
Case MemberFlags.Constructor
targetSymbolKind = SymbolKind.Method
targetMethodKind = MethodKind.Constructor
Debug.Assert(Not isShared) 'static constructors are never called explicitly
Case MemberFlags.Method
targetSymbolKind = SymbolKind.Method
Case MemberFlags.PropertyGet
targetSymbolKind = SymbolKind.Method
targetMethodKind = MethodKind.PropertyGet
Case MemberFlags.Field
targetSymbolKind = SymbolKind.Field
Case MemberFlags.Property
targetSymbolKind = SymbolKind.Property
Case Else
Throw ExceptionUtilities.UnexpectedValue(descriptor.Flags)
End Select
For Each m In declaringType.GetMembers(descriptor.Name)
If m.Kind <> targetSymbolKind OrElse m.IsShared <> isShared OrElse
Not (m.DeclaredAccessibility = Accessibility.Public OrElse (accessWithinOpt IsNot Nothing AndAlso Symbol.IsSymbolAccessible(m, accessWithinOpt))) Then
Continue For
End If
If Not String.Equals(m.Name, descriptor.Name, StringComparison.Ordinal) Then
Continue For
End If
Select Case targetSymbolKind
Case SymbolKind.Method
Dim method = DirectCast(m, MethodSymbol)
Dim methodKind = method.MethodKind
' Treat user-defined conversions and operators as ordinary methods for the purpose
' of matching them here.
If methodKind = MethodKind.Conversion OrElse methodKind = MethodKind.UserDefinedOperator Then
methodKind = MethodKind.Ordinary
End If
If method.Arity <> descriptor.Arity OrElse methodKind <> targetMethodKind OrElse
((descriptor.Flags And MemberFlags.Virtual) <> 0) <>
(method.IsOverridable OrElse method.IsOverrides OrElse method.IsMustOverride) Then
Continue For
End If
If Not comparer.MatchMethodSignature(method, descriptor.Signature) Then
Continue For
End If
Case SymbolKind.Property
Dim [property] = DirectCast(m, PropertySymbol)
If ((descriptor.Flags And MemberFlags.Virtual) <> 0) <>
([property].IsOverridable OrElse [property].IsOverrides OrElse [property].IsMustOverride) Then
Continue For
End If
If Not comparer.MatchPropertySignature([property], descriptor.Signature) Then
Continue For
End If
Case SymbolKind.Field
If Not comparer.MatchFieldSignature(DirectCast(m, FieldSymbol), descriptor.Signature) Then
Continue For
End If
Case Else
Throw ExceptionUtilities.UnexpectedValue(targetSymbolKind)
End Select
If result IsNot Nothing Then
' ambiguity
result = Nothing
Exit For
Else
result = m
End If
Next
Return result
End Function
Friend Class SpecialMembersSignatureComparer
Inherits SignatureComparer(Of MethodSymbol, FieldSymbol, PropertySymbol, TypeSymbol, ParameterSymbol)
Public Shared ReadOnly Instance As New SpecialMembersSignatureComparer()
Protected Sub New()
End Sub
Protected Overrides Function GetMDArrayElementType(type As TypeSymbol) As TypeSymbol
If type.Kind <> SymbolKind.ArrayType Then
Return Nothing
End If
Dim array = DirectCast(type, ArrayTypeSymbol)
If array.IsSZArray Then
Return Nothing ' This is not a multidimensional array
End If
Return array.ElementType
End Function
Protected Overrides Function MatchArrayRank(type As TypeSymbol, countOfDimensions As Integer) As Boolean
If countOfDimensions = 1 Then
Return Nothing ' This must be a multidimensional array
End If
If type.Kind <> SymbolKind.ArrayType Then
Return Nothing
End If
Dim array = DirectCast(type, ArrayTypeSymbol)
Return array.Rank = countOfDimensions
End Function
Protected Overrides Function GetSZArrayElementType(type As TypeSymbol) As TypeSymbol
If type.Kind <> SymbolKind.ArrayType Then
Return Nothing
End If
Dim array = DirectCast(type, ArrayTypeSymbol)
If Not array.IsSZArray Then
Return Nothing ' This is a multidimensional array
End If
Return array.ElementType
End Function
Protected Overrides Function GetFieldType(field As FieldSymbol) As TypeSymbol
Return field.Type
End Function
Protected Overrides Function GetPropertyType(prop As PropertySymbol) As TypeSymbol
Return prop.Type
End Function
Protected Overrides Function GetGenericTypeArgument(ByVal type As TypeSymbol, ByVal argumentIndex As Integer) As TypeSymbol
If type.Kind <> SymbolKind.NamedType Then
Return Nothing
End If
Dim named = DirectCast(type, NamedTypeSymbol)
If named.Arity <= argumentIndex Then
Return Nothing
End If
'We don't support nested types at the moment
If named.ContainingType IsNot Nothing Then
Return Nothing
End If
Return named.TypeArgumentsNoUseSiteDiagnostics(argumentIndex)
End Function
Protected Overrides Function GetGenericTypeDefinition(type As TypeSymbol) As TypeSymbol
If type.Kind <> SymbolKind.NamedType Then
Return Nothing
End If
Dim named = DirectCast(type, NamedTypeSymbol)
'We don't support nested types at the moment
If named.ContainingType IsNot Nothing Then
Return Nothing
End If
If named.Arity = 0 Then
Return Nothing ' Not generic
End If
Return named.OriginalDefinition
End Function
Protected Overrides Function GetParameters(ByVal method As MethodSymbol) As ImmutableArray(Of ParameterSymbol)
Return method.Parameters
End Function
Protected Overrides Function GetParameters(ByVal [property] As PropertySymbol) As ImmutableArray(Of ParameterSymbol)
Return [property].Parameters
End Function
Protected Overrides Function GetParamType(ByVal parameter As ParameterSymbol) As TypeSymbol
Return parameter.Type
End Function
Protected Overrides Function GetPointedToType(type As TypeSymbol) As TypeSymbol
Return Nothing ' Do not support pointers
End Function
Protected Overrides Function GetReturnType(method As MethodSymbol) As TypeSymbol
Return method.ReturnType
End Function
Protected Overrides Function IsByRefParam(ByVal parameter As ParameterSymbol) As Boolean
Return parameter.IsByRef
End Function
Protected Overrides Function IsByRefMethod(ByVal method As MethodSymbol) As Boolean
Return method.ReturnsByRef
End Function
Protected Overrides Function IsByRefProperty(ByVal [property] As PropertySymbol) As Boolean
Return [property].ReturnsByRef
End Function
Protected Overrides Function IsGenericMethodTypeParam(type As TypeSymbol, paramPosition As Integer) As Boolean
If type.Kind <> SymbolKind.TypeParameter Then
Return False
End If
Dim typeParam = DirectCast(type, TypeParameterSymbol)
If typeParam.ContainingSymbol.Kind <> SymbolKind.Method Then
Return False
End If
Return typeParam.Ordinal = paramPosition
End Function
Protected Overrides Function IsGenericTypeParam(type As TypeSymbol, paramPosition As Integer) As Boolean
If type.Kind <> SymbolKind.TypeParameter Then
Return False
End If
Dim typeParam = DirectCast(type, TypeParameterSymbol)
If typeParam.ContainingSymbol.Kind <> SymbolKind.NamedType Then
Return False
End If
Return typeParam.Ordinal = paramPosition
End Function
Protected Overrides Function MatchTypeToTypeId(type As TypeSymbol, typeId As Integer) As Boolean
Return CInt(type.ExtendedSpecialType) = typeId
End Function
End Class
Private Class WellKnownMembersSignatureComparer
Inherits SpecialMembersSignatureComparer
Private ReadOnly _compilation As VisualBasicCompilation
Public Sub New(compilation As VisualBasicCompilation)
_compilation = compilation
End Sub
Protected Overrides Function MatchTypeToTypeId(type As TypeSymbol, typeId As Integer) As Boolean
Dim wellKnownId = CType(typeId, WellKnownType)
If wellKnownId.IsWellKnownType() Then
Return type Is _compilation.GetWellKnownType(wellKnownId)
End If
Return MyBase.MatchTypeToTypeId(type, typeId)
End Function
End Class
Friend Function SynthesizeTupleNamesAttribute(type As TypeSymbol) As SynthesizedAttributeData
Debug.Assert(type IsNot Nothing)
Debug.Assert(type.ContainsTuple())
Dim stringType = GetSpecialType(SpecialType.System_String)
Debug.Assert(stringType IsNot Nothing)
Dim names As ImmutableArray(Of TypedConstant) = TupleNamesEncoder.Encode(type, stringType)
Debug.Assert(Not names.IsDefault, "should not need the attribute when no tuple names")
Dim stringArray = ArrayTypeSymbol.CreateSZArray(stringType, ImmutableArray(Of CustomModifier).Empty, stringType.ContainingAssembly)
Dim args = ImmutableArray.Create(New TypedConstant(stringArray, names))
Return TrySynthesizeAttribute(WellKnownMember.System_Runtime_CompilerServices_TupleElementNamesAttribute__ctorTransformNames, args)
End Function
Friend Class TupleNamesEncoder
Public Shared Function Encode(type As TypeSymbol) As ImmutableArray(Of String)
Dim namesBuilder = ArrayBuilder(Of String).GetInstance()
If Not TryGetNames(type, namesBuilder) Then
namesBuilder.Free()
Return Nothing
End If
Return namesBuilder.ToImmutableAndFree()
End Function
Public Shared Function Encode(type As TypeSymbol, stringType As TypeSymbol) As ImmutableArray(Of TypedConstant)
Dim namesBuilder = ArrayBuilder(Of String).GetInstance()
If Not TryGetNames(type, namesBuilder) Then
namesBuilder.Free()
Return Nothing
End If
Dim names = namesBuilder.SelectAsArray(Function(name, constantType)
Return New TypedConstant(constantType, TypedConstantKind.Primitive, name)
End Function,
stringType)
namesBuilder.Free()
Return names
End Function
Friend Shared Function TryGetNames(type As TypeSymbol, namesBuilder As ArrayBuilder(Of String)) As Boolean
type.VisitType(Function(t As TypeSymbol, builder As ArrayBuilder(Of String)) AddNames(t, builder), namesBuilder)
Return namesBuilder.Any(Function(name) name IsNot Nothing)
End Function
Private Shared Function AddNames(type As TypeSymbol, namesBuilder As ArrayBuilder(Of String)) As Boolean
If type.IsTupleType Then
If type.TupleElementNames.IsDefaultOrEmpty Then
' If none of the tuple elements have names, put
' null placeholders in.
namesBuilder.AddMany(Nothing, type.TupleElementTypes.Length)
Else
namesBuilder.AddRange(type.TupleElementNames)
End If
End If
' Always recur into nested types
Return False
End Function
End Class
End Class
End Namespace
|