/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Symbols/Metadata/PE/PEParameterSymbol.vb
678 строк
28 KB
AlekseyTs
Use ParamCollectionAttribute to mark params collections in metadata (#71747)
26 янв 2024, 04:46
Не верифицирован
26 янв 2024, 04:46
ba5ee92
Код
Авторство
О чём код?
' 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 System.Reflection Imports System.Reflection.Metadata Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports System.Reflection.Metadata.Ecma335 Imports Microsoft.CodeAnalysis.VisualBasic.Emit Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE ''' <summary> ''' The class to represent all types imported from a PE/module. ''' </summary> ''' <remarks></remarks> Friend Class PEParameterSymbol Inherits ParameterSymbol Private ReadOnly _containingSymbol As Symbol Private ReadOnly _name As String Private ReadOnly _type As TypeSymbol Private ReadOnly _handle As ParameterHandle Private ReadOnly _flags As ParameterAttributes Private ReadOnly _ordinal As UShort ' Layout ' |.....|c|n|r| ' ' r = isByRef - 1 bit (bool) ' n = hasNameInMetadata - 1 bit (bool) ' c = hasOptionCompare - 1 bit (bool) Private ReadOnly _packed As Byte Private Const s_isByRefMask As Integer = &H1 Private Const s_hasNameInMetadataMask As Integer = &H2 Private Const s_hasOptionCompareMask As Integer = &H4 Private _lazyCustomAttributes As ImmutableArray(Of VisualBasicAttributeData) Private _lazyDefaultValue As ConstantValue = ConstantValue.Unset ' TODO: We should consider merging these in a single bit field Private _lazyHasIDispatchConstantAttribute As ThreeState = ThreeState.Unknown Private _lazyHasIUnknownConstantAttribute As ThreeState = ThreeState.Unknown Private _lazyHasCallerLineNumberAttribute As ThreeState = ThreeState.Unknown Private _lazyHasCallerMemberNameAttribute As ThreeState = ThreeState.Unknown Private _lazyHasCallerFilePathAttribute As ThreeState = ThreeState.Unknown Private Const UninitializedCallerArgumentExpressionParameterIndex As Integer = Integer.MinValue ''' <summary> ''' The index of a CallerArgumentExpression. The value <see cref="UninitializedCallerArgumentExpressionParameterIndex"/> means uninitialized, -1 means ''' Not found. Otherwise, the index of the CallerArgumentExpression. ''' </summary> Private _lazyCallerArgumentExpressionParameterIndex As Integer = UninitializedCallerArgumentExpressionParameterIndex Private _lazyIsParamArray As ThreeState ''' <summary> ''' Attributes filtered out from m_lazyCustomAttributes, ParamArray, etc. ''' </summary> Private _lazyHiddenAttributes As ImmutableArray(Of VisualBasicAttributeData) Friend Shared Function Create( moduleSymbol As PEModuleSymbol, containingSymbol As PEMethodSymbol, ordinal As Integer, ByRef parameter As ParamInfo(Of TypeSymbol), <Out> ByRef isBad As Boolean ) As PEParameterSymbol Return Create(moduleSymbol, containingSymbol, ordinal, parameter.IsByRef, parameter.RefCustomModifiers, parameter.Type, parameter.Handle, parameter.CustomModifiers, isBad) End Function Friend Shared Function Create( containingSymbol As Symbol, name As String, isByRef As Boolean, refCustomModifiers As ImmutableArray(Of CustomModifier), type As TypeSymbol, handle As ParameterHandle, flags As ParameterAttributes, isParamArray As Boolean, hasOptionCompare As Boolean, ordinal As Integer, defaultValue As ConstantValue, customModifiers As ImmutableArray(Of CustomModifier) ) As PEParameterSymbol If customModifiers.IsEmpty AndAlso refCustomModifiers.IsEmpty Then Return New PEParameterSymbol(containingSymbol, name, isByRef, type, handle, flags, isParamArray, hasOptionCompare, ordinal, defaultValue) End If Return New PEParameterSymbolWithCustomModifiers(containingSymbol, name, isByRef, refCustomModifiers, type, handle, flags, isParamArray, hasOptionCompare, ordinal, defaultValue, customModifiers) End Function Private Sub New( containingSymbol As Symbol, name As String, isByRef As Boolean, type As TypeSymbol, handle As ParameterHandle, flags As ParameterAttributes, isParamArray As Boolean, hasOptionCompare As Boolean, ordinal As Integer, defaultValue As ConstantValue ) Debug.Assert(containingSymbol IsNot Nothing) Debug.Assert(ordinal >= 0) Debug.Assert(type IsNot Nothing) _containingSymbol = containingSymbol Dim hasNameInMetadata As Boolean _name = EnsureParameterNameNotEmpty(name, hasNameInMetadata) _type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, DirectCast(containingSymbol.ContainingModule, PEModuleSymbol)) _handle = handle _ordinal = CType(ordinal, UShort) _flags = flags _lazyIsParamArray = isParamArray.ToThreeState() _lazyDefaultValue = defaultValue _packed = Pack(isByRef, hasNameInMetadata, hasOptionCompare) Debug.Assert(ordinal = Me.Ordinal) Debug.Assert(isByRef = Me.IsByRef) Debug.Assert(hasOptionCompare = Me.HasOptionCompare) Debug.Assert(hasNameInMetadata = Me.HasNameInMetadata) End Sub Private Shared Function Create( moduleSymbol As PEModuleSymbol, containingSymbol As Symbol, ordinal As Integer, isByRef As Boolean, refCustomModifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol)), type As TypeSymbol, handle As ParameterHandle, customModifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol)), <Out> ByRef isBad As Boolean ) As PEParameterSymbol If customModifiers.IsDefaultOrEmpty AndAlso refCustomModifiers.IsDefaultOrEmpty Then Return New PEParameterSymbol(moduleSymbol, containingSymbol, ordinal, isByRef, type, handle, isBad) End If Return New PEParameterSymbolWithCustomModifiers(moduleSymbol, containingSymbol, ordinal, isByRef, refCustomModifiers, type, handle, customModifiers, isBad) End Function Private Sub New( moduleSymbol As PEModuleSymbol, containingSymbol As Symbol, ordinal As Integer, isByRef As Boolean, type As TypeSymbol, handle As ParameterHandle, <Out> ByRef isBad As Boolean ) Debug.Assert(moduleSymbol IsNot Nothing) Debug.Assert(containingSymbol IsNot Nothing) Debug.Assert(ordinal >= 0) Debug.Assert(type IsNot Nothing) isBad = False _containingSymbol = containingSymbol _type = TupleTypeDecoder.DecodeTupleTypesIfApplicable(type, handle, moduleSymbol) _ordinal = CType(ordinal, UShort) _handle = handle Dim hasOptionCompare As Boolean = False If handle.IsNil Then _lazyCustomAttributes = ImmutableArray(Of VisualBasicAttributeData).Empty _lazyHiddenAttributes = ImmutableArray(Of VisualBasicAttributeData).Empty _lazyHasIDispatchConstantAttribute = ThreeState.False _lazyHasIUnknownConstantAttribute = ThreeState.False _lazyDefaultValue = ConstantValue.NotAvailable _lazyHasCallerLineNumberAttribute = ThreeState.False _lazyHasCallerMemberNameAttribute = ThreeState.False _lazyHasCallerFilePathAttribute = ThreeState.False _lazyCallerArgumentExpressionParameterIndex = -1 _lazyIsParamArray = ThreeState.False Else Try moduleSymbol.Module.GetParamPropsOrThrow(handle, _name, _flags) Catch mrEx As BadImageFormatException isBad = True End Try hasOptionCompare = moduleSymbol.Module.HasAttribute(handle, AttributeDescription.OptionCompareAttribute) End If Dim hasNameInMetadata As Boolean _name = EnsureParameterNameNotEmpty(_name, hasNameInMetadata) _packed = Pack(isByRef, hasNameInMetadata, hasOptionCompare) Debug.Assert(isByRef = Me.IsByRef) Debug.Assert(hasOptionCompare = Me.HasOptionCompare) Debug.Assert(hasNameInMetadata = Me.HasNameInMetadata) End Sub Private NotInheritable Class PEParameterSymbolWithCustomModifiers Inherits PEParameterSymbol Private ReadOnly _customModifiers As ImmutableArray(Of CustomModifier) Private ReadOnly _refCustomModifiers As ImmutableArray(Of CustomModifier) Public Sub New( containingSymbol As Symbol, name As String, isByRef As Boolean, refCustomModifiers As ImmutableArray(Of CustomModifier), type As TypeSymbol, handle As ParameterHandle, flags As ParameterAttributes, isParamArray As Boolean, hasOptionCompare As Boolean, ordinal As Integer, defaultValue As ConstantValue, customModifiers As ImmutableArray(Of CustomModifier) ) MyBase.New(containingSymbol, name, isByRef, type, handle, flags, isParamArray, hasOptionCompare, ordinal, defaultValue) _customModifiers = customModifiers _refCustomModifiers = refCustomModifiers Debug.Assert(_refCustomModifiers.IsEmpty OrElse isByRef) End Sub Public Sub New( moduleSymbol As PEModuleSymbol, containingSymbol As Symbol, ordinal As Integer, isByRef As Boolean, refCustomModifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol)), type As TypeSymbol, handle As ParameterHandle, customModifiers As ImmutableArray(Of ModifierInfo(Of TypeSymbol)), <Out> ByRef isBad As Boolean ) MyBase.New(moduleSymbol, containingSymbol, ordinal, isByRef, type, handle, isBad) _customModifiers = VisualBasicCustomModifier.Convert(customModifiers) _refCustomModifiers = VisualBasicCustomModifier.Convert(refCustomModifiers) Debug.Assert(_refCustomModifiers.IsEmpty OrElse isByRef) End Sub Public Overrides ReadOnly Property RefCustomModifiers As ImmutableArray(Of CustomModifier) Get Return _refCustomModifiers End Get End Property Public Overrides ReadOnly Property CustomModifiers As ImmutableArray(Of CustomModifier) Get Return _customModifiers End Get End Property End Class Private Shared Function Pack(isByRef As Boolean, hasNameInMetadata As Boolean, hasOptionCompare As Boolean) As Byte Dim isByRefBits As Integer = If(isByRef, s_isByRefMask, 0) Dim hasNoNameInMetadataBits As Integer = If(hasNameInMetadata, s_hasNameInMetadataMask, 0) Dim hasOptionCompareBits As Integer = If(hasOptionCompare, s_hasOptionCompareMask, 0) Return CType(isByRefBits Or hasNoNameInMetadataBits Or hasOptionCompareBits, Byte) End Function Private Shared Function EnsureParameterNameNotEmpty(name As String, <Out> ByRef hasNameInMetadata As Boolean) As String hasNameInMetadata = Not String.IsNullOrEmpty(name) Return If(hasNameInMetadata, name, "Param") End Function Private ReadOnly Property HasNameInMetadata As Boolean Get Return (_packed And s_hasNameInMetadataMask) <> 0 End Get End Property Public Overrides ReadOnly Property MetadataName As String Get Return If(HasNameInMetadata, _name, String.Empty) End Get End Property Public Overrides ReadOnly Property MetadataToken As Integer Get Return MetadataTokens.GetToken(_handle) End Get End Property Public Overrides ReadOnly Property Name As String Get Return _name End Get End Property Friend ReadOnly Property ParamFlags As ParameterAttributes Get Return _flags End Get End Property Public Overrides ReadOnly Property Ordinal As Integer Get Return _ordinal End Get End Property Public Overrides ReadOnly Property ContainingSymbol As Symbol Get Return _containingSymbol End Get End Property Friend Overrides ReadOnly Property HasMetadataConstantValue As Boolean Get Return (_flags And ParameterAttributes.HasDefault) <> 0 End Get End Property Friend Overrides ReadOnly Property ExplicitDefaultConstantValue(inProgress As SymbolsInProgress(Of ParameterSymbol)) As ConstantValue Get If _lazyDefaultValue Is ConstantValue.Unset Then Debug.Assert(Not _handle.IsNil) Dim defaultValue As ConstantValue = ConstantValue.NotAvailable Dim peModule = Me.PEModule Dim handle = Me._handle If (_flags And ParameterAttributes.HasDefault) <> 0 Then defaultValue = peModule.GetParamDefaultValue(handle) ElseIf IsOptional ' Dev10 behavior just checks for Decimal then DateTime. If both are specified, DateTime wins ' regardless of the parameter's type. If Not peModule.HasDateTimeConstantAttribute(handle, defaultValue) Then peModule.HasDecimalConstantAttribute(handle, defaultValue) End If End If Interlocked.CompareExchange(_lazyDefaultValue, defaultValue, ConstantValue.Unset) End If Return _lazyDefaultValue End Get End Property Friend Overrides ReadOnly Property IsMetadataOptional As Boolean Get Return (_flags And ParameterAttributes.Optional) <> 0 End Get End Property Public Overloads Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData) If _lazyCustomAttributes.IsDefault Then Debug.Assert(Not _handle.IsNil) Dim containingPEModuleSymbol = DirectCast(_containingSymbol.ContainingModule, PEModuleSymbol) ' Filter out ParamArrayAttributes if necessary and cache the attribute handle ' for GetCustomAttributesToEmit Dim filterOutParamArrayAttribute As Boolean = (Not _lazyIsParamArray.HasValue() OrElse _lazyIsParamArray.Value()) Dim defaultValue As ConstantValue = Me.ExplicitDefaultConstantValue Dim filterOutConstantAttributeDescription As AttributeDescription = Nothing If defaultValue IsNot Nothing Then If defaultValue.Discriminator = ConstantValueTypeDiscriminator.DateTime Then filterOutConstantAttributeDescription = AttributeDescription.DateTimeConstantAttribute ElseIf defaultValue.Discriminator = ConstantValueTypeDiscriminator.Decimal Then filterOutConstantAttributeDescription = AttributeDescription.DecimalConstantAttribute End If End If If filterOutParamArrayAttribute OrElse filterOutConstantAttributeDescription.Signatures IsNot Nothing Then Dim paramArrayAttribute As CustomAttributeHandle Dim constantAttribute As CustomAttributeHandle Dim attributes = containingPEModuleSymbol.GetCustomAttributesForToken( _handle, paramArrayAttribute, If(filterOutParamArrayAttribute, AttributeDescription.ParamArrayAttribute, Nothing), constantAttribute, filterOutConstantAttributeDescription) If Not paramArrayAttribute.IsNil OrElse Not constantAttribute.IsNil Then Dim builder = ArrayBuilder(Of VisualBasicAttributeData).GetInstance() If Not paramArrayAttribute.IsNil Then builder.Add(New PEAttributeData(containingPEModuleSymbol, paramArrayAttribute)) End If If Not constantAttribute.IsNil Then builder.Add(New PEAttributeData(containingPEModuleSymbol, constantAttribute)) End If ImmutableInterlocked.InterlockedInitialize(_lazyHiddenAttributes, builder.ToImmutableAndFree()) Else ImmutableInterlocked.InterlockedInitialize(_lazyHiddenAttributes, ImmutableArray(Of VisualBasicAttributeData).Empty) End If If Not _lazyIsParamArray.HasValue() Then Debug.Assert(filterOutParamArrayAttribute) _lazyIsParamArray = (Not paramArrayAttribute.IsNil).ToThreeState() End If ImmutableInterlocked.InterlockedInitialize(_lazyCustomAttributes, attributes) Else ImmutableInterlocked.InterlockedInitialize(_lazyHiddenAttributes, ImmutableArray(Of VisualBasicAttributeData).Empty) containingPEModuleSymbol.LoadCustomAttributes(_handle, _lazyCustomAttributes) End If End If Debug.Assert(Not _lazyHiddenAttributes.IsDefault) Return _lazyCustomAttributes End Function Friend Overrides Iterator Function GetCustomAttributesToEmit(moduleBuilder As PEModuleBuilder) As IEnumerable(Of VisualBasicAttributeData) For Each attribute In GetAttributes() Yield attribute Next ' Yield hidden attributes last, order might be important. For Each attribute In _lazyHiddenAttributes Yield attribute Next End Function Public Overrides ReadOnly Property HasExplicitDefaultValue As Boolean Get Return IsOptional AndAlso ExplicitDefaultConstantValue IsNot Nothing End Get End Property Public Overrides ReadOnly Property IsOptional As Boolean Get Return (_flags And ParameterAttributes.Optional) <> 0 End Get End Property Public Overrides ReadOnly Property IsParamArray As Boolean Get If Not _lazyIsParamArray.HasValue() Then _lazyIsParamArray = Me.PEModule.HasParamArrayAttribute(_handle).ToThreeState() End If Return _lazyIsParamArray.Value() End Get End Property Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location) Get Return _containingSymbol.Locations End Get End Property Public Overrides ReadOnly Property DeclaringSyntaxReferences As ImmutableArray(Of SyntaxReference) Get Return ImmutableArray(Of SyntaxReference).Empty End Get End Property Public Overrides ReadOnly Property Type As TypeSymbol Get Return _type End Get End Property Public Overrides ReadOnly Property IsByRef As Boolean Get Return (_packed And s_isByRefMask) <> 0 End Get End Property Friend Overrides ReadOnly Property IsExplicitByRef As Boolean Get Return IsByRef End Get End Property Friend Overrides ReadOnly Property IsMetadataOut As Boolean Get Return (_flags And ParameterAttributes.Out) <> 0 End Get End Property Friend Overrides ReadOnly Property IsMetadataIn As Boolean Get Return (_flags And ParameterAttributes.In) <> 0 End Get End Property Friend Overrides ReadOnly Property HasOptionCompare As Boolean Get Return (_packed And s_hasOptionCompareMask) <> 0 End Get End Property Public Overrides ReadOnly Property CustomModifiers As ImmutableArray(Of CustomModifier) Get Return ImmutableArray(Of CustomModifier).Empty End Get End Property Public Overrides ReadOnly Property RefCustomModifiers As ImmutableArray(Of CustomModifier) Get Return ImmutableArray(Of CustomModifier).Empty End Get End Property Friend Overrides ReadOnly Property IsMarshalledExplicitly As Boolean Get Return (_flags And ParameterAttributes.HasFieldMarshal) <> 0 End Get End Property Friend Overrides ReadOnly Property MarshallingInformation As MarshalPseudoCustomAttributeData Get ' the compiler doesn't need full marshalling information, just the unmanaged type Return Nothing End Get End Property Friend Overrides ReadOnly Property MarshallingDescriptor As ImmutableArray(Of Byte) Get If (_flags And ParameterAttributes.HasFieldMarshal) = 0 Then Return Nothing End If Debug.Assert(Not _handle.IsNil) Return Me.PEModule.GetMarshallingDescriptor(_handle) End Get End Property Friend Overrides ReadOnly Property MarshallingType As UnmanagedType Get If (_flags And ParameterAttributes.HasFieldMarshal) = 0 Then Return Nothing End If Debug.Assert(Not _handle.IsNil) Return Me.PEModule.GetMarshallingType(_handle) End Get End Property ' May be Nil Friend ReadOnly Property Handle As ParameterHandle Get Return _handle End Get End Property Friend Overrides ReadOnly Property IsIDispatchConstant As Boolean Get If _lazyHasIDispatchConstantAttribute = ThreeState.Unknown Then Debug.Assert(Not _handle.IsNil) _lazyHasIDispatchConstantAttribute = Me.PEModule. HasAttribute(_handle, AttributeDescription.IDispatchConstantAttribute).ToThreeState() End If Return _lazyHasIDispatchConstantAttribute.Value End Get End Property Friend Overrides ReadOnly Property IsIUnknownConstant As Boolean Get If _lazyHasIUnknownConstantAttribute = ThreeState.Unknown Then Debug.Assert(Not _handle.IsNil) _lazyHasIUnknownConstantAttribute = Me.PEModule. HasAttribute(_handle, AttributeDescription.IUnknownConstantAttribute).ToThreeState() End If Return _lazyHasIUnknownConstantAttribute.Value End Get End Property Friend Overrides ReadOnly Property IsCallerLineNumber As Boolean Get If _lazyHasCallerLineNumberAttribute = ThreeState.Unknown Then Debug.Assert(Not _handle.IsNil) _lazyHasCallerLineNumberAttribute = Me.PEModule. HasAttribute(_handle, AttributeDescription.CallerLineNumberAttribute).ToThreeState() End If Return _lazyHasCallerLineNumberAttribute.Value End Get End Property Friend Overrides ReadOnly Property IsCallerMemberName As Boolean Get If _lazyHasCallerMemberNameAttribute = ThreeState.Unknown Then Debug.Assert(Not _handle.IsNil) _lazyHasCallerMemberNameAttribute = Me.PEModule. HasAttribute(_handle, AttributeDescription.CallerMemberNameAttribute).ToThreeState() End If Return _lazyHasCallerMemberNameAttribute.Value End Get End Property Friend Overrides ReadOnly Property IsCallerFilePath As Boolean Get If _lazyHasCallerFilePathAttribute = ThreeState.Unknown Then Debug.Assert(Not _handle.IsNil) _lazyHasCallerFilePathAttribute = Me.PEModule. HasAttribute(_handle, AttributeDescription.CallerFilePathAttribute).ToThreeState() End If Return _lazyHasCallerFilePathAttribute.Value End Get End Property Friend Overrides ReadOnly Property CallerArgumentExpressionParameterIndex As Integer Get If _lazyCallerArgumentExpressionParameterIndex = UninitializedCallerArgumentExpressionParameterIndex Then Debug.Assert(Not _handle.IsNil) Dim attribute = PEModule.FindTargetAttribute(_handle, AttributeDescription.CallerArgumentExpressionAttribute) Dim parameterName As String = Nothing If attribute.HasValue AndAlso PEModule.TryExtractStringValueFromAttribute(attribute.Handle, parameterName) Then Dim parameters = ContainingSymbol.GetParameters() For i = 0 To parameters.Length - 1 If IdentifierComparison.Equals(parameters(i).Name, parameterName) Then _lazyCallerArgumentExpressionParameterIndex = i Exit For End If Next Else _lazyCallerArgumentExpressionParameterIndex = -1 End If End If Return _lazyCallerArgumentExpressionParameterIndex End Get End Property ''' <remarks> ''' This is for perf, not for correctness. ''' </remarks> Friend Overrides ReadOnly Property DeclaringCompilation As VisualBasicCompilation Get Return Nothing End Get End Property Private ReadOnly Property PEModule As PEModule Get Return DirectCast(_containingSymbol.ContainingModule, PEModuleSymbol).Module End Get End Property Friend Function DeriveCompilerFeatureRequiredDiagnostic(decoder As MetadataDecoder) As DiagnosticInfo Return DeriveCompilerFeatureRequiredAttributeDiagnostic(Me, DirectCast(Me.ContainingModule, PEModuleSymbol), Handle, CompilerFeatureRequiredFeatures.None, decoder) End Function Public Overrides ReadOnly Property HasUnsupportedMetadata As Boolean Get Dim containingModule = DirectCast(Me.ContainingModule, PEModuleSymbol) Dim containingMethod = TryCast(Me.ContainingSymbol, PEMethodSymbol) Dim decoder = If(containingMethod IsNot Nothing, New MetadataDecoder(containingModule, containingMethod), New MetadataDecoder(containingModule, DirectCast(ContainingType, PENamedTypeSymbol))) Dim info = DeriveCompilerFeatureRequiredDiagnostic(decoder) Return (info IsNot Nothing AndAlso (info.Code = ERRID.ERR_UnsupportedType1 OrElse info.Code = ERRID.ERR_UnsupportedCompilerFeature)) OrElse MyBase.HasUnsupportedMetadata End Get End Property End Class End Namespace