|
' 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.Concurrent
Imports System.Collections.Immutable
Imports System.Reflection
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports CommonAssemblyWellKnownAttributeData = Microsoft.CodeAnalysis.CommonAssemblyWellKnownAttributeData(Of Microsoft.CodeAnalysis.VisualBasic.Symbols.NamedTypeSymbol)
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' <summary>
''' Represents an assembly built by compiler.
''' </summary>
''' <remarks></remarks>
Partial Friend NotInheritable Class SourceAssemblySymbol
Inherits MetadataOrSourceAssemblySymbol
Implements ISourceAssemblySymbol, ISourceAssemblySymbolInternal, IAttributeTargetSymbol
''' <summary>
''' A Compilation the assembly is created for.
''' </summary>
''' <remarks></remarks>
Private ReadOnly _compilation As VisualBasicCompilation
Private _lazyStrongNameKeys As StrongNameKeys
''' <summary>
''' Assembly's identity.
''' </summary>
''' <remarks></remarks>
Friend m_lazyIdentity As AssemblyIdentity
''' <summary>
''' A list of modules the assembly consists of.
''' The first (index=0) module is a SourceModuleSymbol, which is a primary module, the rest are net-modules.
''' </summary>
Private ReadOnly _modules As ImmutableArray(Of ModuleSymbol)
Private _lazySourceAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData)
Private _lazyNetModuleAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData)
''' <summary>
''' Indices of duplicate assembly attributes, i.e. attributes that bind to the same constructor and have identical arguments, that must not be emitted.
''' </summary>
''' <remarks>
''' These indices correspond to the merged assembly attributes from source and added net modules, i.e. attributes returned by <see cref="GetAttributes"/> method.
''' </remarks>
Private _lazyDuplicateAttributeIndices As HashSet(Of Integer)
Private _lazyEmitExtensionAttribute As Byte = ThreeState.Unknown
Private _lazyIsVbRuntime As ThreeState = ThreeState.Unknown
Private _lazyAssemblyLevelDeclarationErrors As ImmutableArray(Of Diagnostic)
Private _lazyAssemblyLevelDeclarationDependencies As ImmutableArray(Of AssemblySymbol)
Private ReadOnly _assemblySimpleName As String
'This maps from assembly name to a set of public keys. It uses concurrent dictionaries because it is built,
'one attribute at a time, in the callback that validates an attribute's application to a symbol. It is assumed
'to be complete after a call to GetAttributes(). The second dictionary is acting like a set. The value element is
'only used when the key is empty in which case it stores the location and value of the attribute string which
'may be used to construct a diagnostic if the assembly being compiled is found to be strong named.
Private _lazyInternalsVisibleToMap As ConcurrentDictionary(Of String, ConcurrentDictionary(Of ImmutableArray(Of Byte), Tuple(Of Location, String)))
Friend Sub New(compilation As VisualBasicCompilation,
assemblySimpleName As String,
moduleName As String,
netModules As ImmutableArray(Of PEModule))
Debug.Assert(compilation IsNot Nothing)
Debug.Assert(assemblySimpleName IsNot Nothing)
Debug.Assert(Not String.IsNullOrWhiteSpace(moduleName))
Debug.Assert(Not netModules.IsDefault)
_compilation = compilation
_assemblySimpleName = assemblySimpleName
Dim moduleBuilder As New ArrayBuilder(Of ModuleSymbol)(1 + netModules.Length)
moduleBuilder.Add(New SourceModuleSymbol(Me, compilation.Declarations, compilation.Options, moduleName))
Dim importOptions = If(compilation.Options.MetadataImportOptions = MetadataImportOptions.All,
MetadataImportOptions.All,
MetadataImportOptions.Internal)
For Each netModule As PEModule In netModules
moduleBuilder.Add(New PEModuleSymbol(Me, netModule, importOptions, moduleBuilder.Count))
' SetReferences will be called later by the ReferenceManager (in CreateSourceAssemblyFullBind for
' a fresh manager, in CreateSourceAssemblyReuseData for a reused one).
Next
_modules = moduleBuilder.ToImmutableAndFree()
If Not compilation.Options.CryptoPublicKey.IsEmpty Then
' Private key Is Not necessary for assembly identity, only when emitting. For this reason, the private key can remain null.
_lazyStrongNameKeys = StrongNameKeys.Create(compilation.Options.CryptoPublicKey, privateKey:=Nothing, hasCounterSignature:=False, MessageProvider.Instance)
End If
End Sub
''' <summary>
''' This override is essential - it's a base case of the recursive definition.
''' </summary>
Friend Overrides ReadOnly Property DeclaringCompilation As VisualBasicCompilation
Get
Return _compilation
End Get
End Property
Public Overrides ReadOnly Property IsInteractive As Boolean
Get
Return _compilation.IsSubmission
End Get
End Property
Friend Function MightContainNoPiaLocalTypes() As Boolean
For i As Integer = 1 To _modules.Length - 1
Dim peModuleSymbol = DirectCast(_modules(i), Symbols.Metadata.PE.PEModuleSymbol)
If peModuleSymbol.[Module].ContainsNoPiaLocalTypes() Then
Return True
End If
Next
Return SourceModule.MightContainNoPiaLocalTypes()
End Function
Public Overrides ReadOnly Property Identity As AssemblyIdentity
Get
If m_lazyIdentity Is Nothing Then
Interlocked.CompareExchange(m_lazyIdentity, ComputeIdentity(), Nothing)
End If
Return m_lazyIdentity
End Get
End Property
Public Overrides ReadOnly Property HasImportedFromTypeLibAttribute As Boolean
Get
Return (GetSourceDecodedWellKnownAttributeData()?.HasImportedFromTypeLibAttribute).GetValueOrDefault()
End Get
End Property
Public Overrides ReadOnly Property HasPrimaryInteropAssemblyAttribute As Boolean
Get
Return (GetSourceDecodedWellKnownAttributeData()?.HasPrimaryInteropAssemblyAttribute).GetValueOrDefault()
End Get
End Property
Friend Overrides Function GetSpecialTypeMember(member As SpecialMember) As Symbol
If _compilation.IsMemberMissing(member) Then
Return Nothing
End If
Return MyBase.GetSpecialTypeMember(member)
End Function
Public Overrides ReadOnly Property Name As String
Get
Return _assemblySimpleName
End Get
End Property
Private Function IsKnownAssemblyAttribute(attribute As VisualBasicAttributeData) As Boolean
' TODO: This list used to include AssemblyOperatingSystemAttribute and AssemblyProcessorAttribute,
' but it doesn't look like they are defined, cannot find them on MSDN.
If attribute.IsTargetAttribute(AttributeDescription.AssemblyTitleAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyDescriptionAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyConfigurationAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyCultureAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyVersionAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyCompanyAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyProductAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyInformationalVersionAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyCopyrightAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyTrademarkAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyKeyFileAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyKeyNameAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyAlgorithmIdAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyFlagsAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyDelaySignAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblyFileVersionAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.SatelliteContractVersionAttribute) OrElse
attribute.IsTargetAttribute(AttributeDescription.AssemblySignatureKeyAttribute) Then
Return True
End If
Return False
End Function
''' <summary>
''' Gets unique source assembly attributes that should be emitted,
''' i.e. filters out attributes with errors and duplicate attributes.
''' </summary>
Private Function GetUniqueSourceAssemblyAttributes(<Out> ByRef attributeIndicesToSkip As HashSet(Of Integer)) As HashSet(Of VisualBasicAttributeData)
Dim appliedSourceAttributes As ImmutableArray(Of VisualBasicAttributeData) = Me.GetSourceAttributesBag().Attributes
Dim uniqueAttributes As HashSet(Of VisualBasicAttributeData) = Nothing
attributeIndicesToSkip = Nothing
For i As Integer = 0 To appliedSourceAttributes.Length - 1
Dim attribute As VisualBasicAttributeData = appliedSourceAttributes(i)
If Not attribute.HasErrors Then
If Not AddUniqueAssemblyAttribute(attribute, uniqueAttributes) Then
If attributeIndicesToSkip Is Nothing Then
attributeIndicesToSkip = New HashSet(Of Integer)
End If
attributeIndicesToSkip.Add(i)
End If
End If
Next
Return uniqueAttributes
End Function
Private Shared Function AddUniqueAssemblyAttribute(attribute As VisualBasicAttributeData, ByRef uniqueAttributes As HashSet(Of VisualBasicAttributeData)) As Boolean
Debug.Assert(Not attribute.HasErrors)
If uniqueAttributes Is Nothing Then
uniqueAttributes = New HashSet(Of VisualBasicAttributeData)(comparer:=CommonAttributeDataComparer.Instance)
End If
Return uniqueAttributes.Add(attribute)
End Function
Private Function ValidateAttributeUsageForNetModuleAttribute(attribute As VisualBasicAttributeData, netModuleName As String, diagnostics As BindingDiagnosticBag, ByRef uniqueAttributes As HashSet(Of VisualBasicAttributeData)) As Boolean
Debug.Assert(Not attribute.HasErrors)
Dim attributeClass = attribute.AttributeClass
If attributeClass.GetAttributeUsageInfo().AllowMultiple Then
' Duplicate attributes are allowed, but native compiler doesn't emit duplicate attributes, i.e. attributes with same constructor and arguments.
Return AddUniqueAssemblyAttribute(attribute, uniqueAttributes)
Else
' Duplicate attributes with same attribute type are not allowed.
' Check if there is an existing assembly attribute with same attribute type.
If uniqueAttributes Is Nothing OrElse Not uniqueAttributes.Contains(Function(a) TypeSymbol.Equals(a.AttributeClass, attributeClass, TypeCompareKind.ConsiderEverything)) Then
' Attribute with unique attribute type, not a duplicate.
Dim success As Boolean = AddUniqueAssemblyAttribute(attribute, uniqueAttributes)
Debug.Assert(success)
Return True
Else
' Duplicate attribute with same attribute type, we should report an error.
' Native compiler suppresses the error for
' (a) Duplicate well-known assembly attributes and
' (b) Identical duplicates, i.e. attributes with same constructor and arguments.
' For (a), native compiler picks the last of these duplicate well-known netmodule attributes, but these can vary based on the ordering of referenced netmodules.
If IsKnownAssemblyAttribute(attribute) Then
If Not uniqueAttributes.Contains(attribute) Then
' This attribute application will be ignored.
diagnostics.Add(ERRID.WRN_AssemblyAttributeFromModuleIsOverridden, NoLocation.Singleton, attribute.AttributeClass, netModuleName)
End If
ElseIf AddUniqueAssemblyAttribute(attribute, uniqueAttributes) Then
' Error
diagnostics.Add(ERRID.ERR_InvalidMultipleAttributeUsageInNetModule2, NoLocation.Singleton, attribute.AttributeClass.Name, netModuleName)
End If
Return False
End If
End If
' CONSIDER Handling badly targeted assembly attributes from netmodules
'If (attributeUsage.ValidTargets And AttributeTargets.Assembly) = 0 Then
' If Not attribute.HasErrors Then
' 'Error and skip
' diagnostics.Add(ERRID.ERR_InvalidAssemblyAttributeInNetModule2, NoLocation.Singleton, attribute.AttributeClass.Name, netModuleName, attributeUsage.GetValidTargetsString())
' End If
'End If
End Function
Private Function GetNetModuleAttributes(<Out> ByRef netModuleNames As ImmutableArray(Of String)) As ImmutableArray(Of VisualBasicAttributeData)
Dim netModuleNamesBuilder As ArrayBuilder(Of String) = Nothing
Dim moduleAssemblyAttributesBuilder As ArrayBuilder(Of VisualBasicAttributeData) = Nothing
For i As Integer = 1 To _modules.Length - 1
Dim peModuleSymbol = DirectCast(_modules(i), Symbols.Metadata.PE.PEModuleSymbol)
Dim netModuleName As String = peModuleSymbol.Name
For Each attributeData In peModuleSymbol.GetAssemblyAttributes()
If netModuleNamesBuilder Is Nothing Then
netModuleNamesBuilder = ArrayBuilder(Of String).GetInstance()
moduleAssemblyAttributesBuilder = ArrayBuilder(Of VisualBasicAttributeData).GetInstance()
End If
netModuleNamesBuilder.Add(netModuleName)
moduleAssemblyAttributesBuilder.Add(attributeData)
Next
Next
If netModuleNamesBuilder Is Nothing Then
netModuleNames = ImmutableArray(Of String).Empty
Return ImmutableArray(Of VisualBasicAttributeData).Empty
End If
netModuleNames = netModuleNamesBuilder.ToImmutableAndFree()
Return moduleAssemblyAttributesBuilder.ToImmutableAndFree()
End Function
Private Function ValidateAttributeUsageAndDecodeWellKnownNetModuleAttributes(
attributesFromNetModules As ImmutableArray(Of VisualBasicAttributeData),
netModuleNames As ImmutableArray(Of String),
diagnostics As BindingDiagnosticBag,
<Out> ByRef attributeIndicesToSkip As HashSet(Of Integer)) As WellKnownAttributeData
Debug.Assert(attributesFromNetModules.Any())
Debug.Assert(netModuleNames.Any())
Debug.Assert(attributesFromNetModules.Length = netModuleNames.Length)
Dim tree = VisualBasicSyntaxTree.Dummy
Dim node = tree.GetRoot()
Dim binder As Binder = BinderBuilder.CreateSourceModuleBinder(Me.SourceModule)
Dim netModuleAttributesCount As Integer = attributesFromNetModules.Length
Dim sourceAttributesCount As Integer = Me.GetSourceAttributesBag().Attributes.Length
' Get unique source assembly attributes.
Dim uniqueAttributes As HashSet(Of VisualBasicAttributeData) = GetUniqueSourceAssemblyAttributes(attributeIndicesToSkip)
Dim arguments = New DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation)()
arguments.AttributesCount = netModuleAttributesCount
arguments.Diagnostics = diagnostics
arguments.SymbolPart = AttributeLocation.None
' Attributes from the second added module should override attributes from the first added module, etc.
' Attributes from source should override attributes from added modules.
' That is why we are iterating attributes backwards.
For i As Integer = netModuleAttributesCount - 1 To 0 Step -1
Dim attribute As VisualBasicAttributeData = attributesFromNetModules(i)
Dim errorInfo As DiagnosticInfo = attribute.ErrorInfo
If errorInfo IsNot Nothing Then
diagnostics.Add(errorInfo, NoLocation.Singleton)
End If
If Not attribute.HasErrors AndAlso ValidateAttributeUsageForNetModuleAttribute(attribute, netModuleNames(i), diagnostics, uniqueAttributes) Then
arguments.Attribute = attribute
arguments.Index = i
' CONSIDER Provide usable AttributeSyntax node for diagnostics of malformed netmodule assembly attributes
arguments.AttributeSyntaxOpt = Nothing
Me.DecodeWellKnownAttribute(arguments)
Else
If attributeIndicesToSkip Is Nothing Then
attributeIndicesToSkip = New HashSet(Of Integer)
End If
attributeIndicesToSkip.Add(i + sourceAttributesCount)
End If
Next
Return If(arguments.HasDecodedData, arguments.DecodedData, Nothing)
End Function
Private Sub LoadAndValidateNetModuleAttributes(ByRef lazyNetModuleAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData))
' Indices of duplicate assembly attributes, i.e. attributes that bind to the same constructor and have identical arguments, that must not be emitted.
Dim attributeIndicesToSkip As HashSet(Of Integer) = Nothing
If _compilation.Options.OutputKind.IsNetModule() Then
' Compute duplicate source assembly attributes, i.e. attributes with same constructor and arguments, that must not be emitted.
Dim unused = GetUniqueSourceAssemblyAttributes(attributeIndicesToSkip)
Interlocked.CompareExchange(lazyNetModuleAttributesBag, CustomAttributesBag(Of VisualBasicAttributeData).Empty, Nothing)
Else
Dim diagnostics = BindingDiagnosticBag.GetInstance()
Dim netModuleNames As ImmutableArray(Of String) = Nothing
Dim attributesFromNetModules As ImmutableArray(Of VisualBasicAttributeData) = GetNetModuleAttributes(netModuleNames)
Dim wellKnownData As WellKnownAttributeData = Nothing
If attributesFromNetModules.Any() Then
wellKnownData = ValidateAttributeUsageAndDecodeWellKnownNetModuleAttributes(attributesFromNetModules, netModuleNames, diagnostics, attributeIndicesToSkip)
Else
' Compute duplicate source assembly attributes, i.e. attributes with same constructor and arguments, that must not be emitted.
Dim unused = GetUniqueSourceAssemblyAttributes(attributeIndicesToSkip)
End If
' Load type forwarders from modules
Dim forwardedTypes As HashSet(Of NamedTypeSymbol) = Nothing
' Similar to attributes, type forwarders from the second added module should override type forwarders from the first added module, etc.
' This affects only diagnostics.
For i As Integer = _modules.Length - 1 To 1 Step -1
Dim peModuleSymbol = DirectCast(_modules(i), PEModuleSymbol)
For Each forwarded As NamedTypeSymbol In peModuleSymbol.GetForwardedTypes()
If forwardedTypes Is Nothing Then
If wellKnownData Is Nothing Then
wellKnownData = New CommonAssemblyWellKnownAttributeData()
End If
forwardedTypes = DirectCast(wellKnownData, CommonAssemblyWellKnownAttributeData).ForwardedTypes
If forwardedTypes Is Nothing Then
forwardedTypes = New HashSet(Of NamedTypeSymbol)()
DirectCast(wellKnownData, CommonAssemblyWellKnownAttributeData).ForwardedTypes = forwardedTypes
End If
End If
If forwardedTypes.Add(forwarded) Then
If forwarded.IsErrorType() Then
Dim info As DiagnosticInfo = If(forwarded.GetUseSiteInfo().DiagnosticInfo, DirectCast(forwarded, ErrorTypeSymbol).ErrorInfo)
If info IsNot Nothing Then
diagnostics.Add(info, NoLocation.Singleton)
End If
End If
End If
Next
Next
Dim netModuleAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData)
If wellKnownData IsNot Nothing OrElse attributesFromNetModules.Any() Then
netModuleAttributesBag = New CustomAttributesBag(Of VisualBasicAttributeData)()
netModuleAttributesBag.SetEarlyDecodedWellKnownAttributeData(Nothing)
netModuleAttributesBag.SetDecodedWellKnownAttributeData(wellKnownData)
netModuleAttributesBag.SetAttributes(attributesFromNetModules)
Else
netModuleAttributesBag = CustomAttributesBag(Of VisualBasicAttributeData).Empty
End If
' Check if we have any duplicate assembly attribute that must not be emitted,
' unless we are emitting a net module.
If attributeIndicesToSkip IsNot Nothing Then
Debug.Assert(attributeIndicesToSkip.Any())
Interlocked.CompareExchange(_lazyDuplicateAttributeIndices, attributeIndicesToSkip, Nothing)
End If
SourceModule.AtomicStoreReferenceAndDiagnostics(lazyNetModuleAttributesBag, netModuleAttributesBag, diagnostics)
diagnostics.Free()
Debug.Assert(attributeIndicesToSkip Is Nothing OrElse
Not attributeIndicesToSkip.Any(Function(index) index < 0 OrElse index >= Me.GetAttributes().Length))
End If
Debug.Assert(lazyNetModuleAttributesBag.IsSealed)
End Sub
Friend Overrides Function GetAllTopLevelForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
Return Emit.PEModuleBuilder.GetForwardedTypes(Me, builderOpt:=Nothing)
End Function
Private Sub EnsureNetModuleAttributesAreBound()
If _lazyNetModuleAttributesBag Is Nothing Then
LoadAndValidateNetModuleAttributes(_lazyNetModuleAttributesBag)
End If
End Sub
''' <summary>
''' Returns true if the assembly attribute at the given index is a duplicate assembly attribute that must not be emitted.
''' Duplicate assembly attributes are attributes that bind to the same constructor and have identical arguments.
''' </summary>
''' <remarks>
''' This method must be invoked only after all the assembly attributes have been bound.
''' </remarks>
Friend Function IsIndexOfDuplicateAssemblyAttribute(index As Integer) As Boolean
Debug.Assert(Me._lazySourceAttributesBag.IsSealed)
Debug.Assert(Me._lazyNetModuleAttributesBag.IsSealed)
Debug.Assert(index >= 0)
Debug.Assert(index < Me.GetAttributes().Length)
Debug.Assert(Me._lazyDuplicateAttributeIndices Is Nothing OrElse Not IsNetModule)
Return Me._lazyDuplicateAttributeIndices IsNot Nothing AndAlso Me._lazyDuplicateAttributeIndices.Contains(index)
End Function
Public ReadOnly Property DefaultAttributeLocation As AttributeLocation Implements IAttributeTargetSymbol.DefaultAttributeLocation
Get
Return AttributeLocation.Assembly
End Get
End Property
Friend Function GetAttributeDeclarations() As ImmutableArray(Of SyntaxList(Of AttributeListSyntax))
Dim attributeBlocks = ArrayBuilder(Of SyntaxList(Of AttributeListSyntax)).GetInstance()
Dim declarations = DeclaringCompilation.MergedRootDeclaration.Declarations
For Each rootNs As RootSingleNamespaceDeclaration In declarations
If rootNs.HasAssemblyAttributes Then
Dim compilationUnitSyntax = DirectCast(rootNs.Location.SourceTree.GetRoot(), CompilationUnitSyntax)
Dim attributeStatements = compilationUnitSyntax.Attributes
If attributeStatements.Any Then
For Each statement In attributeStatements
'For Each block In statement.AttributeLists
'attributeBlocks.Add(block)
'Next
attributeBlocks.Add(statement.AttributeLists)
Next
End If
End If
Next
Return attributeBlocks.ToImmutableAndFree()
End Function
''' <summary>
''' Returns a bag of netmodule assembly attributes and data decoded from well-known attributes. Returns null if there are no attributes applied on the symbol.
''' </summary>
''' <remarks>
''' Forces binding and decoding of attributes.
''' </remarks>
Friend Function GetNetModuleAttributesBag() As CustomAttributesBag(Of VisualBasicAttributeData)
EnsureNetModuleAttributesAreBound()
Return _lazyNetModuleAttributesBag
End Function
Private Function GetNetModuleAttributes() As ImmutableArray(Of VisualBasicAttributeData)
Dim attributesBag = Me.GetNetModuleAttributesBag()
Debug.Assert(attributesBag.IsSealed)
Return attributesBag.Attributes
End Function
Friend Function GetNetModuleDecodedWellKnownAttributeData() As CommonAssemblyWellKnownAttributeData
Dim attributesBag = Me.GetNetModuleAttributesBag()
Debug.Assert(attributesBag.IsSealed)
Return DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonAssemblyWellKnownAttributeData)
End Function
''' <summary>
''' Gets the attributes applied on this symbol.
''' Returns an empty array if there are no attributes.
''' </summary>
''' <remarks>
''' NOTE: This method should always be kept as a NotOverridable method.
''' If you want to override attribute binding logic for a sub-class, then override <see cref="GetSourceAttributesBag"/> method.
''' </remarks>
Public Overloads Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData)
Dim attributes = Me.GetSourceAttributesBag().Attributes
Dim netmoduleAttributes = Me.GetNetModuleAttributesBag().Attributes
Debug.Assert(Not attributes.IsDefault)
Debug.Assert(Not netmoduleAttributes.IsDefault)
If attributes.Length > 0 Then
If netmoduleAttributes.Length > 0 Then
attributes = attributes.Concat(netmoduleAttributes)
End If
Else
attributes = netmoduleAttributes
End If
Debug.Assert(Not attributes.IsDefault)
Return attributes
End Function
Friend Function GetSourceAttributesBag() As CustomAttributesBag(Of VisualBasicAttributeData)
EnsureAttributesAreBound()
Return Me._lazySourceAttributesBag
End Function
''' <summary>
''' Returns data decoded from source assembly attributes or null if there are none.
''' </summary>
''' <returns>
''' Forces binding and decoding of attributes.
''' TODO: We should replace methods GetSourceDecodedWellKnownAttributeData and GetNetModuleDecodedWellKnownAttributeData with
''' a single method GetDecodedWellKnownAttributeData, which merges DecodedWellKnownAttributeData from source and netmodule attributes.
''' </returns>
''' <remarks></remarks>
Friend Function GetSourceDecodedWellKnownAttributeData() As CommonAssemblyWellKnownAttributeData
Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me._lazySourceAttributesBag
If attributesBag Is Nothing OrElse Not attributesBag.IsDecodedWellKnownAttributeDataComputed Then
attributesBag = Me.GetSourceAttributesBag()
End If
Return DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonAssemblyWellKnownAttributeData)
End Function
Private Function GetWellKnownAttributeDataStringField(fieldGetter As Func(Of CommonAssemblyWellKnownAttributeData, String), Optional missingValue As String = Nothing) As String
Dim defaultValue As String = missingValue
Dim fieldValue = defaultValue
Dim data = GetSourceDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = fieldGetter(data)
End If
If fieldValue Is missingValue Then
data = GetNetModuleDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = fieldGetter(data)
End If
End If
Return fieldValue
End Function
Friend Function GetSecurityAttributes() As IEnumerable(Of Cci.SecurityAttribute)
Dim sourceSecurityAttributes As IEnumerable(Of Cci.SecurityAttribute) = Nothing
Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me.GetSourceAttributesBag()
Dim wellKnownAttributeData = DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonAssemblyWellKnownAttributeData(Of NamedTypeSymbol))
If wellKnownAttributeData IsNot Nothing Then
Dim securityData As SecurityWellKnownAttributeData = wellKnownAttributeData.SecurityInformation
If securityData IsNot Nothing Then
sourceSecurityAttributes = securityData.GetSecurityAttributes(attributesBag.Attributes)
End If
End If
Dim netmoduleSecurityAttributes As IEnumerable(Of Cci.SecurityAttribute) = Nothing
attributesBag = Me.GetNetModuleAttributesBag()
wellKnownAttributeData = DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonAssemblyWellKnownAttributeData(Of NamedTypeSymbol))
If wellKnownAttributeData IsNot Nothing Then
Dim securityData As SecurityWellKnownAttributeData = wellKnownAttributeData.SecurityInformation
If securityData IsNot Nothing Then
netmoduleSecurityAttributes = securityData.GetSecurityAttributes(attributesBag.Attributes)
End If
End If
Dim securityAttributes As IEnumerable(Of Cci.SecurityAttribute) = Nothing
If sourceSecurityAttributes IsNot Nothing Then
If netmoduleSecurityAttributes IsNot Nothing Then
securityAttributes = sourceSecurityAttributes.Concat(netmoduleSecurityAttributes)
Else
securityAttributes = sourceSecurityAttributes
End If
Else
If netmoduleSecurityAttributes IsNot Nothing Then
securityAttributes = netmoduleSecurityAttributes
Else
securityAttributes = SpecializedCollections.EmptyEnumerable(Of Cci.SecurityAttribute)()
End If
End If
Debug.Assert(securityAttributes IsNot Nothing)
Return securityAttributes
End Function
Friend ReadOnly Property FileVersion As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyFileVersionAttributeSetting)
End Get
End Property
Friend ReadOnly Property Title As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyTitleAttributeSetting)
End Get
End Property
Friend ReadOnly Property Description As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyDescriptionAttributeSetting)
End Get
End Property
Friend ReadOnly Property Company As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyCompanyAttributeSetting)
End Get
End Property
Friend ReadOnly Property Product As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyProductAttributeSetting)
End Get
End Property
Friend ReadOnly Property InformationalVersion As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyInformationalVersionAttributeSetting)
End Get
End Property
Friend ReadOnly Property Copyright As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyCopyrightAttributeSetting)
End Get
End Property
Friend ReadOnly Property Trademark As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyTrademarkAttributeSetting)
End Get
End Property
''' <summary>
''' This represents what the user claimed in source through the AssemblyFlagsAttribute.
''' It may be modified as emitted due to presence or absence of the public key.
''' </summary>
Public ReadOnly Property AssemblyFlags As AssemblyFlags Implements ISourceAssemblySymbolInternal.AssemblyFlags
Get
Dim fieldValue As AssemblyFlags = Nothing
Dim data = GetSourceDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = data.AssemblyFlagsAttributeSetting
End If
data = GetNetModuleDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = fieldValue Or data.AssemblyFlagsAttributeSetting
End If
Return fieldValue
End Get
End Property
Private ReadOnly Property DelaySignAttributeSetting As Boolean
Get
Dim defaultValue = False
Dim fieldValue = defaultValue
Dim data = GetSourceDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = (data.AssemblyDelaySignAttributeSetting = ThreeState.True)
End If
If fieldValue = defaultValue Then
data = GetNetModuleDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = (data.AssemblyDelaySignAttributeSetting = ThreeState.True)
End If
End If
Return fieldValue
End Get
End Property
Public ReadOnly Property SignatureKey As String Implements ISourceAssemblySymbolInternal.SignatureKey
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblySignatureKeyAttributeSetting)
End Get
End Property
Private ReadOnly Property AssemblyKeyContainerAttributeSetting As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyKeyContainerAttributeSetting, CommonAssemblyWellKnownAttributeData.StringMissingValue)
End Get
End Property
Private ReadOnly Property AssemblyKeyFileAttributeSetting As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyKeyFileAttributeSetting, CommonAssemblyWellKnownAttributeData.StringMissingValue)
End Get
End Property
Private ReadOnly Property AssemblyCultureAttributeSetting As String
Get
Return GetWellKnownAttributeDataStringField(Function(data) data.AssemblyCultureAttributeSetting)
End Get
End Property
Private ReadOnly Property AssemblyVersionAttributeSetting As Version
Get
Dim defaultValue As Version = Nothing
Dim fieldValue = defaultValue
Dim data = GetSourceDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = data.AssemblyVersionAttributeSetting
End If
If fieldValue Is defaultValue Then
data = GetNetModuleDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = data.AssemblyVersionAttributeSetting
End If
End If
Return fieldValue
End Get
End Property
Public Overrides ReadOnly Property AssemblyVersionPattern As Version Implements ISourceAssemblySymbolInternal.AssemblyVersionPattern
Get
Dim attributeValue = AssemblyVersionAttributeSetting
Return If(attributeValue Is Nothing OrElse (attributeValue.Build <> UShort.MaxValue AndAlso attributeValue.Revision <> UShort.MaxValue), Nothing, attributeValue)
End Get
End Property
Public ReadOnly Property HashAlgorithm As AssemblyHashAlgorithm Implements ISourceAssemblySymbolInternal.HashAlgorithm
Get
Return If(AssemblyAlgorithmIdAttributeSetting, AssemblyHashAlgorithm.Sha1)
End Get
End Property
Friend ReadOnly Property AssemblyAlgorithmIdAttributeSetting As AssemblyHashAlgorithm?
Get
Dim fieldValue As AssemblyHashAlgorithm? = Nothing
Dim data = GetSourceDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = data.AssemblyAlgorithmIdAttributeSetting
End If
If fieldValue Is Nothing Then
data = GetNetModuleDecodedWellKnownAttributeData()
If data IsNot Nothing Then
fieldValue = data.AssemblyAlgorithmIdAttributeSetting
End If
End If
Return fieldValue
End Get
End Property
Private Sub EnsureAttributesAreBound()
If _lazySourceAttributesBag Is Nothing OrElse Not _lazySourceAttributesBag.IsSealed Then
LoadAndValidateAttributes(OneOrMany.Create(GetAttributeDeclarations()), _lazySourceAttributesBag)
End If
End Sub
' TODO: cache
Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
Get
Return Me.Modules.SelectMany(Function(m) m.Locations).AsImmutable()
End Get
End Property
Public Overrides ReadOnly Property Modules As ImmutableArray(Of ModuleSymbol)
Get
Return _modules
End Get
End Property
Friend Overrides Function GetNoPiaResolutionAssemblies() As ImmutableArray(Of AssemblySymbol)
Return SourceModule.GetReferencedAssemblySymbols()
End Function
Friend Overrides Sub SetNoPiaResolutionAssemblies(assemblies As ImmutableArray(Of AssemblySymbol))
Throw ExceptionUtilities.Unreachable
End Sub
Friend Overrides Function GetLinkedReferencedAssemblies() As ImmutableArray(Of AssemblySymbol)
' SourceAssemblySymbol is never used directly as a reference
' when it is or any of its references is linked.
Return Nothing
End Function
Friend Overrides Sub SetLinkedReferencedAssemblies(assemblies As ImmutableArray(Of AssemblySymbol))
' SourceAssemblySymbol is never used directly as a reference
' when it is or any of its references is linked.
Throw ExceptionUtilities.Unreachable
End Sub
Friend Overrides ReadOnly Property IsLinked As Boolean
Get
Return False
End Get
End Property
' Computing the identity requires computing the public key. Computing the public key
' can require binding attributes that contain version or strong name information.
' Attribute binding will check type visibility which will possibly
' check IVT relationships. To correctly determine the IVT relationship requires the public key.
' To avoid infinite recursion, this type notes, per thread, the assembly for which the thread
' is actively computing the public key (s_AssemblyForWhichCurrentThreadIsComputingKeys). Should a request to determine IVT
' relationship occur on the thread that is computing the public key, access is optimistically
' granted provided the simple assembly names match. When such access is granted
' the assembly to which we have been granted access is noted (m_optimisticallyGrantedInternalsAccess).
' After the public key has been computed, the set of optimistic grants is reexamined
' to ensure that full identities match. This may produce diagnostics.
' EDMAURER please don't use thread local storage widely. This is hoped to be a one-off usage.
<ThreadStatic()>
Private Shared s_AssemblyForWhichCurrentThreadIsComputingKeys As AssemblySymbol
' A collection of assemblies to which we were granted internals access by only checking matches for assembly name
' and ignoring public key. This just acts as a set. The Boolean is ignored.
Private _optimisticallyGrantedInternalsAccess As ConcurrentDictionary(Of AssemblySymbol, Boolean)
' Once the computation of the AssemblyIdentity is complete, check whether
' any of the IVT access grants that were optimistically made during AssemblyIdentity computation
' are in fact invalid now that the full identity is known.
Private Sub CheckOptimisticIVTAccessGrants(bag As BindingDiagnosticBag)
Dim haveGrantedAssemblies As ConcurrentDictionary(Of AssemblySymbol, Boolean) = _optimisticallyGrantedInternalsAccess
If haveGrantedAssemblies IsNot Nothing Then
For Each otherAssembly In haveGrantedAssemblies.Keys
Dim conclusion As IVTConclusion = MakeFinalIVTDetermination(otherAssembly)
Debug.Assert(conclusion <> IVTConclusion.NoRelationshipClaimed)
If conclusion = IVTConclusion.PublicKeyDoesntMatch Then
bag.Add(New VBDiagnostic(ErrorFactory.ErrorInfo(ERRID.ERR_FriendRefNotEqualToThis,
otherAssembly.Identity,
Me.Identity),
NoLocation.Singleton))
ElseIf conclusion = IVTConclusion.OneSignedOneNot Then
bag.Add(New VBDiagnostic(ErrorFactory.ErrorInfo(ERRID.ERR_FriendRefSigningMismatch,
otherAssembly.Identity,
Me.Identity),
NoLocation.Singleton))
End If
Next
End If
End Sub
Friend Overrides Function GetInternalsVisibleToPublicKeys(simpleName As String) As IEnumerable(Of ImmutableArray(Of Byte))
'EDMAURER assume that if EnsureAttributesAreBound() returns, then the internals visible to map has been populated.
'Do not optimize by checking if m_lazyInternalsVisibleToMap is Nothing. It may be non-null yet still
'incomplete because another thread is in the process of building it.
EnsureAttributesAreBound()
If _lazyInternalsVisibleToMap Is Nothing Then
Return SpecializedCollections.EmptyEnumerable(Of ImmutableArray(Of Byte))()
End If
Dim result As ConcurrentDictionary(Of ImmutableArray(Of Byte), Tuple(Of Location, String)) = Nothing
_lazyInternalsVisibleToMap.TryGetValue(simpleName, result)
Return If(result IsNot Nothing, result.Keys, SpecializedCollections.EmptyEnumerable(Of ImmutableArray(Of Byte))())
End Function
Friend Overrides Function GetInternalsVisibleToAssemblyNames() As IEnumerable(Of String)
EnsureAttributesAreBound()
If _lazyInternalsVisibleToMap Is Nothing Then
Return SpecializedCollections.EmptyEnumerable(Of String)()
End If
Return _lazyInternalsVisibleToMap.Keys
End Function
Friend ReadOnly Property DeclaresTheObjectClass As Boolean
Get
If Me.CorLibrary IsNot Me Then
Return False
End If
Dim obj = GetSpecialType(SpecialType.System_Object)
Return Not obj.IsErrorType() AndAlso obj.DeclaredAccessibility = Accessibility.Public
End Get
End Property
Friend ReadOnly Property SourceModule As SourceModuleSymbol
Get
Return DirectCast(_modules(0), SourceModuleSymbol)
End Get
End Property
Public Overrides ReadOnly Property MightContainExtensionMethods As Boolean
Get
' Only primary module of an assembly marked with an Extension attribute
' can contain extension methods recognized by the language (Dev10 behavior).
Return SourceModule.MightContainExtensionMethods
End Get
End Property
Private Function ProcessOneInternalsVisibleToAttribute(nodeOpt As AttributeSyntax, attrData As VisualBasicAttributeData, diagnostics As BindingDiagnosticBag) As Boolean
'assume that this code won't be called unless we bound a well-formed, semantically
'correct ctor call.
Dim displayName As String = TryCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
If displayName Is Nothing Then
diagnostics.Add(ERRID.ERR_FriendAssemblyNameInvalid, If(nodeOpt IsNot Nothing, nodeOpt.GetLocation(), NoLocation.Singleton), "")
Return False
End If
Dim identity As AssemblyIdentity = Nothing
Dim parts As AssemblyIdentityParts = Nothing
If Not AssemblyIdentity.TryParseDisplayName(displayName, identity, parts) Then
diagnostics.Add(ERRID.ERR_FriendAssemblyNameInvalid, If(nodeOpt IsNot Nothing, nodeOpt.GetLocation(), NoLocation.Singleton), displayName)
Return False
End If
' Allow public key token due to compatibility reasons, but we are not going to use its value.
Const allowedParts = AssemblyIdentityParts.Name Or AssemblyIdentityParts.PublicKey Or AssemblyIdentityParts.PublicKeyToken
If (parts And Not allowedParts) <> 0 Then
diagnostics.Add(ERRID.ERR_FriendAssemblyBadArguments, If(nodeOpt IsNot Nothing, nodeOpt.GetLocation(), NoLocation.Singleton), displayName)
Return False
End If
If _lazyInternalsVisibleToMap Is Nothing Then
Interlocked.CompareExchange(_lazyInternalsVisibleToMap,
New ConcurrentDictionary(Of String, ConcurrentDictionary(Of ImmutableArray(Of Byte), Tuple(Of Location, String)))(StringComparer.OrdinalIgnoreCase), Nothing)
End If
'later, once the identity is established we confirm that if the assembly being
'compiled is signed all of the IVT attributes specify a key. Stash the location for that
' in the event that a diagnostic needs to be produced.
Dim locationAndValue As Tuple(Of Location, String) = Nothing
' only need to store anything when there is no public key. The only reason to store
' this stuff is for production of errors when the assembly is signed but the IVT attrib
' doesn't contain a public key.
If identity.PublicKey.IsEmpty Then
locationAndValue = New Tuple(Of Location, String)(If(nodeOpt IsNot Nothing, nodeOpt.GetLocation(), NoLocation.Singleton), displayName)
End If
'when two threads are attempting to update the internalsVisibleToMap one of these TryAdd()
'calls can fail. We assume that the 'other' thread in that case will successfully add the same
'contents eventually.
Dim keys As ConcurrentDictionary(Of ImmutableArray(Of Byte), Tuple(Of Location, String)) = Nothing
If _lazyInternalsVisibleToMap.TryGetValue(identity.Name, keys) Then
keys.TryAdd(identity.PublicKey, locationAndValue)
Else
keys = New ConcurrentDictionary(Of ImmutableArray(Of Byte), Tuple(Of Location, String))
keys.TryAdd(identity.PublicKey, locationAndValue)
_lazyInternalsVisibleToMap.TryAdd(identity.Name, keys)
End If
Return True
End Function
Friend Overrides Sub DecodeWellKnownAttribute(ByRef arguments As DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation))
Dim attrData = arguments.Attribute
Debug.Assert(Not attrData.HasErrors)
Debug.Assert(arguments.SymbolPart = AttributeLocation.None)
Dim diagnostics = DirectCast(arguments.Diagnostics, BindingDiagnosticBag)
If attrData.IsTargetAttribute(AttributeDescription.CaseInsensitiveExtensionAttribute) Then
' Already have an attribute, no need to add another one.
Debug.Assert(_lazyEmitExtensionAttribute <> ThreeState.True)
_lazyEmitExtensionAttribute = ThreeState.False
ElseIf attrData.IsTargetAttribute(AttributeDescription.InternalsVisibleToAttribute) Then
ProcessOneInternalsVisibleToAttribute(arguments.AttributeSyntaxOpt, attrData, diagnostics)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblySignatureKeyAttribute) Then
Dim signatureKey = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblySignatureKeyAttributeSetting = signatureKey
If Not StrongNameKeys.IsValidPublicKeyString(signatureKey) Then
diagnostics.Add(ERRID.ERR_InvalidSignaturePublicKey, GetAssemblyAttributeFirstArgumentLocation(arguments.AttributeSyntaxOpt))
End If
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyKeyFileAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyKeyFileAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyKeyNameAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyKeyContainerAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyDelaySignAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyDelaySignAttributeSetting = If(DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, Boolean), ThreeState.True, ThreeState.False)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyVersionAttribute) Then
Dim verString = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
Dim version As Version = Nothing
If Not VersionHelper.TryParseAssemblyVersion(verString, allowWildcard:=Not _compilation.IsEmitDeterministic, version:=version) Then
Dim attributeArgumentSyntaxLocation As Location = GetAssemblyAttributeFirstArgumentLocation(arguments.AttributeSyntaxOpt)
If _compilation.IsEmitDeterministic AndAlso verString?.Contains("*"c) = True Then
diagnostics.Add(ERRID.ERR_InvalidVersionFormatDeterministic, attributeArgumentSyntaxLocation)
Else
diagnostics.Add(ERRID.ERR_InvalidVersionFormat, attributeArgumentSyntaxLocation)
End If
End If
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyVersionAttributeSetting = version
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyFileVersionAttribute) Then
Dim dummy As Version = Nothing
Dim verString = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
If Not VersionHelper.TryParse(verString, version:=dummy) Then
diagnostics.Add(ERRID.WRN_InvalidVersionFormat, GetAssemblyAttributeFirstArgumentLocation(arguments.AttributeSyntaxOpt))
End If
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyFileVersionAttributeSetting = verString
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyInformationalVersionAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyInformationalVersionAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyTitleAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyTitleAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyDescriptionAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyDescriptionAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyCultureAttribute) Then
Dim cultureString = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
If Not String.IsNullOrEmpty(cultureString) Then
If Me.DeclaringCompilation.Options.OutputKind.IsApplication() Then
diagnostics.Add(ERRID.ERR_InvalidAssemblyCultureForExe, GetAssemblyAttributeFirstArgumentLocation(arguments.AttributeSyntaxOpt))
ElseIf Not AssemblyIdentity.IsValidCultureName(cultureString) Then
diagnostics.Add(ERRID.ERR_InvalidAssemblyCulture, GetAssemblyAttributeFirstArgumentLocation(arguments.AttributeSyntaxOpt))
cultureString = Nothing
End If
End If
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyCultureAttributeSetting = cultureString
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyCompanyAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyCompanyAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyProductAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyProductAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyInformationalVersionAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyInformationalVersionAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.SatelliteContractVersionAttribute) Then
'just check the format of this one, don't do anything else with it.
Dim dummy As Version = Nothing
Dim verString = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
If Not VersionHelper.TryParseAssemblyVersion(verString, allowWildcard:=False, version:=dummy) Then
diagnostics.Add(ERRID.ERR_InvalidVersionFormat2, GetAssemblyAttributeFirstArgumentLocation(arguments.AttributeSyntaxOpt))
End If
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyCopyrightAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyCopyrightAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsTargetAttribute(AttributeDescription.AssemblyTrademarkAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyTrademarkAttributeSetting = DirectCast(attrData.CommonConstructorArguments(0).ValueInternal, String)
ElseIf attrData.IsSecurityAttribute(Me.DeclaringCompilation) Then
attrData.DecodeSecurityAttribute(Of CommonAssemblyWellKnownAttributeData)(Me, Me.DeclaringCompilation, arguments)
ElseIf attrData.IsTargetAttribute(AttributeDescription.ClassInterfaceAttribute) Then
attrData.DecodeClassInterfaceAttribute(arguments.AttributeSyntaxOpt, diagnostics)
ElseIf attrData.IsTargetAttribute(AttributeDescription.TypeLibVersionAttribute) Then
ValidateIntegralAttributeNonNegativeArguments(attrData, arguments.AttributeSyntaxOpt, diagnostics)
ElseIf attrData.IsTargetAttribute(AttributeDescription.ComCompatibleVersionAttribute) Then
ValidateIntegralAttributeNonNegativeArguments(attrData, arguments.AttributeSyntaxOpt, diagnostics)
ElseIf attrData.IsTargetAttribute(AttributeDescription.GuidAttribute) Then
Dim guidString As String = attrData.DecodeGuidAttribute(arguments.AttributeSyntaxOpt, diagnostics)
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().GuidAttribute = guidString
ElseIf attrData.IsTargetAttribute(AttributeDescription.ImportedFromTypeLibAttribute) Then
If attrData.CommonConstructorArguments.Length = 1 Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().HasImportedFromTypeLibAttribute = True
End If
ElseIf attrData.IsTargetAttribute(AttributeDescription.PrimaryInteropAssemblyAttribute) Then
If attrData.CommonConstructorArguments.Length = 2 Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().HasPrimaryInteropAssemblyAttribute = True
End If
ElseIf attrData.IsTargetAttribute(AttributeDescription.CompilationRelaxationsAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().HasCompilationRelaxationsAttribute = True
ElseIf attrData.IsTargetAttribute(AttributeDescription.ReferenceAssemblyAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().HasReferenceAssemblyAttribute = True
ElseIf attrData.IsTargetAttribute(AttributeDescription.RuntimeCompatibilityAttribute) Then
' VB doesn't need to decode argument values
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().RuntimeCompatibilityWrapNonExceptionThrows = True
ElseIf attrData.IsTargetAttribute(AttributeDescription.DebuggableAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().HasDebuggableAttribute = True
ElseIf attrData.IsTargetAttribute(AttributeDescription.ExperimentalAttribute) Then
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().ExperimentalAttributeData = attrData.DecodeExperimentalAttribute()
Else
Dim signature As Integer = attrData.GetTargetAttributeSignatureIndex(AttributeDescription.AssemblyAlgorithmIdAttribute)
If signature <> -1 Then
Dim value As Object = attrData.CommonConstructorArguments(0).ValueInternal
Dim algorithmId As AssemblyHashAlgorithm
If signature = 0 Then
algorithmId = CType(value, AssemblyHashAlgorithm)
Else
algorithmId = CType(CUInt(value), AssemblyHashAlgorithm)
End If
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyAlgorithmIdAttributeSetting = algorithmId
Else
signature = attrData.GetTargetAttributeSignatureIndex(AttributeDescription.AssemblyFlagsAttribute)
If signature <> -1 Then
Dim value As Object = attrData.CommonConstructorArguments(0).ValueInternal
Dim nameFlags As AssemblyFlags
If signature = 0 OrElse signature = 1 Then
nameFlags = CType(CType(value, AssemblyNameFlags), AssemblyFlags)
Else
nameFlags = CType(CUInt(value), AssemblyFlags)
End If
arguments.GetOrCreateData(Of CommonAssemblyWellKnownAttributeData)().AssemblyFlagsAttributeSetting = nameFlags
End If
End If
End If
MyBase.DecodeWellKnownAttribute(arguments)
End Sub
Private Shared Function GetAssemblyAttributeFirstArgumentLocation(attributeSyntaxOpt As AttributeSyntax) As Location
If attributeSyntaxOpt Is Nothing Then
Return NoLocation.Singleton
End If
Return attributeSyntaxOpt.ArgumentList.Arguments.First().GetLocation()
End Function
' Checks that the integral arguments for the given well-known attribute are non-negative.
Private Sub ValidateIntegralAttributeNonNegativeArguments(attrData As VisualBasicAttributeData, nodeOpt As AttributeSyntax, diagnostics As BindingDiagnosticBag)
Debug.Assert(Not attrData.HasErrors)
Dim argCount As Integer = attrData.CommonConstructorArguments.Length
For i = 0 To argCount - 1
Dim arg As Integer = attrData.GetConstructorArgument(Of Integer)(i, SpecialType.System_Int32)
If arg < 0 Then
diagnostics.Add(ERRID.ERR_BadAttribute1, VisualBasicAttributeData.GetArgumentLocation(nodeOpt, i), attrData.AttributeClass)
End If
Next
End Sub
Friend Sub AnErrorHasBeenReportedAboutExtensionAttribute()
' Note, we are storing false because, even though we might be required to emit the attribute,
' we can't do that due to the error that we just reported.
Debug.Assert(_lazyEmitExtensionAttribute <> ThreeState.True)
_lazyEmitExtensionAttribute = ThreeState.False
End Sub
Friend Sub GetAllDeclarationErrors(diagnostics As BindingDiagnosticBag, Optional cancellationToken As CancellationToken = Nothing)
Dim hasExtensionMethods As Boolean = False
SourceModule.GetAllDeclarationErrors(diagnostics, cancellationToken, hasExtensionMethods)
diagnostics.AddRange(GetAssemblyLevelDeclarationErrors(hasExtensionMethods), allowMismatchInDependencyAccumulation:=True)
End Sub
''' <summary>
''' Get assembly level declaration errors.
''' </summary>
Private Function GetAssemblyLevelDeclarationErrors(
haveExtensionMethodsInSource As Boolean) As ReadOnlyBindingDiagnostic(Of AssemblySymbol)
If _lazyAssemblyLevelDeclarationErrors.IsDefault OrElse _lazyAssemblyLevelDeclarationDependencies.IsDefault Then
Dim diagnostics = BindingDiagnosticBag.GetInstance()
Dim emitExtensionAttribute As ThreeState = CType(_lazyEmitExtensionAttribute, ThreeState)
If emitExtensionAttribute = ThreeState.Unknown Then
Dim needAttribute As Boolean = haveExtensionMethodsInSource
If Not needAttribute Then
emitExtensionAttribute = ThreeState.False
Else
' We need to emit an Extension attribute on the assembly.
' Can we locate it?
Dim useSiteInfo As UseSiteInfo(Of AssemblySymbol) = Nothing
_compilation.GetExtensionAttributeConstructor(useSiteInfo:=useSiteInfo)
If useSiteInfo.DiagnosticInfo IsNot Nothing Then
' Note, we are storing false because, even though we should emit the attribute,
' we can't do that due to the use site error.
' The diagnostic itself was already reported at the location where the attribute was applied to.
' Reporting it also on a place where it's implicitly used would not be expected by developers.
emitExtensionAttribute = ThreeState.False
Else
emitExtensionAttribute = ThreeState.True
End If
End If
End If
Debug.Assert(_lazyEmitExtensionAttribute = ThreeState.Unknown OrElse
_lazyEmitExtensionAttribute = emitExtensionAttribute)
_lazyEmitExtensionAttribute = emitExtensionAttribute
'strong name key settings are not validated when building netmodules.
'They are validated when the netmodule is added to an assembly.
If StrongNameKeys.DiagnosticOpt IsNot Nothing AndAlso Not IsNetModule Then
diagnostics.Add(StrongNameKeys.DiagnosticOpt)
End If
ValidateIVTPublicKeys(diagnostics)
CheckOptimisticIVTAccessGrants(diagnostics)
DetectAttributeAndOptionConflicts(diagnostics)
If IsDelaySigned AndAlso Not Identity.HasPublicKey Then
diagnostics.Add(ERRID.WRN_DelaySignButNoKey, NoLocation.Singleton)
End If
If DeclaringCompilation.Options.PublicSign Then
If IsNetModule Then
diagnostics.Add(ERRID.ERR_PublicSignNetModule, NoLocation.Singleton)
ElseIf Not Identity.HasPublicKey Then
diagnostics.Add(ERRID.ERR_PublicSignNoKey, NoLocation.Singleton)
End If
End If
' If the options and attributes applied on the compilation imply real signing,
' but we have no private key to sign it with report an error.
' Note that if public key is set and delay sign is off we do OSS signing, which doesn't require private key.
' Consider: should we allow to OSS sign if the key file only contains public key?
If DeclaringCompilation.Options.OutputKind <> OutputKind.NetModule AndAlso
DeclaringCompilation.Options.CryptoPublicKey.IsEmpty AndAlso
Identity.HasPublicKey AndAlso
Not IsDelaySigned AndAlso
Not DeclaringCompilation.Options.PublicSign AndAlso
Not StrongNameKeys.CanSign Then
' Since the container always contains both keys, the problem is that the key file didn't contain private key.
diagnostics.Add(ERRID.ERR_SignButNoPrivateKey, NoLocation.Singleton, StrongNameKeys.KeyFilePath)
End If
ReportDiagnosticsForSynthesizedAttributes(DeclaringCompilation, diagnostics)
ReportDiagnosticsForAddedModules(diagnostics)
Dim immutableBindingDiagnostic As ReadOnlyBindingDiagnostic(Of AssemblySymbol) = diagnostics.ToReadOnlyAndFree()
ImmutableInterlocked.InterlockedInitialize(_lazyAssemblyLevelDeclarationDependencies, immutableBindingDiagnostic.Dependencies)
ImmutableInterlocked.InterlockedInitialize(_lazyAssemblyLevelDeclarationErrors, immutableBindingDiagnostic.Diagnostics)
End If
Debug.Assert(Not _lazyAssemblyLevelDeclarationErrors.IsDefault)
Debug.Assert(Not _lazyAssemblyLevelDeclarationDependencies.IsDefault)
Return New ReadOnlyBindingDiagnostic(Of AssemblySymbol)(_lazyAssemblyLevelDeclarationErrors, _lazyAssemblyLevelDeclarationDependencies)
End Function
Private Sub DetectAttributeAndOptionConflicts(diagnostics As BindingDiagnosticBag)
EnsureAttributesAreBound()
If _compilation.Options.PublicSign AndAlso DelaySignAttributeSetting Then
diagnostics.Add(ERRID.ERR_CmdOptionConflictsSource, NoLocation.Singleton,
AttributeDescription.AssemblyDelaySignAttribute.FullName,
NameOf(_compilation.Options.PublicSign))
End If
If _compilation.Options.OutputKind = OutputKind.NetModule Then
If Not String.IsNullOrEmpty(_compilation.Options.CryptoKeyContainer) Then
Dim assemblyKeyContainerAttributeSetting As String = Me.AssemblyKeyContainerAttributeSetting
If assemblyKeyContainerAttributeSetting Is CommonAssemblyWellKnownAttributeData.StringMissingValue Then
' We need to synthesize this attribute for .NET module,
' touch the constructor in order to generate proper use-site diagnostics
Binder.ReportUseSiteInfoForSynthesizedAttribute(
WellKnownMember.System_Reflection_AssemblyKeyNameAttribute__ctor,
_compilation,
NoLocation.Singleton,
diagnostics)
ElseIf String.Compare(_compilation.Options.CryptoKeyContainer, assemblyKeyContainerAttributeSetting, StringComparison.OrdinalIgnoreCase) <> 0 Then
' If we are building a .NET module, things get more complicated. In particular, we don't sign the module, we emit an attribute with the key
' information, which will be used to sign an assembly once the module is linked into it. If there is already an attribute like that in source,
' native compiler emits both of them, synthetic attribute is emitted after the one from source. Incidentally, ALink picks the last attribute
' for signing and things seem to work out. However, relying on the order of attributes feels fragile, especially given that Roslyn emits
' synthetic attributes before attributes from source. The behavior we settled on for .NET modules is that, if the attribute in source has the
' same value as the one in compilation options, we won't emit the synthetic attribute. If the value doesn't match, we report an error, which
' is a breaking change. Bottom line, we will never produce a module or an assembly with two attributes, regardless whether values are the same
' or not.
diagnostics.Add(ERRID.ERR_CmdOptionConflictsSource, NoLocation.Singleton, AttributeDescription.AssemblyKeyNameAttribute.FullName, "CryptoKeyContainer")
End If
End If
If Not String.IsNullOrEmpty(_compilation.Options.CryptoKeyFile) Then
Dim assemblyKeyFileAttributeSetting As String = Me.AssemblyKeyFileAttributeSetting
If assemblyKeyFileAttributeSetting Is CommonAssemblyWellKnownAttributeData.StringMissingValue Then
' We need to synthesize this attribute for .NET module,
' touch the constructor in order to generate proper use-site diagnostics
Binder.ReportUseSiteInfoForSynthesizedAttribute(
WellKnownMember.System_Reflection_AssemblyKeyFileAttribute__ctor,
_compilation,
NoLocation.Singleton,
diagnostics)
ElseIf String.Compare(_compilation.Options.CryptoKeyFile, assemblyKeyFileAttributeSetting, StringComparison.OrdinalIgnoreCase) <> 0 Then
' Comment in similar section for CryptoKeyContainer is applicable here as well.
diagnostics.Add(ERRID.ERR_CmdOptionConflictsSource, NoLocation.Singleton, AttributeDescription.AssemblyKeyFileAttribute.FullName, "CryptoKeyFile")
End If
End If
ElseIf _compilation.Options.PublicSign Then
If Me.AssemblyKeyContainerAttributeSetting IsNot CommonAssemblyWellKnownAttributeData.StringMissingValue Then
diagnostics.Add(ERRID.WRN_AttributeIgnoredWhenPublicSigning, NoLocation.Singleton, AttributeDescription.AssemblyKeyNameAttribute.FullName)
End If
If Me.AssemblyKeyFileAttributeSetting IsNot CommonAssemblyWellKnownAttributeData.StringMissingValue Then
diagnostics.Add(ERRID.WRN_AttributeIgnoredWhenPublicSigning, NoLocation.Singleton, AttributeDescription.AssemblyKeyFileAttribute.FullName)
End If
End If
End Sub
Private Sub ReportDiagnosticsForAddedModules(diagnostics As BindingDiagnosticBag)
For Each pair In _compilation.GetBoundReferenceManager().ReferencedModuleIndexMap
Dim fileRef = TryCast(pair.Key, PortableExecutableReference)
If fileRef IsNot Nothing AndAlso fileRef.FilePath IsNot Nothing Then
Dim fileName As String = FileNameUtilities.GetFileName(fileRef.FilePath)
Dim moduleName As String = _modules(pair.Value).Name
If Not String.Equals(fileName, moduleName, StringComparison.OrdinalIgnoreCase) Then
' Used to be ERR_UnableToEmitAssembly
diagnostics.Add(ERRID.ERR_NetModuleNameMismatch, NoLocation.Singleton, moduleName, fileName)
End If
End If
Next
' Alink performed these checks only when emitting an assembly.
If _modules.Length > 1 AndAlso Not _compilation.Options.OutputKind.IsNetModule() Then
Dim assemblyMachine = Me.Machine
Dim isPlatformAgnostic As Boolean = (assemblyMachine = PortableExecutable.Machine.I386 AndAlso Not Me.Bit32Required)
Dim knownModuleNames As New HashSet(Of String)(StringComparer.OrdinalIgnoreCase)
For i As Integer = 1 To Modules.Length - 1
Dim m As ModuleSymbol = Modules(i)
If Not knownModuleNames.Add(m.Name) Then
diagnostics.Add(ERRID.ERR_NetModuleNameMustBeUnique, NoLocation.Singleton, m.Name)
End If
If Not DirectCast(m, PEModuleSymbol).Module.IsCOFFOnly Then
Dim moduleMachine = m.Machine
If moduleMachine = PortableExecutable.Machine.I386 AndAlso Not m.Bit32Required Then
' Other module is agnostic, this is always safe
ElseIf isPlatformAgnostic Then
diagnostics.Add(ERRID.ERR_AgnosticToMachineModule, NoLocation.Singleton, m)
ElseIf assemblyMachine <> moduleMachine Then
' Different machine types, and neither is agnostic
' So it is a conflict
diagnostics.Add(ERRID.ERR_ConflictingMachineModule, NoLocation.Singleton, m)
End If
End If
Next
' Assembly main module must explicitly reference all the modules referenced by other assembly
' modules, i.e. all modules from transitive closure must be referenced explicitly here
For i As Integer = 1 To Modules.Length - 1
Dim m = DirectCast(Modules(i), PEModuleSymbol)
Try
For Each referencedModuleName In m.Module.GetReferencedManagedModulesOrThrow()
' Do not report error for this module twice
If knownModuleNames.Add(referencedModuleName) Then
diagnostics.Add(ERRID.ERR_MissingNetModuleReference, NoLocation.Singleton, referencedModuleName)
End If
Next
Catch mrEx As BadImageFormatException
diagnostics.Add(ERRID.ERR_UnsupportedModule1, NoLocation.Singleton, m)
End Try
Next
End If
End Sub
Friend ReadOnly Property IsDelaySigned As Boolean
Get
EnsureAttributesAreBound()
'TODO need to figure out the right behavior when command line and
'attribute value conflict. Does command line setting need to be three-valued?
If (DeclaringCompilation.Options.DelaySign.HasValue) Then
Return DeclaringCompilation.Options.DelaySign.Value
End If
Return DelaySignAttributeSetting
End Get
End Property
Protected Sub ValidateIVTPublicKeys(diagnostics As BindingDiagnosticBag)
EnsureAttributesAreBound()
If Not Me.Identity.IsStrongName Then
Return
End If
If _lazyInternalsVisibleToMap IsNot Nothing Then
For Each keys In _lazyInternalsVisibleToMap.Values
For Each oneKey In keys
If oneKey.Key.IsDefaultOrEmpty Then
diagnostics.Add(ERRID.ERR_FriendAssemblyStrongNameRequired, oneKey.Value.Item1, oneKey.Value.Item2)
End If
Next
Next
End If
End Sub
''' <summary>
''' True if internals are exposed at all.
''' </summary>
''' <remarks>
''' Forces binding and decoding of attributes.
''' This property shouldn't be accessed during binding as it can lead to attribute binding cycle.
''' </remarks>
Public ReadOnly Property InternalsAreVisible As Boolean Implements ISourceAssemblySymbolInternal.InternalsAreVisible
Get
EnsureAttributesAreBound()
Return _lazyInternalsVisibleToMap IsNot Nothing
End Get
End Property
''' <summary>
''' We may synthesize some well-known attributes for this assembly symbol. However, at synthesis time, it is
''' too late to report diagnostics or cancel the emit. Instead, we check for use site errors on the types and members
''' we know we'll need at synthesis time.
''' </summary>
Private Shared Sub ReportDiagnosticsForSynthesizedAttributes(compilation As VisualBasicCompilation, diagnostics As BindingDiagnosticBag)
' May need to synthesize CompilationRelaxationsAttribute and/or RuntimeCompatibilityAttribute if we are not building a net-module.
' NOTE: Native compiler skips synthesizing these attributes if the respective well-known attribute types aren't available, we do the same.
Dim compilationOptions As VisualBasicCompilationOptions = compilation.Options
If Not compilationOptions.OutputKind.IsNetModule() Then
Dim compilationRelaxationsAttributeType = compilation.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_CompilationRelaxationsAttribute)
If TryCast(compilationRelaxationsAttributeType, MissingMetadataTypeSymbol) Is Nothing Then
Binder.ReportUseSiteInfoForSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_CompilationRelaxationsAttribute__ctorInt32, compilation, NoLocation.Singleton, diagnostics)
End If
Dim runtimeCompatibilityAttributeType = compilation.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute)
If TryCast(runtimeCompatibilityAttributeType, MissingMetadataTypeSymbol) Is Nothing Then
Binder.ReportUseSiteInfoForSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute__ctor, compilation, NoLocation.Singleton, diagnostics)
Binder.ReportUseSiteInfoForSynthesizedAttribute(WellKnownMember.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute__WrapNonExceptionThrows, compilation, NoLocation.Singleton, diagnostics)
End If
End If
End Sub
Private ReadOnly Property HasAssemblyOrModuleDebuggableAttribute As Boolean
Get
Dim assemblyData As CommonAssemblyWellKnownAttributeData = Me.GetSourceDecodedWellKnownAttributeData()
If assemblyData IsNot Nothing AndAlso assemblyData.HasDebuggableAttribute Then
Return True
End If
Dim moduleData As CommonModuleWellKnownAttributeData = Me.SourceModule.GetDecodedWellKnownAttributeData()
If moduleData IsNot Nothing AndAlso moduleData.HasDebuggableAttribute Then
Return True
End If
Return False
End Get
End Property
Private ReadOnly Property HasReferenceAssemblyAttribute As Boolean
Get
Dim assemblyData As CommonAssemblyWellKnownAttributeData = Me.GetSourceDecodedWellKnownAttributeData()
Return assemblyData IsNot Nothing AndAlso assemblyData.HasReferenceAssemblyAttribute
End Get
End Property
Friend Overrides Function GetGuidString(ByRef guidString As String) As Boolean
guidString = GetSourceDecodedWellKnownAttributeData()?.GuidAttribute
Return guidString IsNot Nothing
End Function
Friend Overrides Sub AddSynthesizedAttributes(moduleBuilder As PEModuleBuilder, ByRef attributes As ArrayBuilder(Of SynthesizedAttributeData))
MyBase.AddSynthesizedAttributes(moduleBuilder, attributes)
Debug.Assert(_lazyEmitExtensionAttribute <> ThreeState.Unknown)
Debug.Assert(_lazySourceAttributesBag.IsSealed)
Dim options As VisualBasicCompilationOptions = Me.DeclaringCompilation.Options
Dim isBuildingNetModule As Boolean = options.OutputKind.IsNetModule()
Dim emitExtensionAttribute As Boolean = _lazyEmitExtensionAttribute = ThreeState.True
If emitExtensionAttribute Then
AddSynthesizedAttribute(attributes, _compilation.SynthesizeExtensionAttribute())
End If
' Note that manager's collection of referenced symbols may not be sealed
' yet in case this and previous emits didn't emit IL, but only metadata
Dim emitEmbeddedAttribute As Boolean = Me.DeclaringCompilation.EmbeddedSymbolManager.IsAnySymbolReferenced
If emitEmbeddedAttribute Then
AddSynthesizedAttribute(attributes, DeclaringCompilation.TrySynthesizeAttribute(WellKnownMember.Microsoft_VisualBasic_Embedded__ctor))
End If
' Synthesize CompilationRelaxationsAttribute only if all the following requirements are met:
' (a) We are not building a netmodule.
' (b) There is no applied CompilationRelaxationsAttribute assembly attribute in source.
' (c) There is no applied CompilationRelaxationsAttribute assembly attribute for any of the added PE modules.
' Above requirements also hold for synthesizing RuntimeCompatibilityAttribute attribute.
Dim emitCompilationRelaxationsAttribute As Boolean = Not isBuildingNetModule AndAlso Not Me.Modules.Any(Function(m) m.HasAssemblyCompilationRelaxationsAttribute)
If emitCompilationRelaxationsAttribute Then
' Synthesize attribute: <CompilationRelaxationsAttribute(CompilationRelaxations.NoStringInterning)>
' NOTE: Native compiler skips synthesizing these attributes if the respective well-known attribute types aren't available, we do the same.
Dim compilationRelaxationsAttributeType = DeclaringCompilation.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_CompilationRelaxationsAttribute)
If TryCast(compilationRelaxationsAttributeType, MissingMetadataTypeSymbol) Is Nothing Then
Dim int32Type = Me.DeclaringCompilation.GetSpecialType(SpecialType.System_Int32)
Debug.Assert(int32Type.GetUseSiteInfo().DiagnosticInfo Is Nothing, "Use site errors should have been checked ahead of time (type int).")
Dim typedConstantNoStringInterning = New TypedConstant(int32Type, TypedConstantKind.Primitive, Cci.Constants.CompilationRelaxations_NoStringInterning)
AddSynthesizedAttribute(attributes, DeclaringCompilation.TrySynthesizeAttribute(
WellKnownMember.System_Runtime_CompilerServices_CompilationRelaxationsAttribute__ctorInt32,
ImmutableArray.Create(typedConstantNoStringInterning)))
End If
End If
Dim emitRuntimeCompatibilityAttribute As Boolean = Not isBuildingNetModule AndAlso Not Me.Modules.Any(Function(m) m.HasAssemblyRuntimeCompatibilityAttribute)
If emitRuntimeCompatibilityAttribute Then
' Synthesize attribute: <RuntimeCompatibilityAttribute(WrapNonExceptionThrows = true)>
' NOTE: Native compiler skips synthesizing these attributes if the respective well-known attribute types aren't available, we do the same.
Dim runtimeCompatibilityAttributeType = DeclaringCompilation.GetWellKnownType(WellKnownType.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute)
If TryCast(runtimeCompatibilityAttributeType, MissingMetadataTypeSymbol) Is Nothing Then
Dim boolType = Me.DeclaringCompilation.GetSpecialType(SpecialType.System_Boolean)
Debug.Assert(boolType.GetUseSiteInfo().DiagnosticInfo Is Nothing, "Use site errors should have been checked ahead of time (type bool).")
Dim typedConstantTrue = New TypedConstant(boolType, TypedConstantKind.Primitive, True)
AddSynthesizedAttribute(attributes, DeclaringCompilation.TrySynthesizeAttribute(
WellKnownMember.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute__ctor,
ImmutableArray(Of TypedConstant).Empty,
ImmutableArray.Create(New KeyValuePair(Of WellKnownMember, TypedConstant)(
WellKnownMember.System_Runtime_CompilerServices_RuntimeCompatibilityAttribute__WrapNonExceptionThrows, typedConstantTrue))))
End If
End If
' Synthesize DebuggableAttribute only if all the following requirements are met:
' (a) We are not building a netmodule.
' (b) We are emitting debug information (full or pdbonly).
' (c) There is no applied DebuggableAttribute assembly attribute in source.
' (d) There is no applied DebuggableAttribute module attribute in source (NOTE: Native C# compiler and Roslyn C# compiler doesn't check this).
If Not isBuildingNetModule AndAlso Not Me.HasAssemblyOrModuleDebuggableAttribute Then
' Synthesize attribute: <DebuggableAttribute(DebuggableAttribute.DebuggingMode.<Value>)>
Dim int32Type = Me.DeclaringCompilation.GetSpecialType(SpecialType.System_Int32)
If int32Type.GetUseSiteInfo().DiagnosticInfo Is Nothing Then
Dim debuggingMode = DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints
' Since .NET 2.0 the combinations of None, Default And DisableOptimizations have the following effect
'
' None JIT optimizations enabled
' Default JIT optimizations enabled
' DisableOptimizations JIT optimizations enabled
' Default | DisableOptimizations JIT optimizations disabled
If options.OptimizationLevel = OptimizationLevel.Debug Then
debuggingMode = debuggingMode Or DebuggableAttribute.DebuggingModes.Default Or
DebuggableAttribute.DebuggingModes.DisableOptimizations
End If
If options.EnableEditAndContinue Then
debuggingMode = debuggingMode Or DebuggableAttribute.DebuggingModes.EnableEditAndContinue
End If
Dim typedConstantDebugMode = New TypedConstant(int32Type, TypedConstantKind.Enum, CInt(debuggingMode))
AddSynthesizedAttribute(attributes, DeclaringCompilation.TrySynthesizeAttribute(
WellKnownMember.System_Diagnostics_DebuggableAttribute__ctorDebuggingModes,
ImmutableArray.Create(typedConstantDebugMode)))
End If
End If
If _compilation.Options.OutputKind = OutputKind.NetModule Then
' If the attribute is applied in source, do not add synthetic one.
' If its value is different from the supplied through options, an error should have been reported by now.
If Not String.IsNullOrEmpty(_compilation.Options.CryptoKeyContainer) AndAlso
AssemblyKeyContainerAttributeSetting Is CommonAssemblyWellKnownAttributeData.StringMissingValue Then
Dim stringType = _compilation.GetSpecialType(SpecialType.System_String)
Debug.Assert(stringType.GetUseSiteInfo.DiagnosticInfo Is Nothing, "Use site errors should have been checked ahead of time (type string).")
Dim typedConstant = New TypedConstant(stringType, TypedConstantKind.Primitive, _compilation.Options.CryptoKeyContainer)
AddSynthesizedAttribute(attributes, _compilation.TrySynthesizeAttribute(WellKnownMember.System_Reflection_AssemblyKeyNameAttribute__ctor, ImmutableArray.Create(typedConstant)))
End If
If Not String.IsNullOrEmpty(_compilation.Options.CryptoKeyFile) AndAlso
AssemblyKeyFileAttributeSetting Is CommonAssemblyWellKnownAttributeData.StringMissingValue Then
Dim stringType = _compilation.GetSpecialType(SpecialType.System_String)
Debug.Assert(stringType.GetUseSiteInfo.DiagnosticInfo Is Nothing, "Use site errors should have been checked ahead of time (type string).")
Dim typedConstant = New TypedConstant(stringType, TypedConstantKind.Primitive, _compilation.Options.CryptoKeyFile)
AddSynthesizedAttribute(attributes, _compilation.TrySynthesizeAttribute(WellKnownMember.System_Reflection_AssemblyKeyFileAttribute__ctor, ImmutableArray.Create(typedConstant)))
End If
End If
End Sub
Friend Overrides ReadOnly Property PublicKey As ImmutableArray(Of Byte)
Get
Return StrongNameKeys.PublicKey
End Get
End Property
Friend Overrides Function AreInternalsVisibleToThisAssembly(potentialGiverOfAccess As AssemblySymbol) As Boolean
' Ensure that optimistic IVT access is only granted to requests that originated on the thread
' that is trying to compute the assembly identity. This gives us deterministic behavior when
' two threads are checking IVT access but only one of them is in the process of computing identity.
'as an optimization confirm that the identity has not yet been computed to avoid testing TLS
If _lazyStrongNameKeys Is Nothing Then
Dim assemblyWhoseKeysAreBeingComputed = s_AssemblyForWhichCurrentThreadIsComputingKeys
If assemblyWhoseKeysAreBeingComputed IsNot Nothing Then
Debug.Assert(assemblyWhoseKeysAreBeingComputed Is Me)
If Not potentialGiverOfAccess.GetInternalsVisibleToPublicKeys(Me.Name).IsEmpty() Then
If _optimisticallyGrantedInternalsAccess Is Nothing Then
Interlocked.CompareExchange(_optimisticallyGrantedInternalsAccess, New ConcurrentDictionary(Of AssemblySymbol, Boolean), Nothing)
End If
_optimisticallyGrantedInternalsAccess.TryAdd(potentialGiverOfAccess, True)
Return True
Else
Return False
End If
End If
End If
Dim conclusion As IVTConclusion = MakeFinalIVTDetermination(potentialGiverOfAccess)
Return conclusion = IVTConclusion.Match
' Note that C#, for error recovery, includes OrElse conclusion = IVTConclusion.OneSignedOneNot
End Function
Friend ReadOnly Property StrongNameKeys As StrongNameKeys
Get
If _lazyStrongNameKeys Is Nothing Then
Try
Debug.Assert(s_AssemblyForWhichCurrentThreadIsComputingKeys Is Nothing)
s_AssemblyForWhichCurrentThreadIsComputingKeys = Me
ComputeAndSetStrongNameKeys()
Finally
s_AssemblyForWhichCurrentThreadIsComputingKeys = Nothing
End Try
End If
Return _lazyStrongNameKeys
End Get
End Property
Private Sub ComputeAndSetStrongNameKeys()
' TODO
' In order to allow users to escape problems that we create with our provisional granting of IVT access,
' consider not binding the attributes if the command line options were specified, then later bind them
' and report warnings if both were used.
' make sure keycontainer and keyfile attribute contents fields will be set
EnsureAttributesAreBound()
' Creating strong names is a potentially expensive operation, so we will check
' if keys could have been created and published already.
If _lazyStrongNameKeys IsNot Nothing Then
Return
End If
Dim keys As StrongNameKeys
Dim keyFile As String = _compilation.Options.CryptoKeyFile
' Public sign requires a keyfile
If DeclaringCompilation.Options.PublicSign Then
If Not String.IsNullOrEmpty(keyFile) AndAlso Not PathUtilities.IsAbsolute(keyFile) Then
' If keyFile has a relative path then there should be a diagnostic
' about it
Debug.Assert(Not DeclaringCompilation.Options.Errors.IsEmpty)
keys = StrongNameKeys.None
Else
keys = StrongNameKeys.Create(keyFile, MessageProvider.Instance)
End If
' Public signing doesn't require a strong name provider to be used.
Interlocked.CompareExchange(_lazyStrongNameKeys, keys, Nothing)
Return
End If
' when both attributes and command-line options specified, cmd line wins.
If String.IsNullOrEmpty(keyFile) Then
keyFile = Me.AssemblyKeyFileAttributeSetting
If keyFile Is CommonAssemblyWellKnownAttributeData.StringMissingValue Then
keyFile = Nothing
End If
End If
Dim keyContainer As String = _compilation.Options.CryptoKeyContainer
If String.IsNullOrEmpty(keyContainer) Then
keyContainer = Me.AssemblyKeyContainerAttributeSetting
If keyContainer Is CommonAssemblyWellKnownAttributeData.StringMissingValue Then
keyContainer = Nothing
End If
End If
Dim hasCounterSignature = Not String.IsNullOrEmpty(SignatureKey)
keys = StrongNameKeys.Create(DeclaringCompilation.Options.StrongNameProvider, keyFile, keyContainer, hasCounterSignature, MessageProvider.Instance)
Interlocked.CompareExchange(_lazyStrongNameKeys, keys, Nothing)
End Sub
Private Function ComputeIdentity() As AssemblyIdentity
EnsureAttributesAreBound()
Return New AssemblyIdentity(_assemblySimpleName,
VersionHelper.GenerateVersionFromPatternAndCurrentTime(_compilation.Options.CurrentLocalTime, AssemblyVersionAttributeSetting),
Me.AssemblyCultureAttributeSetting,
StrongNameKeys.PublicKey,
hasPublicKey:=Not StrongNameKeys.PublicKey.IsDefault,
isRetargetable:=(AssemblyFlags And AssemblyFlags.Retargetable) = AssemblyFlags.Retargetable)
End Function
Friend ReadOnly Property IsVbRuntime As Boolean
Get
If Me._lazyIsVbRuntime = ThreeState.Unknown Then
Me._lazyIsVbRuntime = CheckForRuntime().ToThreeState
End If
Return Me._lazyIsVbRuntime = ThreeState.True
End Get
End Property
Private Function CheckForRuntime() As Boolean
Dim stdmodule = Me.DeclaringCompilation.GetWellKnownType(WellKnownType.Microsoft_VisualBasic_CompilerServices_StandardModuleAttribute)
Return Not stdmodule.IsErrorType AndAlso
Not stdmodule.IsEmbedded AndAlso
stdmodule.ContainingAssembly Is Me
End Function
Friend Overrides Function TryLookupForwardedMetadataTypeWithCycleDetection(ByRef emittedName As MetadataTypeName, visitedAssemblies As ConsList(Of AssemblySymbol), ignoreCase As Boolean) As NamedTypeSymbol
If Not _compilation.Options.OutputKind.IsNetModule() Then
' See if any of added modules forward the type.
Dim matchedName As String = Nothing
' Similar to attributes, type forwarders from the second added module should override type forwarders from the first added module, etc.
For i As Integer = _modules.Length - 1 To 1 Step -1
Dim peModuleSymbol = DirectCast(_modules(i), PEModuleSymbol)
Dim forwardedToAssemblies = peModuleSymbol.GetAssembliesForForwardedType(emittedName, ignoreCase, matchedName)
If forwardedToAssemblies.FirstSymbol IsNot Nothing Then
If forwardedToAssemblies.SecondSymbol IsNot Nothing Then
Return CreateMultipleForwardingErrorTypeSymbol(emittedName, peModuleSymbol, forwardedToAssemblies.FirstSymbol, forwardedToAssemblies.SecondSymbol)
End If
' Don't bother to check the forwarded-to assembly if we've already seen it.
If visitedAssemblies IsNot Nothing AndAlso visitedAssemblies.Contains(forwardedToAssemblies.FirstSymbol) Then
Return CreateCycleInTypeForwarderErrorTypeSymbol(emittedName)
Else
visitedAssemblies = New ConsList(Of AssemblySymbol)(Me, If(visitedAssemblies, ConsList(Of AssemblySymbol).Empty))
If ignoreCase AndAlso Not String.Equals(emittedName.FullName, matchedName, StringComparison.Ordinal) Then
emittedName = MetadataTypeName.FromFullName(matchedName, emittedName.UseCLSCompliantNameArityEncoding, emittedName.ForcedArity)
End If
Return forwardedToAssemblies.FirstSymbol.LookupDeclaredOrForwardedTopLevelMetadataType(emittedName, visitedAssemblies)
End If
End If
Next
End If
Return Nothing
End Function
Public Overrides Function GetMetadata() As AssemblyMetadata
Return Nothing
End Function
Private ReadOnly Property ISourceAssemblySymbol_Compilation As Compilation Implements ISourceAssemblySymbol.Compilation
Get
Return _compilation
End Get
End Property
Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
Get
' <assembly: Experimental> may have been specified in the assembly or one of the modules
Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me._lazySourceAttributesBag
If attributesBag IsNot Nothing AndAlso attributesBag.IsDecodedWellKnownAttributeDataComputed Then
Dim experimentalData = DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonAssemblyWellKnownAttributeData)?.ExperimentalAttributeData
If experimentalData IsNot Nothing Then
Return experimentalData
End If
End If
attributesBag = Me._lazyNetModuleAttributesBag
If attributesBag IsNot Nothing AndAlso attributesBag.IsDecodedWellKnownAttributeDataComputed Then
Return DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonAssemblyWellKnownAttributeData)?.ExperimentalAttributeData
End If
If GetAttributeDeclarations().IsEmpty Then
Return Nothing
End If
Return ObsoleteAttributeData.Uninitialized
End Get
End Property
End Class
End Namespace
|