/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Symbols/Symbol_Attributes.vb
642 строки
36 KB
Tomáš Matoušek
Report error when MetadataUpdateDeletedAttribute is applied manually (#80125)
17 сен 2025, 00:09
Не верифицирован
17 сен 2025, 00:09
a4d213a
Код
Авторство
О чём код?
' 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.Generic Imports System.Collections.Immutable Imports System.Runtime.InteropServices Imports System.Threading Imports Microsoft.CodeAnalysis.Collections Imports Microsoft.CodeAnalysis.PooledObjects Imports Microsoft.CodeAnalysis.VisualBasic.Emit Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Imports TypeKind = Microsoft.CodeAnalysis.TypeKind Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend Class Symbol ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ' Changes to the public interface of this class should remain synchronized with the C# version of Symbol. ' Do not make any changes to the public interface without making the corresponding change ' to the C# version. ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ''' <summary> ''' Gets the attributes on this symbol. Returns an empty ImmutableArray if there are ''' no attributes. ''' </summary> Public Overridable Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData) Return ImmutableArray(Of VisualBasicAttributeData).Empty End Function ''' <summary> ''' Build and add synthesized attributes for this symbol. ''' </summary> Friend Overridable Sub AddSynthesizedAttributes(moduleBuilder As PEModuleBuilder, ByRef attributes As ArrayBuilder(Of VisualBasicAttributeData)) End Sub ''' <summary> ''' Convenience helper called by subclasses to add a synthesized attribute to a collection of attributes. ''' </summary> Friend Shared Sub AddSynthesizedAttribute(ByRef attributes As ArrayBuilder(Of VisualBasicAttributeData), attribute As VisualBasicAttributeData) If attribute IsNot Nothing Then If attributes Is Nothing Then attributes = ArrayBuilder(Of VisualBasicAttributeData).GetInstance(4) End If attributes.Add(attribute) End If End Sub ''' <summary> ''' Returns the appropriate AttributeTarget for a symbol. This is used to validate attribute usage when ''' applying an attribute to a symbol. For any symbol that does not support the application of custom ''' attributes 0 is returned. ''' </summary> ''' <returns>The attribute target flag for this symbol or 0 if none apply.</returns> ''' <remarks></remarks> Friend Function GetAttributeTarget() As AttributeTargets Select Case Kind Case SymbolKind.Assembly Return AttributeTargets.Assembly Case SymbolKind.Event Return AttributeTargets.Event Case SymbolKind.Field Return AttributeTargets.Field Case SymbolKind.Method Dim method = DirectCast(Me, MethodSymbol) Select Case method.MethodKind Case MethodKind.Constructor, MethodKind.SharedConstructor Return AttributeTargets.Constructor Case MethodKind.Ordinary, MethodKind.DeclareMethod, MethodKind.UserDefinedOperator, MethodKind.Conversion, MethodKind.PropertyGet, MethodKind.PropertySet, MethodKind.EventAdd, MethodKind.EventRaise, MethodKind.EventRemove, MethodKind.DelegateInvoke Return AttributeTargets.Method End Select Case SymbolKind.Property Return AttributeTargets.Property Case SymbolKind.NamedType Dim namedType = DirectCast(Me, NamedTypeSymbol) Select Case namedType.TypeKind Case TypeKind.Class, TypeKind.Module Return AttributeTargets.Class Case TypeKind.Structure Return AttributeTargets.Struct Case TypeKind.Interface Return AttributeTargets.Interface Case TypeKind.Enum Return AttributeTargets.Enum Or AttributeTargets.Struct Case TypeKind.Delegate Return AttributeTargets.Delegate Case TypeKind.Submission ' attributes can't be applied on a submission type Throw ExceptionUtilities.UnexpectedValue(namedType.TypeKind) End Select Case SymbolKind.NetModule Return AttributeTargets.Module Case SymbolKind.Parameter Return AttributeTargets.Parameter Case SymbolKind.TypeParameter Return AttributeTargets.GenericParameter End Select Return 0 End Function ''' <summary> ''' Method to early decode applied well-known attribute which can be queried by the binder. ''' This method is called during attribute binding after we have bound the attribute types for all attributes, ''' but haven't yet bound the attribute arguments/attribute constructor. ''' Early decoding certain well-known attributes enables the binder to use this decoded information on this symbol ''' when binding the attribute arguments/attribute constructor without causing attribute binding cycle. ''' </summary> Friend Overridable Function EarlyDecodeWellKnownAttribute(ByRef arguments As EarlyDecodeWellKnownAttributeArguments(Of EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation)) As VisualBasicAttributeData Return Nothing End Function Friend Function EarlyDecodeDeprecatedOrExperimentalOrObsoleteAttribute( ByRef arguments As EarlyDecodeWellKnownAttributeArguments(Of EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation), <Out> ByRef boundAttribute As VisualBasicAttributeData, <Out> ByRef obsoleteData As ObsoleteAttributeData ) As Boolean Dim type = arguments.AttributeType Dim syntax = arguments.AttributeSyntax Dim kind As ObsoleteAttributeKind If VisualBasicAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.ObsoleteAttribute) Then kind = ObsoleteAttributeKind.Obsolete ElseIf VisualBasicAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.DeprecatedAttribute) Then kind = ObsoleteAttributeKind.Deprecated ElseIf VisualBasicAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.WindowsExperimentalAttribute) Then kind = ObsoleteAttributeKind.WindowsExperimental ElseIf VisualBasicAttributeData.IsTargetEarlyAttribute(type, syntax, AttributeDescription.ExperimentalAttribute) Then kind = ObsoleteAttributeKind.Experimental Else boundAttribute = Nothing obsoleteData = Nothing Return False End If Dim hasAnyDiagnostics As Boolean = False boundAttribute = arguments.Binder.GetAttribute(syntax, type, hasAnyDiagnostics) If Not boundAttribute.HasErrors Then obsoleteData = boundAttribute.DecodeObsoleteAttribute(kind) If hasAnyDiagnostics Then boundAttribute = Nothing End If Else obsoleteData = Nothing boundAttribute = Nothing End If Return True End Function ''' <summary> ''' This method is called by the binder when it is finished binding a set of attributes on the symbol so that ''' the symbol can extract data from the attribute arguments and potentially perform validation specific to ''' some well known attributes. ''' </summary> ''' <remarks> ''' <para> ''' Symbol types should override this if they want to handle a specific well-known attribute. ''' If the attribute is of a type that the symbol does not wish to handle, it should delegate back to ''' this (base) method. ''' </para> ''' </remarks> Friend Overridable Sub DecodeWellKnownAttribute(ByRef arguments As DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation)) Dim compilation = Me.DeclaringCompilation MarkEmbeddedAttributeTypeReference(arguments.Attribute, arguments.AttributeSyntaxOpt, compilation) ReportExtensionAttributeUseSiteInfo(arguments.Attribute, arguments.AttributeSyntaxOpt, compilation, DirectCast(arguments.Diagnostics, BindingDiagnosticBag)) If arguments.Attribute.IsTargetAttribute(AttributeDescription.SkipLocalsInitAttribute) Then DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.WRN_AttributeNotSupportedInVB, arguments.AttributeSyntaxOpt.Location, AttributeDescription.SkipLocalsInitAttribute.FullName) ElseIf arguments.Attribute.IsTargetAttribute(AttributeDescription.CompilerFeatureRequiredAttribute) Then DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_DoNotUseCompilerFeatureRequired, arguments.AttributeSyntaxOpt.Location) ElseIf arguments.Attribute.IsTargetAttribute(AttributeDescription.RequiredMemberAttribute) Then DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_DoNotUseRequiredMember, arguments.AttributeSyntaxOpt.Location) ElseIf arguments.Attribute.IsTargetAttribute(AttributeDescription.ExperimentalAttribute) Then If Not SyntaxFacts.IsValidIdentifier(DirectCast(arguments.Attribute.CommonConstructorArguments(0).ValueInternal, String)) Then Dim attrArgumentLocation = VisualBasicAttributeData.GetFirstArgumentLocation(arguments.AttributeSyntaxOpt) DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_InvalidExperimentalDiagID, attrArgumentLocation) End If ElseIf arguments.Attribute.IsTargetAttribute(AttributeDescription.MetadataUpdateDeletedAttribute) Then arguments.Diagnostics.DiagnosticBag.Add(ERRID.ERR_AttributeCannotBeAppliedManually, arguments.AttributeSyntaxOpt.Location, AttributeDescription.MetadataUpdateDeletedAttribute.FullName) End If End Sub ''' <summary> ''' Called to report attribute related diagnostics after all attributes have been bound and decoded. ''' Called even if there are no attributes. ''' </summary> ''' <remarks> ''' This method is called by the binder from <see cref="LoadAndValidateAttributes"/> after it has finished binding attributes on the symbol, ''' has executed <see cref="DecodeWellKnownAttribute"/> for attributes applied on the symbol and has stored the decoded data in the ''' lazyCustomAttributesBag on the symbol. Bound attributes haven't been stored on the bag yet. ''' ''' Post-validation for attributes that is dependent on other attributes can be done here. ''' ''' This method should not have any side effects on the symbol, i.e. it SHOULD NOT change the symbol state. ''' </remarks> ''' <param name="boundAttributes">Bound attributes.</param> ''' <param name="allAttributeSyntaxNodes">Syntax nodes of attributes in order they are specified in source.</param> ''' <param name="diagnostics">Diagnostic bag.</param> ''' <param name="symbolPart">Specific part of the symbol to which the attributes apply, or <see cref="AttributeLocation.None"/> if the attributes apply to the symbol itself.</param> ''' <param name="decodedData">Decoded well known attribute data.</param> Friend Overridable Sub PostDecodeWellKnownAttributes(boundAttributes As ImmutableArray(Of VisualBasicAttributeData), allAttributeSyntaxNodes As ImmutableArray(Of AttributeSyntax), diagnostics As BindingDiagnosticBag, symbolPart As AttributeLocation, decodedData As WellKnownAttributeData) End Sub ''' <summary> ''' This method does the following set of operations in the specified order: ''' (1) GetAttributesToBind: Merge the given attributeBlockSyntaxList into a single list of attributes to bind. ''' (2) GetAttributes: Bind the attributes (attribute type, arguments and constructor). ''' (3) DecodeWellKnownAttributes: Decode and validate bound well-known attributes. ''' (4) ValidateAttributes: Perform some additional attribute validations, such as ''' 1) Duplicate attributes, ''' 2) Attribute usage target validation, etc. ''' (5) Store the bound attributes and decoded well-known attribute data in lazyCustomAttributesBag in a thread safe manner. ''' </summary> Friend Sub LoadAndValidateAttributes(attributeBlockSyntaxList As OneOrMany(Of SyntaxList(Of AttributeListSyntax)), ByRef lazyCustomAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData), Optional symbolPart As AttributeLocation = 0) Dim diagnostics = BindingDiagnosticBag.GetInstance() Dim sourceAssembly = DirectCast(If(Me.Kind = SymbolKind.Assembly, Me, Me.ContainingAssembly), SourceAssemblySymbol) Dim sourceModule = sourceAssembly.SourceModule Dim compilation = sourceAssembly.DeclaringCompilation Dim binders As ImmutableArray(Of Binder) = Nothing Dim attributesToBind = GetAttributesToBind(attributeBlockSyntaxList, symbolPart, compilation, binders) Dim boundAttributes As ImmutableArray(Of VisualBasicAttributeData) Dim wellKnownAttrData As WellKnownAttributeData If attributesToBind.Any() Then Debug.Assert(attributesToBind.Any()) Debug.Assert(binders.Any()) Debug.Assert(attributesToBind.Length = binders.Length) ' Initialize the bag so that data decoded from early attributes can be stored onto it. If (lazyCustomAttributesBag Is Nothing) Then Interlocked.CompareExchange(lazyCustomAttributesBag, New CustomAttributesBag(Of VisualBasicAttributeData)(), Nothing) End If Dim boundAttributeTypes As ImmutableArray(Of NamedTypeSymbol) = Binder.BindAttributeTypes(binders, attributesToBind, Me, diagnostics) Dim attributeBuilder = New VisualBasicAttributeData(boundAttributeTypes.Length - 1) {} ' Early bind and decode some well-known attributes. Dim earlyData As EarlyWellKnownAttributeData = Me.EarlyDecodeWellKnownAttributes(binders, boundAttributeTypes, attributesToBind, attributeBuilder, symbolPart) ' Store data decoded from early bound well-known attributes. lazyCustomAttributesBag.SetEarlyDecodedWellKnownAttributeData(earlyData) ' Bind attributes. Binder.GetAttributes(binders, attributesToBind, boundAttributeTypes, attributeBuilder, Me, diagnostics) boundAttributes = attributeBuilder.AsImmutableOrNull ' Validate attribute usage and Decode remaining well-known attributes. wellKnownAttrData = Me.ValidateAttributeUsageAndDecodeWellKnownAttributes(binders, attributesToBind, boundAttributes, diagnostics, symbolPart) ' Store data decoded from remaining well-known attributes. lazyCustomAttributesBag.SetDecodedWellKnownAttributeData(wellKnownAttrData) Else boundAttributes = ImmutableArray(Of VisualBasicAttributeData).Empty wellKnownAttrData = Nothing Interlocked.CompareExchange(lazyCustomAttributesBag, CustomAttributesBag(Of VisualBasicAttributeData).WithEmptyData(), Nothing) End If Me.PostDecodeWellKnownAttributes(boundAttributes, attributesToBind, diagnostics, symbolPart, wellKnownAttrData) ' Store attributes into the bag. sourceModule.AtomicStoreAttributesAndDiagnostics(lazyCustomAttributesBag, boundAttributes, diagnostics) diagnostics.Free() Debug.Assert(lazyCustomAttributesBag.IsSealed) End Sub Private Function GetAttributesToBind(attributeDeclarationSyntaxLists As OneOrMany(Of SyntaxList(Of AttributeListSyntax)), symbolPart As AttributeLocation, compilation As VisualBasicCompilation, <Out> ByRef binders As ImmutableArray(Of Binder)) As ImmutableArray(Of AttributeSyntax) Dim attributeTarget = DirectCast(Me, IAttributeTargetSymbol) Dim sourceModule = DirectCast(compilation.SourceModule, SourceModuleSymbol) Dim syntaxBuilder As ArrayBuilder(Of AttributeSyntax) = Nothing Dim bindersBuilder As ArrayBuilder(Of Binder) = Nothing Dim attributesToBindCount As Integer = 0 For listIndex = 0 To attributeDeclarationSyntaxLists.Count - 1 Dim attributeDeclarationSyntaxList As SyntaxList(Of AttributeListSyntax) = attributeDeclarationSyntaxLists(listIndex) If attributeDeclarationSyntaxList.Any() Then Dim prevCount As Integer = attributesToBindCount For Each attributeDeclarationSyntax In attributeDeclarationSyntaxList For Each attributeSyntax In attributeDeclarationSyntax.Attributes If MatchAttributeTarget(attributeTarget, symbolPart, attributeSyntax.Target) Then If syntaxBuilder Is Nothing Then syntaxBuilder = New ArrayBuilder(Of AttributeSyntax)() bindersBuilder = New ArrayBuilder(Of Binder)() End If syntaxBuilder.Add(attributeSyntax) attributesToBindCount += 1 End If Next Next If attributesToBindCount <> prevCount Then Debug.Assert(attributeDeclarationSyntaxList.Node IsNot Nothing) Debug.Assert(bindersBuilder IsNot Nothing) Dim binder = GetAttributeBinder(attributeDeclarationSyntaxList, sourceModule) For i = 0 To attributesToBindCount - prevCount - 1 bindersBuilder.Add(binder) Next End If End If Next If syntaxBuilder IsNot Nothing Then binders = bindersBuilder.ToImmutableAndFree() Return syntaxBuilder.ToImmutableAndFree() Else binders = ImmutableArray(Of Binder).Empty Return ImmutableArray(Of AttributeSyntax).Empty End If End Function Friend Function GetAttributeBinder(syntaxList As SyntaxList(Of AttributeListSyntax), sourceModule As SourceModuleSymbol) As Binder Dim syntaxTree = syntaxList.Node.SyntaxTree Dim parent = syntaxList.Node.Parent If parent.IsKind(SyntaxKind.AttributesStatement) AndAlso parent.Parent.IsKind(SyntaxKind.CompilationUnit) Then ' Create a binder for the file-level attributes. To avoid infinite recursion, the bound file information ' must be fully computed prior to trying to bind the file attributes. Return BinderBuilder.CreateBinderForProjectLevelNamespace(sourceModule, syntaxTree) Else Return BinderBuilder.CreateBinderForAttribute(sourceModule, syntaxTree, Me) End If End Function Private Shared Function MatchAttributeTarget(attributeTarget As IAttributeTargetSymbol, symbolPart As AttributeLocation, targetOpt As AttributeTargetSyntax) As Boolean If targetOpt Is Nothing Then Return True End If Dim explicitTarget As AttributeLocation ' Parser ensures that an error is reported for anything other than "assembly" or ' "module". Only assembly and module keywords can get here. Select Case targetOpt.AttributeModifier.Kind Case SyntaxKind.AssemblyKeyword explicitTarget = AttributeLocation.Assembly Case SyntaxKind.ModuleKeyword explicitTarget = AttributeLocation.Module Case Else Throw ExceptionUtilities.UnexpectedValue(targetOpt.AttributeModifier.Kind) End Select If symbolPart = 0 Then Return explicitTarget = attributeTarget.DefaultAttributeLocation Else Return explicitTarget = symbolPart End If End Function Friend Shared Sub GetAttributesToBind(attributeBlockSyntaxList As SyntaxList(Of AttributeListSyntax), ByRef attributeSyntaxBuilder As ArrayBuilder(Of AttributeSyntax)) If attributeBlockSyntaxList.Count > 0 Then If attributeSyntaxBuilder Is Nothing Then attributeSyntaxBuilder = ArrayBuilder(Of AttributeSyntax).GetInstance() End If For Each attributeBlock In attributeBlockSyntaxList attributeSyntaxBuilder.AddRange(attributeBlock.Attributes) Next End If End Sub ''' <summary> ''' Method to early decode certain well-known attributes which can be queried by the binder. ''' This method is called during attribute binding after we have bound the attribute types for all attributes, ''' but haven't yet bound the attribute arguments/attribute constructor. ''' Early decoding certain well-known attributes enables the binder to use this decoded information on this symbol ''' when binding the attribute arguments/attribute constructor without causing attribute binding cycle. ''' </summary> Private Function EarlyDecodeWellKnownAttributes(binders As ImmutableArray(Of Binder), boundAttributeTypes As ImmutableArray(Of NamedTypeSymbol), attributesToBind As ImmutableArray(Of AttributeSyntax), attributeBuilder As VisualBasicAttributeData(), symbolPart As AttributeLocation) As EarlyWellKnownAttributeData Debug.Assert(boundAttributeTypes.Any()) Debug.Assert(attributesToBind.Any()) Dim arguments = New EarlyDecodeWellKnownAttributeArguments(Of EarlyWellKnownAttributeBinder, NamedTypeSymbol, AttributeSyntax, AttributeLocation)() arguments.SymbolPart = symbolPart For i = 0 To boundAttributeTypes.Length - 1 Dim attributeType As NamedTypeSymbol = boundAttributeTypes(i) If Not attributeType.IsErrorType() Then arguments.Binder = New EarlyWellKnownAttributeBinder(Me, binders(i)) arguments.AttributeType = attributeType arguments.AttributeSyntax = attributesToBind(i) attributeBuilder(i) = Me.EarlyDecodeWellKnownAttribute(arguments) End If Next Return If(arguments.HasDecodedData, arguments.DecodedData, Nothing) End Function ''' <summary> ''' This method validates attribute usage for each bound attribute and calls <see cref="DecodeWellKnownAttribute"/> ''' on attributes with valid attribute usage. ''' This method is called by the binder when it is finished binding a set of attributes on the symbol so that ''' the symbol can extract data from the attribute arguments and potentially perform validation specific to ''' some well known attributes. ''' </summary> Friend Function ValidateAttributeUsageAndDecodeWellKnownAttributes( binders As ImmutableArray(Of Binder), attributeSyntaxList As ImmutableArray(Of AttributeSyntax), boundAttributes As ImmutableArray(Of VisualBasicAttributeData), diagnostics As BindingDiagnosticBag, symbolPart As AttributeLocation) As WellKnownAttributeData Debug.Assert(binders.Any()) Debug.Assert(attributeSyntaxList.Any()) Debug.Assert(boundAttributes.Any()) Debug.Assert(binders.Length = boundAttributes.Length) Debug.Assert(attributeSyntaxList.Length = boundAttributes.Length) Dim totalAttributesCount As Integer = boundAttributes.Length Dim uniqueAttributeTypes = New HashSet(Of NamedTypeSymbol) Dim arguments = New DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation)() arguments.AttributesCount = totalAttributesCount arguments.Diagnostics = diagnostics arguments.SymbolPart = symbolPart For i = 0 To totalAttributesCount - 1 Dim boundAttribute As VisualBasicAttributeData = boundAttributes(i) Dim attributeSyntax As AttributeSyntax = attributeSyntaxList(i) Dim binder As Binder = binders(i) If Not boundAttribute.HasErrors AndAlso ValidateAttributeUsage(boundAttribute, attributeSyntax, binder.Compilation, symbolPart, diagnostics, uniqueAttributeTypes) Then arguments.Attribute = boundAttribute arguments.AttributeSyntaxOpt = attributeSyntax arguments.Index = i Me.DecodeWellKnownAttribute(arguments) End If Next Return If(arguments.HasDecodedData, arguments.DecodedData, Nothing) End Function ''' <summary> ''' Validate attribute usage target and duplicate attributes. ''' </summary> ''' <param name="attribute">Bound attribute</param> ''' <param name="node">Syntax node for attribute specification</param> ''' <param name="compilation">Compilation</param> ''' <param name="symbolPart">Symbol part to which the attribute has been applied</param> ''' <param name="diagnostics">Diagnostics</param> ''' <param name="uniqueAttributeTypes">Set of unique attribute types applied to the symbol</param> Private Function ValidateAttributeUsage( attribute As VisualBasicAttributeData, node As AttributeSyntax, compilation As VisualBasicCompilation, symbolPart As AttributeLocation, diagnostics As BindingDiagnosticBag, uniqueAttributeTypes As HashSet(Of NamedTypeSymbol)) As Boolean Dim attributeType As NamedTypeSymbol = attribute.AttributeClass Debug.Assert(attributeType IsNot Nothing) Debug.Assert(Not attributeType.IsErrorType()) Debug.Assert(attributeType.IsOrDerivedFromWellKnownClass(WellKnownType.System_Attribute, compilation, CompoundUseSiteInfo(Of AssemblySymbol).Discarded)) ' Get attribute usage for this attribute Dim attributeUsage As AttributeUsageInfo = attributeType.GetAttributeUsageInfo() Debug.Assert(Not attributeUsage.IsNull) ' check if this attribute was used multiple times and attributeUsage.AllowMultiple is False. If Not uniqueAttributeTypes.Add(attributeType) AndAlso Not attributeUsage.AllowMultiple Then diagnostics.Add(ERRID.ERR_InvalidMultipleAttributeUsage1, node.GetLocation(), CustomSymbolDisplayFormatter.ShortErrorName(attributeType)) Return False End If Dim attributeTarget As AttributeTargets If symbolPart = AttributeLocation.Return Then Debug.Assert(Me.Kind = SymbolKind.Method OrElse Me.Kind = SymbolKind.Property) attributeTarget = AttributeTargets.ReturnValue Else attributeTarget = Me.GetAttributeTarget() End If ' VB allows NonSerialized on events even though the NonSerialized does not have this attribute usage specified. ' See Dev 10 Bindable::VerifyCustomAttributesOnSymbol Dim applicationIsValid As Boolean If attributeType Is compilation.GetWellKnownType(WellKnownType.System_NonSerializedAttribute) AndAlso Me.Kind = SymbolKind.Event AndAlso DirectCast(Me, SourceEventSymbol).AssociatedField IsNot Nothing Then applicationIsValid = True Else Dim validOn = attributeUsage.ValidTargets applicationIsValid = attributeTarget <> 0 AndAlso (validOn And attributeTarget) <> 0 End If If Not applicationIsValid Then Select Case attributeTarget Case AttributeTargets.Assembly diagnostics.Add(ERRID.ERR_InvalidAssemblyAttribute1, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType)) Case AttributeTargets.Module diagnostics.Add(ERRID.ERR_InvalidModuleAttribute1, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType)) Case AttributeTargets.Method If Me.Kind = SymbolKind.Method Then Dim method = DirectCast(Me, SourceMethodSymbol) Dim accessorName = TryGetAccessorDisplayName(method.MethodKind) If accessorName IsNot Nothing Then Debug.Assert(method.AssociatedSymbol IsNot Nothing) diagnostics.Add(ERRID.ERR_InvalidAttributeUsageOnAccessor, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType), accessorName, CustomSymbolDisplayFormatter.ShortErrorName(method.AssociatedSymbol)) Exit Select End If End If diagnostics.Add(ERRID.ERR_InvalidAttributeUsage2, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType), CustomSymbolDisplayFormatter.ShortErrorName(Me).ToString()) Case AttributeTargets.Field Dim withEventsBackingField = TryCast(Me, SourceWithEventsBackingFieldSymbol) Dim ownerName As String If withEventsBackingField IsNot Nothing Then ownerName = CustomSymbolDisplayFormatter.ShortErrorName(withEventsBackingField.AssociatedSymbol).ToString() Else ownerName = CustomSymbolDisplayFormatter.ShortErrorName(Me).ToString() End If diagnostics.Add(ERRID.ERR_InvalidAttributeUsage2, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType), ownerName) Case AttributeTargets.ReturnValue diagnostics.Add(ERRID.ERR_InvalidAttributeUsage2, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType), New LocalizableErrorArgument(ERRID.IDS_FunctionReturnType)) Case Else diagnostics.Add(ERRID.ERR_InvalidAttributeUsage2, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType), CustomSymbolDisplayFormatter.ShortErrorName(Me).ToString()) End Select Return False End If If attribute.IsSecurityAttribute(compilation) Then Select Case Me.Kind Case SymbolKind.Assembly, SymbolKind.NamedType, SymbolKind.Method Exit Select Case Else ' BC36979: Security attribute '{0}' is not valid on this declaration type. Security attributes are only valid on assembly, type and method declarations. diagnostics.Add(ERRID.ERR_SecurityAttributeInvalidTarget, node.Name.GetLocation, CustomSymbolDisplayFormatter.ShortErrorName(attributeType)) Return False End Select End If Return True End Function Private Sub ReportExtensionAttributeUseSiteInfo(attribute As VisualBasicAttributeData, nodeOpt As AttributeSyntax, compilation As VisualBasicCompilation, diagnostics As BindingDiagnosticBag) ' report issues with a custom extension attribute everywhere, where the attribute is used in source ' (we will not report in location where it's implicitly used (like the containing module or assembly of extension methods) Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing If attribute.AttributeConstructor IsNot Nothing AndAlso attribute.AttributeConstructor Is compilation.GetExtensionAttributeConstructor(useSiteInfo) Then diagnostics.Add(useSiteInfo, If(nodeOpt IsNot Nothing, nodeOpt.GetLocation(), NoLocation.Singleton)) End If End Sub Private Sub MarkEmbeddedAttributeTypeReference(attribute As VisualBasicAttributeData, nodeOpt As AttributeSyntax, compilation As VisualBasicCompilation) Debug.Assert(Not attribute.HasErrors) ' Mark embedded attribute type reference only if the owner is itself not ' embedded and the attribute syntax is actually from the current compilation. If Not Me.IsEmbedded AndAlso attribute.AttributeClass.IsEmbedded AndAlso nodeOpt IsNot Nothing AndAlso compilation.ContainsSyntaxTree(nodeOpt.SyntaxTree) Then ' Note that none of embedded symbols from referenced ' assemblies or compilations should be found/referenced. Debug.Assert(attribute.AttributeClass.ContainingAssembly Is compilation.Assembly) compilation.EmbeddedSymbolManager.MarkSymbolAsReferenced(attribute.AttributeClass) End If End Sub ''' <summary> ''' Ensure that attributes are bound and the ObsoleteState/ExperimentalState of this symbol is known. ''' </summary> Friend Sub ForceCompleteObsoleteAttribute() If Me.ObsoleteKind = ObsoleteAttributeKind.Uninitialized Then Me.GetAttributes() End If Debug.Assert(Me.ObsoleteState <> ThreeState.Unknown, "ObsoleteState should be true or false now.") Debug.Assert(Me.ExperimentalState <> ThreeState.Unknown, "ExperimentalState should be true or false now.") Me.ContainingSymbol?.ForceCompleteObsoleteAttribute() End Sub End Class End Namespace