|
' 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 System.Reflection
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.Threading
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Collections
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports TypeKind = Microsoft.CodeAnalysis.TypeKind
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' <summary>
''' Represents an attribute applied to a Symbol.
''' </summary>
Friend MustInherit Class VisualBasicAttributeData
Inherits AttributeData
Private _lazyIsSecurityAttribute As ThreeState = ThreeState.Unknown
''' <summary>
''' Gets the attribute class being applied.
''' </summary>
Public MustOverride Shadows ReadOnly Property AttributeClass As NamedTypeSymbol
''' <summary>
''' Gets the constructor used in this application of the attribute.
''' </summary>
Public MustOverride Shadows ReadOnly Property AttributeConstructor As MethodSymbol
''' <summary>
''' Gets a reference to the source for this application of the attribute. Returns null for applications of attributes on metadata Symbols.
''' </summary>
Public MustOverride Shadows ReadOnly Property ApplicationSyntaxReference As SyntaxReference
''' <summary>
''' Gets the list of constructor arguments specified by this application of the attribute. This list contains both positional arguments
''' and named arguments that are formal parameters to the constructor.
''' </summary>
Public Shadows ReadOnly Property ConstructorArguments As IEnumerable(Of TypedConstant)
Get
Return Me.CommonConstructorArguments
End Get
End Property
''' <summary>
''' Gets the list of named field or property value arguments specified by this application of the attribute.
''' </summary>
Public Shadows ReadOnly Property NamedArguments As IEnumerable(Of KeyValuePair(Of String, TypedConstant))
Get
Return Me.CommonNamedArguments
End Get
End Property
Friend MustOverride Overrides ReadOnly Property HasErrors As Boolean
Friend MustOverride ReadOnly Property ErrorInfo As DiagnosticInfo
Friend MustOverride Overrides ReadOnly Property IsConditionallyOmitted As Boolean
''' <summary>
''' Compares the namespace and type name with the attribute's namespace and type name. Returns true if they are the same.
''' </summary>
Friend MustOverride Function IsTargetAttribute(
namespaceName As String,
typeName As String,
Optional ignoreCase As Boolean = False
) As Boolean
Friend Function IsTargetAttribute(description As AttributeDescription) As Boolean
Return GetTargetAttributeSignatureIndex(description) <> -1
End Function
Friend MustOverride Function GetTargetAttributeSignatureIndex(description As AttributeDescription) As Integer
''' <summary>
''' Checks if an applied attribute with the given attributeType matches the namespace name and type name of the given early attribute's description
''' and the attribute description has a signature with parameter count equal to the given attribute syntax's argument list count.
''' NOTE: We don't allow early decoded attributes to have optional parameters.
''' </summary>
Friend Overloads Shared Function IsTargetEarlyAttribute(attributeType As NamedTypeSymbol, attributeSyntax As AttributeSyntax, description As AttributeDescription) As Boolean
Debug.Assert(Not attributeType.IsErrorType())
Dim argumentCount As Integer = If(attributeSyntax.ArgumentList IsNot Nothing,
attributeSyntax.ArgumentList.Arguments.Where(Function(arg) arg.Kind = SyntaxKind.SimpleArgument AndAlso Not arg.IsNamed).Count,
0)
Return AttributeData.IsTargetEarlyAttribute(attributeType, argumentCount, description)
End Function
''' <summary>
''' Returns the <see cref="System.String"/> that represents the current AttributeData.
''' </summary>
''' <returns>A <see cref="System.String"/> that represents the current AttributeData.</returns>
Public Overrides Function ToString() As String
If Me.AttributeClass IsNot Nothing Then
Dim className As String = Me.AttributeClass.ToDisplayString(SymbolDisplayFormat.QualifiedNameOnlyFormat)
If Not Me.CommonConstructorArguments.Any() And Not Me.CommonNamedArguments.Any() Then
Return className
End If
Dim pooledStrbuilder = PooledStringBuilder.GetInstance()
Dim stringBuilder As StringBuilder = pooledStrbuilder.Builder
stringBuilder.Append(className)
stringBuilder.Append("(")
Dim first As Boolean = True
For Each constructorArgument In Me.CommonConstructorArguments
If Not first Then
stringBuilder.Append(", ")
End If
stringBuilder.Append(constructorArgument.ToVisualBasicString())
first = False
Next
For Each namedArgument In Me.CommonNamedArguments
If Not first Then
stringBuilder.Append(", ")
End If
stringBuilder.Append(namedArgument.Key)
stringBuilder.Append(":=")
stringBuilder.Append(namedArgument.Value.ToVisualBasicString())
first = False
Next
stringBuilder.Append(")")
Return pooledStrbuilder.ToStringAndFree()
End If
Return MyBase.ToString()
End Function
#Region "AttributeData Implementation"
''' <summary>
''' Gets the attribute class being applied as an <see cref="INamedTypeSymbol"/>
''' </summary>
Protected Overrides ReadOnly Property CommonAttributeClass As INamedTypeSymbol
Get
Return AttributeClass()
End Get
End Property
''' <summary>
''' Gets the constructor used in this application of the attribute as an <see cref="IMethodSymbol"/>.
''' </summary>
Protected Overrides ReadOnly Property CommonAttributeConstructor As IMethodSymbol
Get
Return AttributeConstructor()
End Get
End Property
''' <summary>
''' Gets a reference to the source for this application of the attribute. Returns null for applications of attributes on metadata Symbols.
''' </summary>
Protected Overrides ReadOnly Property CommonApplicationSyntaxReference As SyntaxReference
Get
Return ApplicationSyntaxReference()
End Get
End Property
#End Region
#Region "Attribute Decoding"
Friend Function IsSecurityAttribute(comp As VisualBasicCompilation) As Boolean
' CLI spec (Partition II Metadata), section 21.11 "DeclSecurity : 0x0E" states:
' SPEC: If the attribute's type is derived (directly or indirectly) from System.Security.Permissions.SecurityAttribute then
' SPEC: it is a security custom attribute and requires special treatment.
If _lazyIsSecurityAttribute = ThreeState.Unknown Then
_lazyIsSecurityAttribute = Me.AttributeClass.IsOrDerivedFromWellKnownClass(WellKnownType.System_Security_Permissions_SecurityAttribute, comp, useSiteInfo:=CompoundUseSiteInfo(Of AssemblySymbol).Discarded).ToThreeState()
End If
Return _lazyIsSecurityAttribute.Value
End Function
Friend Sub DecodeSecurityAttribute(Of T As {WellKnownAttributeData, ISecurityAttributeTarget, New})(targetSymbol As Symbol, compilation As VisualBasicCompilation, ByRef arguments As DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation))
Dim hasErrors As Boolean = False
Dim action As DeclarativeSecurityAction = Me.DecodeSecurityAttributeAction(targetSymbol, compilation, arguments.AttributeSyntaxOpt, hasErrors, DirectCast(arguments.Diagnostics, BindingDiagnosticBag))
If Not hasErrors Then
Dim data As T = arguments.GetOrCreateData(Of T)()
Dim securityData As SecurityWellKnownAttributeData = data.GetOrCreateData()
securityData.SetSecurityAttribute(arguments.Index, action, arguments.AttributesCount)
If Me.IsTargetAttribute(AttributeDescription.PermissionSetAttribute) Then
Dim resolvedPathForFixup As String = Me.DecodePermissionSetAttribute(compilation, arguments)
If resolvedPathForFixup IsNot Nothing Then
securityData.SetPathForPermissionSetAttributeFixup(arguments.Index, resolvedPathForFixup, arguments.AttributesCount)
End If
End If
End If
End Sub
Private Function DecodeSecurityAttributeAction(
targetSymbol As Symbol,
compilation As VisualBasicCompilation,
nodeOpt As AttributeSyntax,
ByRef hasErrors As Boolean,
diagnostics As BindingDiagnosticBag
) As DeclarativeSecurityAction
Debug.Assert(Not hasErrors)
Debug.Assert(Me.IsSecurityAttribute(compilation))
Debug.Assert(targetSymbol.Kind = SymbolKind.Assembly OrElse targetSymbol.Kind = SymbolKind.NamedType OrElse targetSymbol.Kind = SymbolKind.Method)
If Me.AttributeConstructor.ParameterCount = 0 Then
' NOTE: Security custom attributes must have a valid SecurityAction as its first argument, we have none here.
' NOTE: Ideally, we should always generate 'BC31205: First argument to a security attribute must be a valid SecurityAction' for this case.
' NOTE: However, native compiler allows applying System.Security.Permissions.HostProtectionAttribute attribute without any argument and uses
' NOTE: SecurityAction.LinkDemand as the default SecurityAction in this case. We maintain compatibility with the native compiler for this case.
' BREAKING CHANGE: Even though the native compiler intends to allow only HostProtectionAttribute to be applied without any arguments,
' it doesn't quite do this correctly
' The implementation issue leads to the native compiler allowing any user defined security attribute with a parameterless constructor and a named property argument as the first
' attribute argument to have the above mentioned behavior, even though the comment clearly mentions that this behavior was intended only for the HostProtectionAttribute.
' We currently allow this case only for the HostProtectionAttribute. In future if need arises, we can exactly match native compiler's behavior.
If Me.IsTargetAttribute(AttributeDescription.HostProtectionAttribute) Then
Return DeclarativeSecurityAction.LinkDemand
End If
Else
Dim firstArg As TypedConstant = Me.CommonConstructorArguments.FirstOrDefault()
Dim firstArgType = DirectCast(firstArg.TypeInternal, TypeSymbol)
Dim useSiteInfo As New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, compilation.Assembly)
If firstArgType IsNot Nothing AndAlso firstArgType.IsOrDerivedFromWellKnownClass(WellKnownType.System_Security_Permissions_SecurityAction, compilation, useSiteInfo) Then
Return ValidateSecurityAction(firstArg, targetSymbol, nodeOpt, diagnostics, hasErrors)
End If
diagnostics.Add(If(nodeOpt IsNot Nothing, nodeOpt.Name.GetLocation, NoLocation.Singleton), useSiteInfo)
End If
' BC31211: First argument to a security attribute must be a valid SecurityAction
diagnostics.Add(ErrorFactory.ErrorInfo(ERRID.ERR_SecurityAttributeMissingAction),
If(nodeOpt IsNot Nothing, nodeOpt.Name.GetLocation, NoLocation.Singleton))
hasErrors = True
Return Nothing
End Function
Friend Shared Function GetArgumentLocation(nodeOpt As AttributeSyntax, argumentIndex As Integer) As Location
Return GetArgumentDisplayAndLocation(nodeOpt, 0, argumentIndex).Location
End Function
Private Shared Function GetArgumentDisplayAndLocation(nodeOpt As AttributeSyntax, value As Integer, argumentIndex As Integer) As (ArgumentDisplay As String, Location As Location)
If nodeOpt IsNot Nothing Then
If nodeOpt.ArgumentList IsNot Nothing AndAlso nodeOpt.ArgumentList.Arguments.Count > argumentIndex Then
Dim arg As ArgumentSyntax = nodeOpt.ArgumentList.Arguments(argumentIndex)
Return (arg.ToString(), arg.GetLocation())
Else
Return (value.ToString(), nodeOpt.GetLocation())
End If
Else
Return ("", NoLocation.Singleton)
End If
End Function
Friend Shared Function GetFirstArgumentLocation(nodeOpt As AttributeSyntax) As Location
Return GetArgumentLocation(nodeOpt, argumentIndex:=0)
End Function
Private Shared Function GetFirstArgumentDisplayAndLocation(nodeOpt As AttributeSyntax, value As Integer) As (ArgumentDisplay As String, Location As Location)
Return GetArgumentDisplayAndLocation(nodeOpt, value, argumentIndex:=0)
End Function
Private Function ValidateSecurityAction(
typedValue As TypedConstant,
targetSymbol As Symbol,
nodeOpt As AttributeSyntax,
diagnostics As BindingDiagnosticBag,
<Out> ByRef hasErrors As Boolean
) As DeclarativeSecurityAction
Debug.Assert(targetSymbol.Kind = SymbolKind.Assembly OrElse targetSymbol.Kind = SymbolKind.NamedType OrElse targetSymbol.Kind = SymbolKind.Method)
Dim securityAction As Integer = CInt(typedValue.ValueInternal)
hasErrors = False
Dim isPermissionRequestAction As Boolean
Select Case securityAction
Case DeclarativeSecurityAction.InheritanceDemand,
DeclarativeSecurityAction.LinkDemand
If Me.IsTargetAttribute(AttributeDescription.PrincipalPermissionAttribute) Then
' BC31215: SecurityAction value '{0}' is invalid for PrincipalPermission attribute
Dim displayAndLocation As (ArgumentDisplay As String, Location As Location) = GetFirstArgumentDisplayAndLocation(nodeOpt, securityAction)
diagnostics.Add(ERRID.ERR_PrincipalPermissionInvalidAction, displayAndLocation.Location, displayAndLocation.ArgumentDisplay)
hasErrors = True
Return DeclarativeSecurityAction.None
End If
isPermissionRequestAction = False
Case 1
' Native compiler allows security action value 1 even though there is no corresponding field in
' System.Security.Permissions.SecurityAction enum.
' We will maintain compatibility.
Case DeclarativeSecurityAction.Assert,
DeclarativeSecurityAction.Demand,
DeclarativeSecurityAction.PermitOnly,
DeclarativeSecurityAction.Deny
isPermissionRequestAction = False
Case DeclarativeSecurityAction.RequestMinimum,
DeclarativeSecurityAction.RequestOptional,
DeclarativeSecurityAction.RequestRefuse
isPermissionRequestAction = True
Case Else
' BC31214: SecurityAction value '{0}' is invalid for security attributes applied to a type or a method.
Dim displayAndLocation As (ArgumentDisplay As String, Location As Location) = GetFirstArgumentDisplayAndLocation(nodeOpt, securityAction)
diagnostics.Add(ERRID.ERR_SecurityAttributeInvalidActionTypeOrMethod, displayAndLocation.Location, displayAndLocation.ArgumentDisplay)
hasErrors = True
Return DeclarativeSecurityAction.None
End Select
If isPermissionRequestAction Then
If targetSymbol.Kind = SymbolKind.NamedType OrElse targetSymbol.Kind = SymbolKind.Method Then
' Types and methods cannot take permission requests.
' BC31214: SecurityAction value '{0}' is invalid for security attributes applied to a type or a method.
Dim displayAndLocation As (ArgumentDisplay As String, Location As Location) = GetFirstArgumentDisplayAndLocation(nodeOpt, securityAction)
diagnostics.Add(ERRID.ERR_SecurityAttributeInvalidActionTypeOrMethod, displayAndLocation.Location, displayAndLocation.ArgumentDisplay)
hasErrors = True
Return DeclarativeSecurityAction.None
End If
ElseIf targetSymbol.Kind = SymbolKind.Assembly Then
' Assemblies cannot take declarative security.
' BC31213: SecurityAction value '{0}' is invalid for security attributes applied to an assembly.
Dim displayAndLocation As (ArgumentDisplay As String, Location As Location) = GetFirstArgumentDisplayAndLocation(nodeOpt, securityAction)
diagnostics.Add(ERRID.ERR_SecurityAttributeInvalidActionAssembly, displayAndLocation.Location, displayAndLocation.ArgumentDisplay)
hasErrors = True
Return DeclarativeSecurityAction.None
End If
Return CType(securityAction, DeclarativeSecurityAction)
End Function
''' <summary>
''' Decodes PermissionSetAttribute applied in source to determine if it needs any fixup during codegen.
''' </summary>
''' <remarks>
''' PermissionSetAttribute needs fixup when it contains an assignment to the 'File' property as a single named attribute argument.
''' Fixup performed is ported from SecurityAttributes::FixUpPermissionSetAttribute.
''' It involves following steps:
''' 1) Verifying that the specified file name resolves to a valid path.
''' 2) Reading the contents of the file into a byte array.
''' 3) Convert each byte in the file content into two bytes containing hexa-decimal characters.
''' 4) Replacing the 'File = fileName' named argument with 'Hex = hexFileContent' argument, where hexFileContent is the converted output from step 3) above.
'''
''' Step 1) is performed in this method, i.e. during binding.
''' Remaining steps are performed during serialization as we want to avoid retaining the entire file contents throughout the binding/codegen pass.
''' See <see cref="Microsoft.CodeAnalysis.CodeGen.PermissionSetAttributeWithFileReference"/> for remaining fixup steps.
''' </remarks>
''' <returns>String containing the resolved file path if PermissionSetAttribute needs fixup during codegen, null otherwise.</returns>
Friend Function DecodePermissionSetAttribute(compilation As VisualBasicCompilation, ByRef arguments As DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation)) As String
Dim resolvedFilePath As String = Nothing
Dim namedArgs = Me.CommonNamedArguments
If namedArgs.Length = 1 Then
Dim namedArg = namedArgs(0)
Dim attrType As NamedTypeSymbol = Me.AttributeClass
Dim filePropName As String = PermissionSetAttributeWithFileReference.FilePropertyName
Dim hexPropName As String = PermissionSetAttributeWithFileReference.HexPropertyName
If namedArg.Key = filePropName AndAlso
PermissionSetAttributeTypeHasRequiredProperty(attrType, filePropName) Then
' resolve file prop path
Dim fileName = DirectCast(namedArg.Value.ValueInternal, String)
Dim resolver = compilation.Options.XmlReferenceResolver
resolvedFilePath = If(resolver IsNot Nothing, resolver.ResolveReference(fileName, baseFilePath:=Nothing), Nothing)
If resolvedFilePath Is Nothing Then
' BC31216: Unable to resolve file path '{0}' specified for the named argument '{1}' for PermissionSet attribute.
Dim argSyntaxLocation As Location = If(arguments.AttributeSyntaxOpt IsNot Nothing,
arguments.AttributeSyntaxOpt.ArgumentList.Arguments(1).GetLocation(),
NoLocation.Singleton)
DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_PermissionSetAttributeInvalidFile, argSyntaxLocation, If(fileName, "<empty>"), filePropName)
ElseIf (Not PermissionSetAttributeTypeHasRequiredProperty(attrType, hexPropName)) Then
' PermissionSetAttribute was defined in user source, but doesn't have the required Hex property.
' Native compiler still emits the file content as named assignment to 'Hex' property, but this leads to a runtime exception.
' We instead skip the fixup and emit the file property.
' CONSIDER: We may want to consider taking a breaking change and generating an error here.
Return Nothing
End If
End If
End If
Return resolvedFilePath
End Function
' This method checks if the given PermissionSetAttribute type has a property member with the given propName which is
' writable, non-generic, public and of string type.
Private Shared Function PermissionSetAttributeTypeHasRequiredProperty(permissionSetType As NamedTypeSymbol, propName As String) As Boolean
Dim members = permissionSetType.GetMembers(propName)
If members.Length = 1 AndAlso members(0).Kind = SymbolKind.Property Then
Dim [property] = DirectCast(members(0), PropertySymbol)
If [property].Type IsNot Nothing AndAlso [property].Type.SpecialType = SpecialType.System_String AndAlso
[property].DeclaredAccessibility = Accessibility.Public AndAlso [property].GetArity() = 0 AndAlso
[property].HasSet AndAlso [property].SetMethod.DeclaredAccessibility = Accessibility.Public Then
Return True
End If
End If
Return False
End Function
Friend Sub DecodeClassInterfaceAttribute(nodeOpt As AttributeSyntax, diagnostics As BindingDiagnosticBag)
Debug.Assert(Not Me.HasErrors)
Dim ctorArgument As TypedConstant = Me.CommonConstructorArguments(0)
Debug.Assert(ctorArgument.Kind = TypedConstantKind.Enum OrElse ctorArgument.Kind = TypedConstantKind.Primitive)
Dim interfaceType As ClassInterfaceType = If(ctorArgument.Kind = TypedConstantKind.Enum,
ctorArgument.DecodeValue(Of ClassInterfaceType)(SpecialType.System_Enum),
CType(ctorArgument.DecodeValue(Of Short)(SpecialType.System_Int16), ClassInterfaceType))
Select Case interfaceType
Case ClassInterfaceType.None, Cci.Constants.ClassInterfaceType_AutoDispatch, Cci.Constants.ClassInterfaceType_AutoDual
Exit Select
Case Else
Dim location As Location = GetFirstArgumentLocation(nodeOpt)
diagnostics.Add(ERRID.ERR_BadAttribute1, location, Me.AttributeClass)
End Select
End Sub
Friend Sub DecodeInterfaceTypeAttribute(node As AttributeSyntax, diagnostics As BindingDiagnosticBag)
Dim discarded As ComInterfaceType = Nothing
If Not DecodeInterfaceTypeAttribute(discarded) Then
Dim location As Location = GetFirstArgumentLocation(node)
diagnostics.Add(ERRID.ERR_BadAttribute1, location, Me.AttributeClass)
End If
End Sub
Friend Function DecodeInterfaceTypeAttribute(<Out> ByRef interfaceType As ComInterfaceType) As Boolean
Debug.Assert(Not Me.HasErrors)
Dim ctorArgument As TypedConstant = Me.CommonConstructorArguments(0)
Debug.Assert(ctorArgument.Kind = TypedConstantKind.Enum OrElse ctorArgument.Kind = TypedConstantKind.Primitive)
interfaceType = If(ctorArgument.Kind = TypedConstantKind.Enum,
ctorArgument.DecodeValue(Of ComInterfaceType)(SpecialType.System_Enum),
CType(ctorArgument.DecodeValue(Of Short)(SpecialType.System_Int16), ComInterfaceType))
Select Case interfaceType
Case Cci.Constants.ComInterfaceType_InterfaceIsDual, Cci.Constants.ComInterfaceType_InterfaceIsIDispatch, ComInterfaceType.InterfaceIsIInspectable, ComInterfaceType.InterfaceIsIUnknown
Return True
Case Else
Return False
End Select
End Function
Friend Function DecodeTypeLibTypeAttribute() As Cci.TypeLibTypeFlags
Debug.Assert(Not Me.HasErrors)
Dim ctorArgument As TypedConstant = Me.CommonConstructorArguments(0)
Debug.Assert(ctorArgument.Kind = TypedConstantKind.Enum OrElse ctorArgument.Kind = TypedConstantKind.Primitive)
Return If(ctorArgument.Kind = TypedConstantKind.Enum,
ctorArgument.DecodeValue(Of Cci.TypeLibTypeFlags)(SpecialType.System_Enum),
CType(ctorArgument.DecodeValue(Of Short)(SpecialType.System_Int16), Cci.TypeLibTypeFlags))
End Function
Friend Function DecodeGuidAttribute(nodeOpt As AttributeSyntax, diagnostics As BindingDiagnosticBag) As String
Debug.Assert(Not Me.HasErrors)
Dim guidString As String = Me.GetConstructorArgument(Of String)(0, SpecialType.System_String)
' Native compiler allows only a specific GUID format: "D" format (32 digits separated by hyphens)
Dim guidVal As Guid
If Not Guid.TryParseExact(guidString, "D", guidVal) Then
Dim location As Location = GetFirstArgumentLocation(nodeOpt)
diagnostics.Add(ERRID.ERR_BadAttributeUuid2, location, Me.AttributeClass, If(guidString, ObjectDisplay.NullLiteral))
guidString = String.Empty
End If
Return guidString
End Function
Friend Function DecodeDefaultMemberAttribute() As String
Debug.Assert(Not Me.HasErrors)
Return Me.GetConstructorArgument(Of String)(0, SpecialType.System_String)
End Function
Private Protected NotOverridable Overrides Function IsStringProperty(memberName As String) As Boolean
If AttributeClass IsNot Nothing Then
For Each member In AttributeClass.GetMembers(memberName)
Dim prop = TryCast(member, PropertySymbol)
If prop?.Type.SpecialType = SpecialType.System_String Then
Return True
End If
Next
End If
Return False
End Function
#End Region
''' <summary>
''' This method determines if an applied attribute must be emitted.
''' Some attributes appear in symbol model to reflect the source code, but should not be emitted.
''' </summary>
Friend Function ShouldEmitAttribute(target As Symbol, isReturnType As Boolean, emittingAssemblyAttributesInNetModule As Boolean) As Boolean
Debug.Assert(TypeOf target Is SourceAssemblySymbol OrElse TypeOf target.ContainingAssembly Is SourceAssemblySymbol)
' Attribute type is conditionally omitted if both the following are true:
' (a) It has at least one applied conditional attribute AND
' (b) None of conditional symbols are true at the attribute source location.
If Me.IsConditionallyOmitted Then
Return False
End If
' // UNDONE:harishk - spec. issue
' // how to deal with CLS Compliant attributes present on both Modules and Assemblies ?
' // Also this might be a issue for other well known attributes too ?
' //
' // For CLSCompliance - Ignore Module attributes for Assemblies and vice-versa
Select Case target.Kind
Case SymbolKind.Assembly
If (Not emittingAssemblyAttributesInNetModule AndAlso
(IsTargetAttribute(AttributeDescription.AssemblyCultureAttribute) OrElse
IsTargetAttribute(AttributeDescription.AssemblyVersionAttribute) OrElse
IsTargetAttribute(AttributeDescription.AssemblyFlagsAttribute) OrElse
IsTargetAttribute(AttributeDescription.AssemblyAlgorithmIdAttribute))) OrElse
(IsTargetAttribute(AttributeDescription.CLSCompliantAttribute) AndAlso
target.DeclaringCompilation.Options.OutputKind = OutputKind.NetModule) OrElse
IsTargetAttribute(AttributeDescription.TypeForwardedToAttribute) OrElse
Me.IsSecurityAttribute(target.DeclaringCompilation) Then
Return False
End If
Case SymbolKind.Event
If IsTargetAttribute(AttributeDescription.SpecialNameAttribute) OrElse
IsTargetAttribute(AttributeDescription.NonSerializedAttribute) Then
Return False
End If
Case SymbolKind.Field
If IsTargetAttribute(AttributeDescription.SpecialNameAttribute) OrElse
IsTargetAttribute(AttributeDescription.NonSerializedAttribute) OrElse
IsTargetAttribute(AttributeDescription.FieldOffsetAttribute) OrElse
IsTargetAttribute(AttributeDescription.MarshalAsAttribute) Then
Return False
End If
Case SymbolKind.Method
If isReturnType Then
If IsTargetAttribute(AttributeDescription.MarshalAsAttribute) Then
Return False
End If
Else
If IsTargetAttribute(AttributeDescription.SpecialNameAttribute) OrElse
IsTargetAttribute(AttributeDescription.MethodImplAttribute) OrElse
IsTargetAttribute(AttributeDescription.DllImportAttribute) OrElse
IsTargetAttribute(AttributeDescription.PreserveSigAttribute) OrElse
Me.IsSecurityAttribute(target.DeclaringCompilation) Then
Return False
End If
End If
Case SymbolKind.NetModule
If (IsTargetAttribute(AttributeDescription.CLSCompliantAttribute) AndAlso
target.DeclaringCompilation.Options.OutputKind <> OutputKind.NetModule) Then
Return False
End If
Case SymbolKind.NamedType
If IsTargetAttribute(AttributeDescription.SpecialNameAttribute) OrElse
IsTargetAttribute(AttributeDescription.ComImportAttribute) OrElse
IsTargetAttribute(AttributeDescription.SerializableAttribute) OrElse
IsTargetAttribute(AttributeDescription.StructLayoutAttribute) OrElse
IsTargetAttribute(AttributeDescription.WindowsRuntimeImportAttribute) OrElse
Me.IsSecurityAttribute(target.DeclaringCompilation) Then
Return False
End If
Case SymbolKind.Parameter
If IsTargetAttribute(AttributeDescription.OptionalAttribute) OrElse
IsTargetAttribute(AttributeDescription.MarshalAsAttribute) OrElse
IsTargetAttribute(AttributeDescription.InAttribute) OrElse
IsTargetAttribute(AttributeDescription.OutAttribute) Then
Return False
End If
Case SymbolKind.Property
If IsTargetAttribute(AttributeDescription.SpecialNameAttribute) Then
Return False
End If
End Select
Return True
End Function
End Class
Friend Module AttributeDataExtensions
<System.Runtime.CompilerServices.Extension()>
Public Function IndexOfAttribute(attributes As ImmutableArray(Of VisualBasicAttributeData), description As AttributeDescription) As Integer
For i As Integer = 0 To attributes.Length - 1
If attributes(i).IsTargetAttribute(description) Then
Return i
End If
Next
Return -1
End Function
End Module
End Namespace
|