/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Symbols/Attributes/SourceAttributeData.vb
310 строк
13 KB
AlekseyTs
Ensure errors are reported when compiler is unable to emit a required attribute. (#70556)
27 окт 2023, 01:26
Не верифицирован
27 окт 2023, 01:26
06072fb
Код
Авторство
О чём код?
' 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 Imports System.Collections.Generic Imports System.Collections.Immutable Imports Microsoft.Cci Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic Imports Microsoft.CodeAnalysis.VisualBasic.Emit Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports System.Reflection.Metadata Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols Friend NotInheritable Class SourceAttributeData Inherits VisualBasicAttributeData Private ReadOnly _compilation As VisualBasicCompilation Private ReadOnly _attributeClass As NamedTypeSymbol ' TODO - Remove attribute class. It is available from the constructor. Private ReadOnly _attributeConstructor As MethodSymbol Private ReadOnly _constructorArguments As ImmutableArray(Of TypedConstant) Private ReadOnly _namedArguments As ImmutableArray(Of KeyValuePair(Of String, TypedConstant)) Private ReadOnly _isConditionallyOmitted As Boolean Private ReadOnly _hasErrors As Boolean Private ReadOnly _applicationNode As SyntaxReference Friend Sub New(ByVal compilation As VisualBasicCompilation, ByVal applicationNode As SyntaxReference, ByVal attrClass As NamedTypeSymbol, ByVal attrMethod As MethodSymbol, ByVal constructorArgs As ImmutableArray(Of TypedConstant), ByVal namedArgs As ImmutableArray(Of KeyValuePair(Of String, TypedConstant)), ByVal isConditionallyOmitted As Boolean, ByVal hasErrors As Boolean) Debug.Assert(compilation IsNot Nothing) Debug.Assert(applicationNode IsNot Nothing) Debug.Assert(attrMethod IsNot Nothing OrElse hasErrors) Me._compilation = compilation Me._applicationNode = applicationNode Me._attributeClass = attrClass Me._attributeConstructor = attrMethod Me._constructorArguments = constructorArgs.NullToEmpty() Me._namedArguments = If(namedArgs.IsDefault, ImmutableArray.Create(Of KeyValuePair(Of String, TypedConstant))(), namedArgs) Me._isConditionallyOmitted = isConditionallyOmitted Me._hasErrors = hasErrors End Sub Public Overrides ReadOnly Property AttributeClass As NamedTypeSymbol Get Return _attributeClass End Get End Property Public Overrides ReadOnly Property AttributeConstructor As MethodSymbol Get Return _attributeConstructor End Get End Property Public Overrides ReadOnly Property ApplicationSyntaxReference As SyntaxReference Get Return _applicationNode End Get End Property Protected Overrides ReadOnly Property CommonConstructorArguments As ImmutableArray(Of TypedConstant) Get Return _constructorArguments End Get End Property Protected Overrides ReadOnly Property CommonNamedArguments As ImmutableArray(Of KeyValuePair(Of String, TypedConstant)) Get Return _namedArguments End Get End Property Friend Overrides ReadOnly Property IsConditionallyOmitted As Boolean Get Return _isConditionallyOmitted End Get End Property Friend Function WithOmittedCondition(isConditionallyOmitted As Boolean) As SourceAttributeData If Me.IsConditionallyOmitted = isConditionallyOmitted Then Return Me End If Return New SourceAttributeData(Me._compilation, Me.ApplicationSyntaxReference, Me.AttributeClass, Me.AttributeConstructor, Me.CommonConstructorArguments, Me.CommonNamedArguments, isConditionallyOmitted, Me.HasErrors) End Function Friend Overrides ReadOnly Property HasErrors As Boolean Get Return _hasErrors End Get End Property Friend Overrides ReadOnly Property ErrorInfo As DiagnosticInfo Get Return Nothing ' Binder reports errors End Get End Property ''' <summary> ''' This method finds an attribute by metadata name and signature. The algorithm for signature matching is similar to the one ''' in Module.GetTargetAttributeSignatureIndex. Note, the signature matching is limited to primitive types ''' and System.Type. It will not match an arbitrary signature but it is sufficient to match the signatures of the current set of ''' well known attributes. ''' </summary> ''' <param name="description">Attribute to match.</param> Friend Overrides Function GetTargetAttributeSignatureIndex(description As AttributeDescription) As Integer Return GetTargetAttributeSignatureIndex(_compilation, AttributeClass, AttributeConstructor, description) End Function Friend Overloads Shared Function GetTargetAttributeSignatureIndex(compilation As VisualBasicCompilation, attributeClass As NamedTypeSymbol, attributeConstructor As MethodSymbol, description As AttributeDescription) As Integer If Not IsTargetAttribute(attributeClass, description.Namespace, description.Name, description.MatchIgnoringCase) Then Return -1 End If Dim lazySystemType As TypeSymbol = Nothing Dim ctor = attributeConstructor ' Ensure that the attribute data really has a constructor before comparing the signature. If ctor Is Nothing Then Return -1 End If Dim parameters = ctor.Parameters Dim foundMatch = False For i = 0 To description.Signatures.Length - 1 Dim targetSignature = description.Signatures(i) If targetSignature(0) <> SignatureAttributes.Instance Then Continue For End If Dim parameterCount = targetSignature(1) If parameterCount <> parameters.Length Then Continue For End If If CType(targetSignature(2), SignatureTypeCode) <> SignatureTypeCode.Void Then Continue For End If foundMatch = (targetSignature.Length = 3) Dim k = 0 For j = 3 To targetSignature.Length - 1 If k >= parameters.Length Then Exit For End If Dim parameterType As TypeSymbol = parameters(k).Type Dim specType = parameterType.GetEnumUnderlyingTypeOrSelf.SpecialType Dim targetType As Byte = targetSignature(j) If targetType = SignatureTypeCode.TypeHandle Then j += 1 If parameterType.Kind <> SymbolKind.NamedType AndAlso parameterType.Kind <> SymbolKind.ErrorType Then foundMatch = False Exit For End If Dim namedType = DirectCast(parameterType, NamedTypeSymbol) Dim targetInfo As AttributeDescription.TypeHandleTargetInfo = AttributeDescription.TypeHandleTargets(targetSignature(j)) ' Compare name and containing symbol name. Uses HasNameQualifier ' extension method to avoid string allocations. If Not String.Equals(namedType.MetadataName, targetInfo.Name, StringComparison.Ordinal) OrElse Not namedType.HasNameQualifier(targetInfo.Namespace, StringComparison.Ordinal) Then foundMatch = False Exit For End If targetType = CByte(targetInfo.Underlying) ElseIf parameterType.IsArrayType Then specType = DirectCast(parameterType, ArrayTypeSymbol).ElementType.SpecialType End If Select Case targetType Case CByte(SignatureTypeCode.Boolean) foundMatch = specType = SpecialType.System_Boolean k += 1 Case CByte(SignatureTypeCode.Char) foundMatch = specType = SpecialType.System_Char k += 1 Case CByte(SignatureTypeCode.SByte) foundMatch = specType = SpecialType.System_SByte k += 1 Case CByte(SignatureTypeCode.Byte) foundMatch = specType = SpecialType.System_Byte k += 1 Case CByte(SignatureTypeCode.Int16) foundMatch = specType = SpecialType.System_Int16 k += 1 Case CByte(SignatureTypeCode.UInt16) foundMatch = specType = SpecialType.System_UInt16 k += 1 Case CByte(SignatureTypeCode.Int32) foundMatch = specType = SpecialType.System_Int32 k += 1 Case CByte(SignatureTypeCode.UInt32) foundMatch = specType = SpecialType.System_UInt32 k += 1 Case CByte(SignatureTypeCode.Int64) foundMatch = specType = SpecialType.System_Int64 k += 1 Case CByte(SignatureTypeCode.UInt64) foundMatch = specType = SpecialType.System_UInt64 k += 1 Case CByte(SignatureTypeCode.Single) foundMatch = specType = SpecialType.System_Single k += 1 Case CByte(SignatureTypeCode.Double) foundMatch = specType = SpecialType.System_Double k += 1 Case CByte(SignatureTypeCode.String) foundMatch = specType = SpecialType.System_String k += 1 Case CByte(SignatureTypeCode.Object) foundMatch = specType = SpecialType.System_Object k += 1 Case CByte(SerializationTypeCode.Type) If lazySystemType Is Nothing Then lazySystemType = compilation.GetWellKnownType(WellKnownType.System_Type) End If foundMatch = TypeSymbol.Equals(parameterType, lazySystemType, TypeCompareKind.ConsiderEverything) k += 1 Case CByte(SignatureTypeCode.SZArray) ' skip over and check the next byte foundMatch = parameterType.IsArrayType Case Else Return -1 End Select If Not foundMatch Then Exit For End If Next If foundMatch Then Return i End If Next Debug.Assert(Not foundMatch) Return -1 End Function ''' <summary> ''' Compares the namespace and type name with the attribute's namespace and type name. Returns true if they are the same. ''' </summary> Friend Overrides Function IsTargetAttribute( namespaceName As String, typeName As String, Optional ignoreCase As Boolean = False ) As Boolean Return IsTargetAttribute(AttributeClass, namespaceName, typeName, ignoreCase) End Function Friend Overloads Shared Function IsTargetAttribute( attributeClass As NamedTypeSymbol, namespaceName As String, typeName As String, Optional ignoreCase As Boolean = False ) As Boolean If attributeClass.IsErrorType() AndAlso Not TypeOf attributeClass Is MissingMetadataTypeSymbol Then ' Can't guarantee complete name information. Return False End If Dim options As StringComparison = If(ignoreCase, StringComparison.OrdinalIgnoreCase, StringComparison.Ordinal) Return attributeClass.HasNameQualifier(namespaceName, options) AndAlso attributeClass.Name.Equals(typeName, options) End Function End Class End Namespace