File: Symbols\Source\SourceModuleSymbol.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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.Runtime.CompilerServices
Imports System.Runtime.InteropServices
Imports System.Threading
Imports Microsoft.CodeAnalysis.ErrorReporting
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports ReferenceEqualityComparer = Roslyn.Utilities.ReferenceEqualityComparer
 
Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
 
    ''' <summary>
    ''' Represents the primary module of an assembly being built by compiler.
    ''' </summary>
    ''' <remarks></remarks>
    Partial Friend NotInheritable Class SourceModuleSymbol
        Inherits NonMissingModuleSymbol
        Implements IAttributeTargetSymbol
 
        ''' <summary>
        ''' Owning assembly.
        ''' </summary>
        ''' <remarks></remarks>
        Private ReadOnly _assemblySymbol As SourceAssemblySymbol
 
        ' The declaration table for all the source files.
        Private ReadOnly _declarationTable As DeclarationTable
 
        ' Options that control compilation
        Private ReadOnly _options As VisualBasicCompilationOptions
 
        ' Module attributes
        Private _lazyCustomAttributesBag As CustomAttributesBag(Of VisualBasicAttributeData)
 
        Private _lazyContainsExtensionMethods As Byte = ThreeState.Unknown
 
        Private _lazyAssembliesToEmbedTypesFrom As ImmutableArray(Of AssemblySymbol)
 
        Private _lazyContainsExplicitDefinitionOfNoPiaLocalTypes As ThreeState = ThreeState.Unknown
 
        Private _locations As ImmutableArray(Of Location)
 
        ''' <summary>
        ''' Holds diagnostics not related to source code
        ''' in any particular source file
        ''' </summary>
        Private ReadOnly _diagnosticBagDeclare As New DiagnosticBag()
 
        Private _hasBadAttributes As Boolean
 
        Friend ReadOnly Property Options As VisualBasicCompilationOptions
            Get
                Return _options
            End Get
        End Property
 
        ' A concurrent dictionary that hold SourceFile objects for each source file, created
        ' on demand. Each source file object holds information about the source that is specific to a particular
        ' compilation and doesn't survive edits in any way (unlike the declaration table, which is incrementally
        ' updated between compilations as edits occur.)
        Private ReadOnly _sourceFileMap As New ConcurrentDictionary(Of SyntaxTree, SourceFile)
 
        ' lazily populated with the global namespace symbol
        Private _lazyGlobalNamespace As SourceNamespaceSymbol
 
        ' lazily populated with the bound imports
        Private _lazyBoundImports As BoundImports
        Private _lazyBoundImportsAdditionalDiagnostics As StrongBox(Of ReadOnlyBindingDiagnostic(Of AssemblySymbol))
 
        ' lazily populate with quick attribute checker that is initialized with the imports.
        Private _lazyQuickAttributeChecker As QuickAttributeChecker
 
        ' lazily populate with diagnostics validating linked assemblies.
        Private _lazyLinkedAssemblyDiagnostics As ImmutableArray(Of Diagnostic)
 
        Private _lazyTypesWithDefaultInstanceAlias As Dictionary(Of NamedTypeSymbol, SynthesizedMyGroupCollectionPropertySymbol)
        Private Shared ReadOnly s_noTypesWithDefaultInstanceAlias As New Dictionary(Of NamedTypeSymbol, SynthesizedMyGroupCollectionPropertySymbol)()
 
        Friend Sub New(assemblySymbol As SourceAssemblySymbol,
                       declarationTable As DeclarationTable,
                       options As VisualBasicCompilationOptions,
                       nameAndExtension As String)
            Debug.Assert(assemblySymbol IsNot Nothing)
 
            _assemblySymbol = assemblySymbol
            _declarationTable = declarationTable
            _options = options
            _nameAndExtension = nameAndExtension
        End Sub
 
        Friend Overrides ReadOnly Property Ordinal As Integer
            Get
                Return 0
            End Get
        End Property
 
        Friend Overrides ReadOnly Property Machine As System.Reflection.PortableExecutable.Machine
            Get
                Select Case DeclaringCompilation.Options.Platform
                    Case Platform.Arm64
                        Return System.Reflection.PortableExecutable.Machine.Arm64
                    Case Platform.Arm
                        Return System.Reflection.PortableExecutable.Machine.ArmThumb2
                    Case Platform.X64
                        Return System.Reflection.PortableExecutable.Machine.Amd64
                    Case Platform.Itanium
                        Return System.Reflection.PortableExecutable.Machine.IA64
                    Case Else
                        Return System.Reflection.PortableExecutable.Machine.I386
                End Select
            End Get
        End Property
 
        Friend Overrides ReadOnly Property Bit32Required As Boolean
            Get
                Return DeclaringCompilation.Options.Platform = Platform.X86
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingSymbol As Symbol
            Get
                Return _assemblySymbol
            End Get
        End Property
 
        Public Overrides ReadOnly Property ContainingAssembly As AssemblySymbol
            Get
                Return _assemblySymbol
            End Get
        End Property
 
        Public ReadOnly Property ContainingSourceAssembly As SourceAssemblySymbol
            Get
                Return _assemblySymbol
            End Get
        End Property
 
        ''' <summary>
        ''' This override is essential - it's a base case of the recursive definition.
        ''' </summary>
        Friend Overrides ReadOnly Property DeclaringCompilation As VisualBasicCompilation
            Get
                Return _assemblySymbol.DeclaringCompilation
            End Get
        End Property
 
        Private ReadOnly _nameAndExtension As String
 
        Public Overrides ReadOnly Property Name As String
            Get
                Return _nameAndExtension
            End Get
        End Property
 
        ''' <summary>
        ''' Get the SourceFile object associated with a root declaration.
        ''' Returns Nothing if the tree doesn't belong to the compilation.
        ''' </summary>
        Friend Function TryGetSourceFile(tree As SyntaxTree) As SourceFile
            Debug.Assert(tree IsNot Nothing)
 
            Dim srcFile As SourceFile = Nothing
            If _sourceFileMap.TryGetValue(tree, srcFile) Then
                Return srcFile
 
            ElseIf _assemblySymbol.DeclaringCompilation.AllSyntaxTrees.Contains(tree) Then
                srcFile = New SourceFile(Me, tree)
                Return _sourceFileMap.GetOrAdd(tree, srcFile)
 
            Else
                Return Nothing
            End If
        End Function
 
        ' Gets the global namespace for that merges the global namespace across all source files.
        Public Overrides ReadOnly Property GlobalNamespace As NamespaceSymbol
            Get
                If _lazyGlobalNamespace Is Nothing Then
                    Dim globalNS = New SourceNamespaceSymbol(DeclaringCompilation.MergedRootDeclaration, Nothing, Me)
                    Interlocked.CompareExchange(_lazyGlobalNamespace, globalNS, Nothing)
                End If
 
                Return _lazyGlobalNamespace
            End Get
        End Property
 
        ' Get the "root" or default namespace that all source types are declared inside. This may be the global namespace
        ' or may be another namespace. This is a non-merged, source only namespace.
        Friend ReadOnly Property RootNamespace As NamespaceSymbol
            Get
                Dim result = Me.GlobalNamespace.LookupNestedNamespace(Me.Options.GetRootNamespaceParts())
                Debug.Assert(result IsNot Nothing, "Something is deeply wrong with the declaration table or the symbol table")
                Return result
            End Get
        End Property
 
        Public Overrides ReadOnly Property Locations As ImmutableArray(Of Location)
            Get
                If _locations.IsDefault Then
                    ImmutableInterlocked.InterlockedInitialize(
                        _locations,
                        DeclaringCompilation.MergedRootDeclaration.Declarations.SelectAsArray(Function(d) d.Location))
                End If
 
                Return _locations
            End Get
        End Property
 
        Friend ReadOnly Property SyntaxTrees As IEnumerable(Of SyntaxTree)
            Get
                Return _assemblySymbol.DeclaringCompilation.AllSyntaxTrees
            End Get
        End Property
 
        Public ReadOnly Property DefaultAttributeLocation As AttributeLocation Implements IAttributeTargetSymbol.DefaultAttributeLocation
            Get
                Return AttributeLocation.Module
            End Get
        End Property
 
        ''' <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="GetAttributesBag"/> method.
        ''' </remarks>
        Public Overrides Function GetAttributes() As ImmutableArray(Of VisualBasicAttributeData)
            Return Me.GetAttributesBag().Attributes
        End Function
 
        Private Function GetAttributesBag() As CustomAttributesBag(Of VisualBasicAttributeData)
            If _lazyCustomAttributesBag Is Nothing OrElse Not _lazyCustomAttributesBag.IsSealed Then
                Dim mergedAttributes = DirectCast(Me.ContainingAssembly, SourceAssemblySymbol).GetAttributeDeclarations()
                LoadAndValidateAttributes(OneOrMany.Create(mergedAttributes), _lazyCustomAttributesBag)
            End If
            Return _lazyCustomAttributesBag
        End Function
 
        Friend Function GetDecodedWellKnownAttributeData() As CommonModuleWellKnownAttributeData
            Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me._lazyCustomAttributesBag
            If attributesBag Is Nothing OrElse Not attributesBag.IsDecodedWellKnownAttributeDataComputed Then
                attributesBag = Me.GetAttributesBag()
            End If
 
            Return DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonModuleWellKnownAttributeData)
        End Function
 
        ' Get a quick attribute checker that can be used for quick attributes checks, initialized with project-level
        ' aliases.
        Public ReadOnly Property QuickAttributeChecker As QuickAttributeChecker
            Get
                If _lazyQuickAttributeChecker Is Nothing Then
                    Interlocked.CompareExchange(_lazyQuickAttributeChecker, CreateQuickAttributeChecker(), Nothing)
                End If
 
                Return _lazyQuickAttributeChecker
            End Get
        End Property
 
        Friend ReadOnly Property AnyReferencedAssembliesAreLinked As Boolean
            Get
                Return GetAssembliesToEmbedTypesFrom().Length > 0
            End Get
        End Property
 
        Friend Function MightContainNoPiaLocalTypes() As Boolean
            Return AnyReferencedAssembliesAreLinked OrElse
                ContainsExplicitDefinitionOfNoPiaLocalTypes
        End Function
 
        Friend Function GetAssembliesToEmbedTypesFrom() As ImmutableArray(Of AssemblySymbol)
            If _lazyAssembliesToEmbedTypesFrom.IsDefault Then
                AssertReferencesInitialized()
                Dim assemblies = ArrayBuilder(Of AssemblySymbol).GetInstance()
 
                For Each assembly In GetReferencedAssemblySymbols()
                    If assembly.IsLinked Then
                        assemblies.Add(assembly)
                    End If
                Next
 
                ImmutableInterlocked.InterlockedInitialize(_lazyAssembliesToEmbedTypesFrom, assemblies.ToImmutableAndFree())
            End If
 
            Debug.Assert(Not _lazyAssembliesToEmbedTypesFrom.IsDefault)
            Return _lazyAssembliesToEmbedTypesFrom
        End Function
 
        Friend ReadOnly Property ContainsExplicitDefinitionOfNoPiaLocalTypes As Boolean
            Get
                If _lazyContainsExplicitDefinitionOfNoPiaLocalTypes = ThreeState.Unknown Then
                    _lazyContainsExplicitDefinitionOfNoPiaLocalTypes = NamespaceContainsExplicitDefinitionOfNoPiaLocalTypes(GlobalNamespace).ToThreeState()
                End If
 
                Debug.Assert(_lazyContainsExplicitDefinitionOfNoPiaLocalTypes <> ThreeState.Unknown)
                Return _lazyContainsExplicitDefinitionOfNoPiaLocalTypes = ThreeState.True
            End Get
        End Property
 
        Private Shared Function NamespaceContainsExplicitDefinitionOfNoPiaLocalTypes(ns As NamespaceSymbol) As Boolean
            For Each s In ns.GetMembersUnordered()
                Select Case s.Kind
                    Case SymbolKind.Namespace
                        If NamespaceContainsExplicitDefinitionOfNoPiaLocalTypes(DirectCast(s, NamespaceSymbol)) Then
                            Return True
                        End If
                    Case SymbolKind.NamedType
                        If DirectCast(s, NamedTypeSymbol).IsExplicitDefinitionOfNoPiaLocalType Then
                            Return True
                        End If
                End Select
            Next
            Return False
        End Function
 
        Private Function CreateQuickAttributeChecker() As QuickAttributeChecker
            ' First, initialize for the predefined attributes.
            Dim checker As New QuickAttributeChecker()
            checker.AddName(AttributeDescription.CaseInsensitiveExtensionAttribute.Name, QuickAttributes.Extension)
            checker.AddName(AttributeDescription.ObsoleteAttribute.Name, QuickAttributes.Obsolete)
            checker.AddName(AttributeDescription.DeprecatedAttribute.Name, QuickAttributes.Obsolete)
            checker.AddName(AttributeDescription.ExperimentalAttribute.Name, QuickAttributes.Obsolete)
            checker.AddName(AttributeDescription.MyGroupCollectionAttribute.Name, QuickAttributes.MyGroupCollection)
            checker.AddName(AttributeDescription.TypeIdentifierAttribute.Name, QuickAttributes.TypeIdentifier)
 
            ' Now process alias imports
            For Each globalImport In Options.GlobalImports
                If globalImport.Clause.Kind = SyntaxKind.SimpleImportsClause Then
                    Dim simpleImportsClause = DirectCast(globalImport.Clause, SimpleImportsClauseSyntax)
 
                    If simpleImportsClause.Alias IsNot Nothing Then
                        checker.AddAlias(simpleImportsClause)
                    End If
                End If
            Next
 
            checker.Seal()
            Return checker
        End Function
 
        ' Make sure the project level imports are bound.
        Private Sub EnsureImportsAreBound(cancellationToken As CancellationToken)
            If _lazyBoundImports Is Nothing Then
                If Interlocked.CompareExchange(_lazyBoundImports, BindImports(cancellationToken), Nothing) Is Nothing Then
                    EnsureImportsAreValidated()
                End If
            End If
        End Sub
 
        Private Sub EnsureImportsAreValidated()
            If _lazyBoundImportsAdditionalDiagnostics Is Nothing Then
                Dim diagnosticBag = BindingDiagnosticBag.GetInstance()
                ValidateImports(_lazyBoundImports.MemberImports, _lazyBoundImports.MemberImportsInfo, _lazyBoundImports.AliasImports, _lazyBoundImports.AliasImportsInfo, diagnosticBag)
                Interlocked.CompareExchange(_lazyBoundImportsAdditionalDiagnostics, New StrongBox(Of ReadOnlyBindingDiagnostic(Of AssemblySymbol))(diagnosticBag.ToReadOnlyAndFree()), Nothing)
            End If
        End Sub
 
        ' Bind the project level imports.
        Private Function BindImports(cancellationToken As CancellationToken) As BoundImports
            Dim diagBag = BindingDiagnosticBag.GetInstance()
 
            Dim membersMap = New HashSet(Of NamespaceOrTypeSymbol)
            Dim aliasesMap = New Dictionary(Of String, AliasAndImportsClausePosition)(IdentifierComparison.Comparer)
            Dim membersBuilder = ArrayBuilder(Of NamespaceOrTypeAndImportsClausePosition).GetInstance()
            Dim membersInfoBuilder = ArrayBuilder(Of GlobalImportInfo).GetInstance()
            Dim aliasesBuilder = ArrayBuilder(Of AliasAndImportsClausePosition).GetInstance()
            Dim aliasesInfoBuilder = ArrayBuilder(Of GlobalImportInfo).GetInstance()
            Dim xmlNamespaces = New Dictionary(Of String, XmlNamespaceAndImportsClausePosition)
            Dim diagBagForThisImport = BindingDiagnosticBag.GetInstance()
 
            Try
                For Each globalImport In Options.GlobalImports
                    cancellationToken.ThrowIfCancellationRequested()
 
                    diagBagForThisImport.Clear()
                    Dim data = New ModuleImportData(globalImport, membersMap, aliasesMap, membersBuilder, membersInfoBuilder, aliasesBuilder, aliasesInfoBuilder, xmlNamespaces, diagBagForThisImport.DependenciesBag)
                    Dim binder As Binder = BinderBuilder.CreateBinderForProjectImports(Me, VisualBasicSyntaxTree.Dummy)
                    binder.BindImportClause(globalImport.Clause, data, diagBagForThisImport.DiagnosticBag)
 
                    ' Map diagnostics to new ones.
                    ' Note, it is safe to resolve diagnostics here because we suppress obsolete diagnostics
                    ' in ProjectImportsBinder.
                    For Each d As Diagnostic In diagBagForThisImport.DiagnosticBag.AsEnumerable()
                        ' NOTE: Dev10 doesn't report 'ERR_DuplicateImport1' for project level imports.
                        If d.Code <> ERRID.ERR_DuplicateImport1 Then
                            diagBag.Add(globalImport.MapDiagnostic(d))
                        End If
                    Next
 
                    diagBag.AddDependencies(diagBagForThisImport)
                Next
 
                Return New BoundImports(
                    membersBuilder.ToImmutable(),
                    membersInfoBuilder.ToImmutable(),
                    aliasesMap,
                    aliasesBuilder.ToImmutable(),
                    aliasesInfoBuilder.ToImmutable(),
                    If(xmlNamespaces.Count > 0, xmlNamespaces, Nothing),
                    diagBag.ToReadOnly())
            Finally
                membersBuilder.Free()
                membersInfoBuilder.Free()
                aliasesBuilder.Free()
                aliasesInfoBuilder.Free()
                diagBagForThisImport.Free()
                diagBag.Free()
            End Try
        End Function
 
        ''' <summary>
        ''' Data for Binder.BindImportClause that maintains flat lists of members, aliases,
        ''' and corresponding syntax references in addition to the dictionaries needed by
        ''' BindImportClause. The syntax references, instances of GlobalImportInfo, are used
        ''' later, when validating constraints, to generate Locations for constraint errors.
        ''' </summary>
        Private NotInheritable Class ModuleImportData
            Inherits ImportData
 
            Private ReadOnly _globalImport As GlobalImport
            Private ReadOnly _membersBuilder As ArrayBuilder(Of NamespaceOrTypeAndImportsClausePosition)
            Private ReadOnly _membersInfoBuilder As ArrayBuilder(Of GlobalImportInfo)
            Private ReadOnly _aliasesBuilder As ArrayBuilder(Of AliasAndImportsClausePosition)
            Private ReadOnly _aliasesInfoBuilder As ArrayBuilder(Of GlobalImportInfo)
            Private ReadOnly _dependencies As ICollection(Of AssemblySymbol)
 
            Public Sub New(globalImport As GlobalImport,
                           membersMap As HashSet(Of NamespaceOrTypeSymbol),
                           aliasesMap As Dictionary(Of String, AliasAndImportsClausePosition),
                           membersBuilder As ArrayBuilder(Of NamespaceOrTypeAndImportsClausePosition),
                           membersInfoBuilder As ArrayBuilder(Of GlobalImportInfo),
                           aliasesBuilder As ArrayBuilder(Of AliasAndImportsClausePosition),
                           aliasesInfoBuilder As ArrayBuilder(Of GlobalImportInfo),
                           xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition),
                           dependencies As ICollection(Of AssemblySymbol))
                MyBase.New(membersMap, aliasesMap, xmlNamespaces)
                _globalImport = globalImport
                _membersBuilder = membersBuilder
                _membersInfoBuilder = membersInfoBuilder
                _aliasesBuilder = aliasesBuilder
                _aliasesInfoBuilder = aliasesInfoBuilder
                _dependencies = dependencies
            End Sub
 
            Public Overrides Sub AddMember(
                    syntaxRef As SyntaxReference,
                    member As NamespaceOrTypeSymbol,
                    importsClausePosition As Integer,
                    dependencies As IReadOnlyCollection(Of AssemblySymbol),
                    isPrjectImportDeclaration As Boolean)
                ' Do not expose any locations for project level imports.  This matches the effective logic
                ' we have for aliases, which are given NoLocation.Singleton (which never translates to a
                ' DeclaringSyntaxReference).
                Dim pair = New NamespaceOrTypeAndImportsClausePosition(
                    member, importsClausePosition, If(isPrjectImportDeclaration, Nothing, syntaxRef), ImmutableArray(Of AssemblySymbol).Empty)
                Members.Add(member)
                _membersBuilder.Add(pair)
                _membersInfoBuilder.Add(New GlobalImportInfo(_globalImport, syntaxRef))
                AddDependencies(dependencies)
            End Sub
 
            Private Sub AddDependencies(dependencies As IReadOnlyCollection(Of AssemblySymbol))
                For Each dependency In dependencies
                    _dependencies.Add(dependency)
                Next
            End Sub
 
            Public Overrides Sub AddAlias(syntaxRef As SyntaxReference, name As String, [alias] As AliasSymbol, importsClausePosition As Integer, dependencies As IReadOnlyCollection(Of AssemblySymbol))
                Dim pair = New AliasAndImportsClausePosition([alias], importsClausePosition, syntaxRef, ImmutableArray(Of AssemblySymbol).Empty)
                Aliases.Add(name, pair)
                _aliasesBuilder.Add(pair)
                _aliasesInfoBuilder.Add(New GlobalImportInfo(_globalImport, syntaxRef))
                AddDependencies(dependencies)
            End Sub
        End Class
 
        ''' <summary>
        ''' Perform any validation of import statements that must occur
        ''' after the import statements have been added to the module.
        ''' </summary>
        Private Sub ValidateImports(
                                         memberImports As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition),
                                         memberImportsInfo As ImmutableArray(Of GlobalImportInfo),
                                         aliasImports As ImmutableArray(Of AliasAndImportsClausePosition),
                                         aliasImportsInfo As ImmutableArray(Of GlobalImportInfo),
                                         diagnostics As BindingDiagnosticBag)
            ' TODO: Dev10 reports error on specific type parts rather than the import
            ' (reporting error on Object rather than C in C = A(Of Object) for instance).
 
            If Not memberImports.IsDefault Then
                For i = 0 To memberImports.Length - 1
                    Dim namespaceOrType As NamespaceOrTypeSymbol = memberImports(i).NamespaceOrType
                    Dim type = TryCast(namespaceOrType, TypeSymbol)
                    If type IsNot Nothing Then
                        ValidateImport(type, memberImportsInfo(i), diagnostics)
                    Else
                        diagnostics.AddAssembliesUsedByNamespaceReference(DirectCast(namespaceOrType, NamespaceSymbol))
                    End If
                Next
            End If
 
            If Not aliasImports.IsDefault Then
                For i = 0 To aliasImports.Length - 1
                    Dim target As NamespaceOrTypeSymbol = aliasImports(i).Alias.Target
                    Dim type = TryCast(target, TypeSymbol)
                    If type IsNot Nothing Then
                        ValidateImport(type, aliasImportsInfo(i), diagnostics)
                    Else
                        diagnostics.AddAssembliesUsedByNamespaceReference(DirectCast(target, NamespaceSymbol))
                    End If
                Next
            End If
        End Sub
 
        ''' <summary>
        ''' Perform validation of an import statement that must occur
        ''' after the statement has been added to the module. Specifically,
        ''' constraints are checked for generic type references.
        ''' </summary>
        Private Sub ValidateImport(type As TypeSymbol, info As GlobalImportInfo, diagnostics As BindingDiagnosticBag)
            Dim diagnosticsBuilder = ArrayBuilder(Of TypeParameterDiagnosticInfo).GetInstance()
            Dim useSiteDiagnosticsBuilder As ArrayBuilder(Of TypeParameterDiagnosticInfo) = Nothing
            type.CheckAllConstraints(
                DeclaringCompilation.LanguageVersion,
                diagnosticsBuilder, useSiteDiagnosticsBuilder, template:=New CompoundUseSiteInfo(Of AssemblySymbol)(diagnostics, ContainingAssembly))
 
            If useSiteDiagnosticsBuilder IsNot Nothing Then
                diagnosticsBuilder.AddRange(useSiteDiagnosticsBuilder)
            End If
 
            For Each pair In diagnosticsBuilder
                If pair.UseSiteInfo.DiagnosticInfo IsNot Nothing Then
                    diagnostics.Add(info.Import.MapDiagnostic(New VBDiagnostic(pair.UseSiteInfo.DiagnosticInfo, info.SyntaxReference.GetLocation())))
                End If
 
                diagnostics.AddDependencies(pair.UseSiteInfo)
            Next
            diagnosticsBuilder.Free()
        End Sub
 
        ' Get the project-level member imports, or Nothing if none.
        Friend ReadOnly Property MemberImports As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition)
            Get
                EnsureImportsAreBound(CancellationToken.None)
                Return _lazyBoundImports.MemberImports
            End Get
        End Property
 
        Friend ReadOnly Property AliasImports As ImmutableArray(Of AliasAndImportsClausePosition)
            Get
                EnsureImportsAreBound(CancellationToken.None)
                Return _lazyBoundImports.AliasImports
            End Get
        End Property
 
        ' Get the project level alias imports, or Nothing if none.
        Friend ReadOnly Property AliasImportsMap As Dictionary(Of String, AliasAndImportsClausePosition)
            Get
                EnsureImportsAreBound(CancellationToken.None)
                Return _lazyBoundImports.AliasImportsMap
            End Get
        End Property
 
        ' Get the project level xmlns imports, or Nothing if none.
        Friend ReadOnly Property XmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition)
            Get
                EnsureImportsAreBound(CancellationToken.None)
                Return _lazyBoundImports.XmlNamespaces
            End Get
        End Property
 
        ''' <summary>
        ''' Get all the declaration errors in a single tree.
        ''' </summary>
        Friend Function GetDeclarationErrorsInTree(tree As SyntaxTree,
                                                   filterSpanWithinTree As TextSpan?,
                                                   locationFilter As Func(Of IEnumerable(Of Diagnostic), SyntaxTree, TextSpan?, IEnumerable(Of Diagnostic)),
                                                   cancellationToken As CancellationToken) As ImmutableArray(Of Diagnostic)
            Dim builder = ArrayBuilder(Of Diagnostic).GetInstance()
 
            ' Force source file to generate errors for Imports and the like.
            Dim sourceFile As SourceFile = TryGetSourceFile(tree)
            Debug.Assert(sourceFile IsNot Nothing)
 
            If filterSpanWithinTree.HasValue Then
                Dim diagnostics = sourceFile.GetDeclarationErrorsInSpan(filterSpanWithinTree.Value, cancellationToken)
                diagnostics = locationFilter(diagnostics, tree, filterSpanWithinTree)
                builder.AddRange(diagnostics)
            Else
                sourceFile.GenerateAllDeclarationErrors()
            End If
 
            ' Force bind module and assembly attributes
            Me.GetAttributes()
            Me.ContainingAssembly.GetAttributes()
 
            ' Force all types to generate errors.
            Dim tasks As ConcurrentStack(Of Task) = If(ContainingSourceAssembly.DeclaringCompilation.Options.ConcurrentBuild, New ConcurrentStack(Of Task)(), Nothing)
 
            ' Force all types that were declared in this tree to generate errors. We may also generate declaration
            ' errors for other parts of partials; that's OK and those errors will be retained, but won't be in the
            ' diagnostic bag for this particular file.
            VisitAllSourceTypesAndNamespaces(Sub(typeOrNamespace As NamespaceOrTypeSymbol)
                                                 If Not typeOrNamespace.IsDefinedInSourceTree(tree, filterSpanWithinTree) Then
                                                     Return
                                                 End If
 
                                                 If typeOrNamespace.IsNamespace Then
                                                     DirectCast(typeOrNamespace, SourceNamespaceSymbol).GenerateDeclarationErrorsInTree(tree, filterSpanWithinTree, cancellationToken)
                                                 Else
                                                     ' synthetic event delegates are not source types so use NamedTypeSymbol.
                                                     Dim sourceType = DirectCast(typeOrNamespace, NamedTypeSymbol)
                                                     sourceType.GenerateDeclarationErrors(cancellationToken)
                                                 End If
                                             End Sub,
                tasks, cancellationToken)
 
            If tasks IsNot Nothing Then
                Dim curTask As Task = Nothing
                While tasks.TryPop(curTask)
                    curTask.GetAwaiter().GetResult()
                End While
            End If
 
            ' Get all the errors that were generated.
            Dim declarationDiagnostics = sourceFile.DeclarationDiagnostics.AsEnumerable()
 
            ' Filter diagnostics outside the tree/span of interest.
            If locationFilter IsNot Nothing Then
                Debug.Assert(tree IsNot Nothing)
                declarationDiagnostics = locationFilter(declarationDiagnostics, tree, filterSpanWithinTree)
            End If
 
            For Each d As Diagnostic In declarationDiagnostics
                builder.Add(d)
            Next
 
            Return builder.ToImmutableAndFree()
        End Function
 
        ''' <summary>
        ''' Get all the declaration errors.
        ''' </summary>
        Friend Sub GetAllDeclarationErrors(diagnostics As BindingDiagnosticBag, cancellationToken As CancellationToken, ByRef hasExtensionMethods As Boolean)
            ' Bind project level imports
            EnsureImportsAreBound(cancellationToken)
            EnsureImportsAreValidated()
 
            ' Force all source files to generate errors for imports and the like.
            If ContainingSourceAssembly.DeclaringCompilation.Options.ConcurrentBuild Then
                Dim trees = ArrayBuilder(Of SyntaxTree).GetInstance()
                trees.AddRange(SyntaxTrees)
 
                RoslynParallel.For(
                    0,
                    trees.Count,
                    UICultureUtilities.WithCurrentUICulture(
                        Sub(i As Integer)
                            TryGetSourceFile(trees(i)).GenerateAllDeclarationErrors()
                        End Sub),
                    cancellationToken)
                trees.Free()
            Else
                For Each tree In SyntaxTrees
                    cancellationToken.ThrowIfCancellationRequested()
                    TryGetSourceFile(tree).GenerateAllDeclarationErrors()
                Next
            End If
 
            ' Force bind module and assembly attributes
            Dim unused = Me.GetAttributes()
            unused = Me.ContainingAssembly.GetAttributes()
 
            EnsureLinkedAssembliesAreValidated(cancellationToken)
 
            ' Force all types to generate errors.
            Dim tasks As ConcurrentStack(Of Task) = If(ContainingSourceAssembly.DeclaringCompilation.Options.ConcurrentBuild,
                                                       New ConcurrentStack(Of Task)(), Nothing)
 
            VisitAllSourceTypesAndNamespaces(Sub(typeOrNamespace As NamespaceOrTypeSymbol)
                                                 If typeOrNamespace.IsNamespace Then
                                                     DirectCast(typeOrNamespace, SourceNamespaceSymbol).GenerateDeclarationErrors(cancellationToken)
                                                 Else
                                                     ' synthetic event delegates are not source types so use NamedTypeSymbol.
                                                     Dim sourceType = DirectCast(typeOrNamespace, NamedTypeSymbol)
                                                     sourceType.GenerateDeclarationErrors(cancellationToken)
                                                 End If
                                             End Sub,
                tasks, cancellationToken)
 
            If tasks IsNot Nothing Then
                Dim curTask As Task = Nothing
                While tasks.TryPop(curTask)
                    curTask.GetAwaiter().GetResult()
                End While
            End If
 
            ' At this point we should have recorded presence of extension methods.
            If _lazyContainsExtensionMethods = ThreeState.Unknown Then
                _lazyContainsExtensionMethods = ThreeState.False
            End If
 
            hasExtensionMethods = _lazyContainsExtensionMethods = ThreeState.True
 
            ' Accumulate all the errors that were generated.
            diagnostics.AddRange(Me._diagnosticBagDeclare)
            diagnostics.AddRange(Me._lazyBoundImports.Diagnostics, allowMismatchInDependencyAccumulation:=True)
            diagnostics.AddRange(Me._lazyBoundImportsAdditionalDiagnostics.Value, allowMismatchInDependencyAccumulation:=True)
            diagnostics.AddRange(Me._lazyLinkedAssemblyDiagnostics)
 
            For Each tree In SyntaxTrees
                diagnostics.AddRange(TryGetSourceFile(tree).DeclarationDiagnostics)
            Next
        End Sub
 
        ' Visit all of the source types within this source module.
        Private Sub VisitAllSourceTypesAndNamespaces(visitor As Action(Of NamespaceOrTypeSymbol), tasks As ConcurrentStack(Of Task), cancellationToken As CancellationToken)
            VisitTypesAndNamespacesWithin(Me.GlobalNamespace, visitor, tasks, cancellationToken)
        End Sub
 
        ' Visit all source types and namespaces within this source namespace or type, inclusive of this source namespace or type
        Private Sub VisitTypesAndNamespacesWithin(ns As NamespaceOrTypeSymbol, visitor As Action(Of NamespaceOrTypeSymbol), tasks As ConcurrentStack(Of Task), cancellationToken As CancellationToken)
            Dim stack = ArrayBuilder(Of NamespaceOrTypeSymbol).GetInstance
            Try
                stack.Push(ns)
                While stack.Count > 0
                    cancellationToken.ThrowIfCancellationRequested()
                    Dim symbol = stack.Pop()
 
                    If tasks IsNot Nothing Then
                        Dim worker As Task = Task.Run(
                            UICultureUtilities.WithCurrentUICulture(
                                Sub()
                                    Try
                                        visitor(symbol)
                                    Catch e As Exception When FatalError.ReportAndPropagateUnlessCanceled(e)
                                        Throw ExceptionUtilities.Unreachable
                                    End Try
                                End Sub),
                            cancellationToken)
                        tasks.Push(worker)
                    Else
                        visitor(symbol)
                    End If
 
                    For Each child As Symbol In If(symbol.IsNamespace, symbol.GetMembers(), symbol.GetTypeMembers().Cast(Of Symbol))
                        stack.Push(DirectCast(child, NamespaceOrTypeSymbol))
                    Next
                End While
            Finally
                stack.Free()
            End Try
        End Sub
 
        Private Sub EnsureLinkedAssembliesAreValidated(cancellationToken As CancellationToken)
            If _lazyLinkedAssemblyDiagnostics.IsDefault Then
                Dim diagnostics = DiagnosticBag.GetInstance()
                ValidateLinkedAssemblies(diagnostics, cancellationToken)
                ImmutableInterlocked.InterlockedInitialize(_lazyLinkedAssemblyDiagnostics, diagnostics.ToReadOnlyAndFree)
            End If
        End Sub
 
        Private Sub ValidateLinkedAssemblies(diagnostics As DiagnosticBag, cancellationToken As CancellationToken)
            For Each assembly In GetReferencedAssemblySymbols()
                cancellationToken.ThrowIfCancellationRequested()
 
                If assembly.IsMissing OrElse Not assembly.IsLinked Then
                    Continue For
                End If
 
                If Not assembly.GetGuidString(Nothing) Then
                    diagnostics.Add(ERRID.ERR_PIAHasNoAssemblyGuid1,
                                    NoLocation.Singleton,
                                    assembly,
                                    AttributeDescription.GuidAttribute.FullName)
                End If
 
                If Not assembly.HasImportedFromTypeLibAttribute AndAlso Not assembly.HasPrimaryInteropAssemblyAttribute Then
                    diagnostics.Add(ERRID.ERR_PIAHasNoTypeLibAttribute1,
                                    NoLocation.Singleton,
                                    assembly,
                                    AttributeDescription.ImportedFromTypeLibAttribute.FullName,
                                    AttributeDescription.PrimaryInteropAssemblyAttribute.FullName)
                End If
            Next
        End Sub
 
        ' This lock is used in the implementation of AtomicStoreReferenceAndDiagnostics
        Private ReadOnly _diagnosticLock As New Object()
 
        ' Checks if the given diagnostic bag has all lazy obsolete diagnostics.
        Private Shared Function HasAllLazyDiagnostics(diagBag As DiagnosticBag) As Boolean
            Debug.Assert(diagBag IsNot Nothing)
            Debug.Assert(Not diagBag.IsEmptyWithoutResolution())
 
            For Each diag In diagBag.AsEnumerable()
                Dim cdiag = TryCast(diag, DiagnosticWithInfo)
                If cdiag Is Nothing OrElse Not cdiag.HasLazyInfo Then
                    Return False
                End If
            Next
 
            Return True
        End Function
 
        ''' <summary>
        ''' Atomically store value into variable, and store the diagnostics away for later retrieval.
        ''' When this routine returns, variable is non-null. If this routine stored value into variable,
        ''' then the diagnostic bag is saved away before the variable is stored and it returns True.
        ''' Otherwise it returns False.
        ''' </summary>
        Friend Function AtomicStoreReferenceAndDiagnostics(Of T As Class)(ByRef variable As T,
                                                                     value As T,
                                                                     diagBag As BindingDiagnosticBag,
                                                                     Optional comparand As T = Nothing) As Boolean
            Debug.Assert(value IsNot comparand)
 
            If diagBag Is Nothing OrElse diagBag.IsEmpty Then
                Return Interlocked.CompareExchange(variable, value, comparand) Is comparand AndAlso comparand Is Nothing
            Else
                Dim stored = False
                SyncLock _diagnosticLock
                    If variable Is comparand Then
                        StoreDeclarationDiagnostics(diagBag)
                        stored = Interlocked.CompareExchange(variable, value, comparand) Is comparand
                        If Not stored AndAlso Not IsEmptyIgnoringLazyDiagnostics(diagBag) Then
 
                            ' If this gets hit, then someone wrote to variable without going through this
                            ' routine, or else someone wrote to variable with this routine but an empty
                            ' diagnostic bag (they went through the above If part). Either is a bug.
                            Throw ExceptionUtilities.Unreachable
                        End If
                    End If
                End SyncLock
                Return stored AndAlso comparand Is Nothing
            End If
        End Function
 
        Private Shared Function IsEmptyIgnoringLazyDiagnostics(diagBag As BindingDiagnosticBag) As Boolean
            Return diagBag.DependenciesBag.IsNullOrEmpty() AndAlso
                   (Not diagBag.AccumulatesDiagnostics OrElse HasAllLazyDiagnostics(diagBag.DiagnosticBag))
        End Function
 
        ' Atomically store value into variable, and store the diagnostics away for later retrieval.
        ' When this routine returns, variable is not equal to comparand. If this routine stored value into variable,
        ' then the diagnostic bag is saved away before the variable is stored.
        Friend Sub AtomicStoreIntegerAndDiagnostics(ByRef variable As Integer,
                                                    value As Integer,
                                                    comparand As Integer,
                                                    diagBag As BindingDiagnosticBag)
            If diagBag Is Nothing OrElse diagBag.IsEmpty Then
                Interlocked.CompareExchange(variable, value, comparand)
            Else
                SyncLock _diagnosticLock
                    If variable = comparand Then
                        StoreDeclarationDiagnostics(diagBag)
                        If Interlocked.CompareExchange(variable, value, comparand) <> comparand AndAlso
                            Not IsEmptyIgnoringLazyDiagnostics(diagBag) Then
 
                            ' If this gets hit, then someone wrote to variable without going through this
                            ' routine, or else someone wrote to variable with this routine but an empty
                            ' diagnostic bag (they went through the above If part). Either is a bug.
                            Throw ExceptionUtilities.Unreachable
                        End If
                    End If
                End SyncLock
            End If
        End Sub
 
        ' Atomically set flag value into variable, and store the diagnostics away for later retrieval.
        ' When this routine returns, variable is not equal to comparand. If this routine stored value into variable,
        ' then the diagnostic bag is saved away before the variable is stored.
        Friend Function AtomicSetFlagAndStoreDiagnostics(ByRef variable As Integer,
                                               mask As Integer,
                                               comparand As Integer,
                                               diagBag As BindingDiagnosticBag) As Boolean
            If diagBag Is Nothing OrElse diagBag.IsEmpty Then
                Return ThreadSafeFlagOperations.Set(variable, mask)
            Else
                SyncLock _diagnosticLock
                    Dim change = (variable And mask) = comparand
                    If change Then
                        StoreDeclarationDiagnostics(diagBag)
 
                        If Not ThreadSafeFlagOperations.Set(variable, mask) AndAlso
                             Not IsEmptyIgnoringLazyDiagnostics(diagBag) Then
 
                            ' If this gets hit, then someone wrote to variable without going through this
                            ' routine, or else someone wrote to variable with this routine but an empty
                            ' diagnostic bag (they went through the above If part). Either is a bug.
                            Throw ExceptionUtilities.Unreachable
                        End If
                    End If
                    Return change
                End SyncLock
            End If
        End Function
 
        ' Atomically set flag value into variable, and raise the symbol declared event.
        ' When this routine returns, variable is not equal to comparand. If this routine stored value into variable,
        ' then the symbol declared event was raised for the symbol.
        Friend Function AtomicSetFlagAndRaiseSymbolDeclaredEvent(ByRef variable As Integer,
                                               mask As Integer,
                                               comparand As Integer,
                                               symbol As Symbol) As Boolean
            Debug.Assert(Me.DeclaringCompilation.EventQueue IsNot Nothing)
 
            SyncLock _diagnosticLock
                Dim change = (variable And mask) = comparand
                If change Then
                    Me.DeclaringCompilation.SymbolDeclaredEvent(symbol)
 
                    If Not ThreadSafeFlagOperations.Set(variable, mask) Then
                        ' If this gets hit, then someone wrote to variable without going through this
                        ' routine, which is a bug.
                        Throw ExceptionUtilities.Unreachable
                    End If
                End If
                Return change
            End SyncLock
        End Function
 
        Friend Function AtomicStoreArrayAndDiagnostics(Of T)(ByRef variable As ImmutableArray(Of T),
                                                             value As ImmutableArray(Of T),
                                                             diagBag As BindingDiagnosticBag) As Boolean
            Debug.Assert(Not value.IsDefault)
 
            If diagBag Is Nothing OrElse diagBag.IsEmpty Then
                Return ImmutableInterlocked.InterlockedInitialize(variable, value)
            Else
                SyncLock _diagnosticLock
                    If variable.IsDefault Then
                        StoreDeclarationDiagnostics(diagBag)
                        Dim stored = ImmutableInterlocked.InterlockedInitialize(variable, value)
                        If Not stored AndAlso Not IsEmptyIgnoringLazyDiagnostics(diagBag) Then
 
                            ' If this gets hit, then someone wrote to variable without going through this
                            ' routine, or else someone wrote to variable with this routine but an empty
                            ' diagnostic bag (they went through the above If part). Either is a bug.
                            Throw ExceptionUtilities.Unreachable
                        End If
                        Return stored
                    Else
                        Return False
                    End If
                End SyncLock
            End If
        End Function
 
        Friend Sub AtomicStoreAttributesAndDiagnostics(attributesBag As CustomAttributesBag(Of VisualBasicAttributeData),
                                                       attributesToStore As ImmutableArray(Of VisualBasicAttributeData),
                                                       diagBag As BindingDiagnosticBag)
            Debug.Assert(attributesBag IsNot Nothing)
            Debug.Assert(Not attributesToStore.IsDefault)
 
            RecordPresenceOfBadAttributes(attributesToStore)
 
            If diagBag Is Nothing OrElse diagBag.IsEmpty Then
                attributesBag.SetAttributes(attributesToStore)
            Else
                SyncLock _diagnosticLock
                    If Not attributesBag.IsSealed Then
                        StoreDeclarationDiagnostics(diagBag)
 
                        If Not attributesBag.SetAttributes(attributesToStore) AndAlso
                            Not IsEmptyIgnoringLazyDiagnostics(diagBag) Then
 
                            ' If this gets hit, then someone set attributes in the bag without going through this
                            ' routine, or else someone set attributes in the bag with this routine but an empty
                            ' diagnostic bag (they went through the above If part). Either is a bug.
                            Throw ExceptionUtilities.Unreachable
                        End If
 
                        Debug.Assert(attributesBag.IsSealed)
                    End If
                End SyncLock
            End If
        End Sub
 
        Private Sub RecordPresenceOfBadAttributes(attributes As ImmutableArray(Of VisualBasicAttributeData))
            If Not _hasBadAttributes Then
                For Each attribute In attributes
                    If attribute.HasErrors Then
                        _hasBadAttributes = True
                        Exit For
                    End If
                Next
            End If
        End Sub
 
        Friend ReadOnly Property HasBadAttributes As Boolean
            Get
                Return _hasBadAttributes
            End Get
        End Property
 
        ' same as AtomicStoreReferenceAndDiagnostics, but without storing any references
        Friend Sub AddDeclarationDiagnostics(diagBag As BindingDiagnosticBag)
            If Not diagBag.IsEmpty Then
                SyncLock _diagnosticLock
                    StoreDeclarationDiagnostics(diagBag)
                End SyncLock
            End If
        End Sub
 
        ' Given a diagnostic bag, store the diagnostics into the correct bags.
        ' NOTE: This is called from AtomicStoreReferenceAndDiagnostics, which takes a lock.
        ' NOTE: It is important that it doesn't do any operation that wants to acquire another lock.
        ' NOTE: Copy without resolving diagnostics.
        Private Sub StoreDeclarationDiagnostics(diagBag As BindingDiagnosticBag)
            If Not diagBag.IsEmpty Then
                If Not diagBag.DiagnosticBag?.IsEmptyWithoutResolution Then
                    For Each d As Diagnostic In diagBag.DiagnosticBag.AsEnumerableWithoutResolution()
                        Dim loc = d.Location
                        If loc.IsInSource Then
                            Dim tree = DirectCast(loc.SourceTree, VisualBasicSyntaxTree)
                            Dim sourceFile = TryGetSourceFile(tree)
                            Debug.Assert(sourceFile IsNot Nothing)
                            sourceFile.DeclarationDiagnostics.Add(d)
                        Else
                            Me._diagnosticBagDeclare.Add(d)
                        End If
                    Next
                End If
 
                If Not diagBag.DependenciesBag.IsNullOrEmpty() Then
                    DeclaringCompilation.AddUsedAssemblies(diagBag.DependenciesBag)
                End If
            End If
        End Sub
 
        Friend Overrides ReadOnly Property TypeNames As ICollection(Of String)
            Get
                Return _declarationTable.TypeNames
            End Get
        End Property
 
        Friend Overrides ReadOnly Property NamespaceNames As ICollection(Of String)
            Get
                Return _declarationTable.NamespaceNames
            End Get
        End Property
 
        Friend 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).
                If _lazyContainsExtensionMethods = ThreeState.Unknown Then
                    If Not (_assemblySymbol.Modules(0) Is Me) Then
                        _lazyContainsExtensionMethods = ThreeState.False
                    End If
                End If
 
                Return _lazyContainsExtensionMethods <> ThreeState.False
            End Get
        End Property
 
        Friend Sub RecordPresenceOfExtensionMethods()
            Debug.Assert(_lazyContainsExtensionMethods <> ThreeState.False)
            _lazyContainsExtensionMethods = ThreeState.True
        End Sub
 
        Friend Overrides Sub DecodeWellKnownAttribute(ByRef arguments As DecodeWellKnownAttributeArguments(Of AttributeSyntax, VisualBasicAttributeData, AttributeLocation))
            Debug.Assert(arguments.AttributeSyntaxOpt IsNot Nothing)
 
            Dim attrData = arguments.Attribute
            Debug.Assert(Not attrData.HasErrors)
            Debug.Assert(arguments.SymbolPart = AttributeLocation.None)
 
            If attrData.IsTargetAttribute(AttributeDescription.TupleElementNamesAttribute) Then
                DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_ExplicitTupleElementNamesAttribute, arguments.AttributeSyntaxOpt.Location)
            End If
 
            If attrData.IsTargetAttribute(AttributeDescription.DefaultCharSetAttribute) Then
                Dim charSet As CharSet = attrData.GetConstructorArgument(Of CharSet)(0, SpecialType.System_Enum)
                If Not CommonModuleWellKnownAttributeData.IsValidCharSet(charSet) Then
                    DirectCast(arguments.Diagnostics, BindingDiagnosticBag).Add(ERRID.ERR_BadAttribute1, VisualBasicAttributeData.GetFirstArgumentLocation(arguments.AttributeSyntaxOpt), attrData.AttributeClass)
                Else
                    arguments.GetOrCreateData(Of CommonModuleWellKnownAttributeData)().DefaultCharacterSet = charSet
                End If
            ElseIf attrData.IsTargetAttribute(AttributeDescription.DebuggableAttribute) Then
                arguments.GetOrCreateData(Of CommonModuleWellKnownAttributeData).HasDebuggableAttribute = True
            ElseIf attrData.IsTargetAttribute(AttributeDescription.ExperimentalAttribute) Then
                arguments.GetOrCreateData(Of CommonModuleWellKnownAttributeData).ExperimentalAttributeData = attrData.DecodeObsoleteAttribute(ObsoleteAttributeKind.Experimental)
            End If
 
            MyBase.DecodeWellKnownAttribute(arguments)
        End Sub
 
        Friend Overrides ReadOnly Property HasAssemblyCompilationRelaxationsAttribute() As Boolean
            Get
                Dim decodedData As CommonAssemblyWellKnownAttributeData(Of NamedTypeSymbol) = DirectCast(Me.ContainingAssembly, SourceAssemblySymbol).GetSourceDecodedWellKnownAttributeData()
                Return decodedData IsNot Nothing AndAlso decodedData.HasCompilationRelaxationsAttribute
            End Get
        End Property
 
        Friend Overrides ReadOnly Property HasAssemblyRuntimeCompatibilityAttribute() As Boolean
            Get
                Dim decodedData As CommonAssemblyWellKnownAttributeData(Of NamedTypeSymbol) = DirectCast(Me.ContainingAssembly, SourceAssemblySymbol).GetSourceDecodedWellKnownAttributeData()
                Return decodedData IsNot Nothing AndAlso decodedData.HasRuntimeCompatibilityAttribute
            End Get
        End Property
 
        Friend Overrides ReadOnly Property DefaultMarshallingCharSet As CharSet?
            Get
                Dim data = GetDecodedWellKnownAttributeData()
                Return If(data IsNot Nothing AndAlso data.HasDefaultCharSetAttribute, data.DefaultCharacterSet, DirectCast(Nothing, CharSet?))
            End Get
        End Property
 
        Public Function GetMyGroupCollectionPropertyWithDefaultInstanceAlias(classType As NamedTypeSymbol) As SynthesizedMyGroupCollectionPropertySymbol
            Debug.Assert(classType.IsDefinition AndAlso Not classType.IsGenericType)
 
            If _lazyTypesWithDefaultInstanceAlias Is Nothing Then
                _lazyTypesWithDefaultInstanceAlias = GetTypesWithDefaultInstanceAlias()
            End If
 
            Dim result As SynthesizedMyGroupCollectionPropertySymbol = Nothing
 
            If _lazyTypesWithDefaultInstanceAlias IsNot s_noTypesWithDefaultInstanceAlias AndAlso
               _lazyTypesWithDefaultInstanceAlias.TryGetValue(classType, result) Then
                Return result
            End If
 
            Return Nothing
        End Function
 
        Private Function GetTypesWithDefaultInstanceAlias() As Dictionary(Of NamedTypeSymbol, SynthesizedMyGroupCollectionPropertySymbol)
            Dim result As Dictionary(Of NamedTypeSymbol, SynthesizedMyGroupCollectionPropertySymbol) = Nothing
 
            If _assemblySymbol.DeclaringCompilation.MyTemplate IsNot Nothing Then
                GetTypesWithDefaultInstanceAlias(GlobalNamespace, result)
            End If
 
            If result Is Nothing Then
                result = s_noTypesWithDefaultInstanceAlias
            End If
 
            Return result
        End Function
 
        Private Shared Sub GetTypesWithDefaultInstanceAlias(
            namespaceOrType As NamespaceOrTypeSymbol,
            <[In], Out> ByRef result As Dictionary(Of NamedTypeSymbol, SynthesizedMyGroupCollectionPropertySymbol)
        )
            For Each member As Symbol In namespaceOrType.GetMembersUnordered()
                Select Case member.Kind
                    Case SymbolKind.Property
                        If member.IsMyGroupCollectionProperty Then
                            Dim prop = DirectCast(member, SynthesizedMyGroupCollectionPropertySymbol)
 
                            ' See Semantics::GetDefaultInstanceBaseNameForMyGroupMember
                            If prop.DefaultInstanceAlias.Length > 0 Then
                                Dim targetType = DirectCast(prop.Type, NamedTypeSymbol)
 
                                If result Is Nothing Then
                                    result = New Dictionary(Of NamedTypeSymbol, SynthesizedMyGroupCollectionPropertySymbol)(ReferenceEqualityComparer.Instance)
                                ElseIf result.ContainsKey(targetType) Then
                                    ' ambiguity
                                    result(targetType) = Nothing
                                    Exit Select
                                End If
 
                                result.Add(targetType, prop)
                            End If
                        End If
 
                    Case SymbolKind.NamedType
                        Dim named = TryCast(member, SourceNamedTypeSymbol)
 
                        If named IsNot Nothing Then
                            For Each syntaxRef As SyntaxReference In named.SyntaxReferences
                                If syntaxRef.SyntaxTree.IsMyTemplate Then
                                    GetTypesWithDefaultInstanceAlias(named, result)
                                    Exit For
                                End If
                            Next
                        End If
 
                    Case SymbolKind.Namespace
                        GetTypesWithDefaultInstanceAlias(DirectCast(member, NamespaceSymbol), result)
                End Select
            Next
        End Sub
 
        Public Overrides Function GetMetadata() As ModuleMetadata
            Return Nothing
        End Function
 
        Friend Overrides ReadOnly Property ObsoleteAttributeData As ObsoleteAttributeData
            Get
                Dim attributesBag As CustomAttributesBag(Of VisualBasicAttributeData) = Me._lazyCustomAttributesBag
                If attributesBag IsNot Nothing AndAlso attributesBag.IsDecodedWellKnownAttributeDataComputed Then
                    Return DirectCast(attributesBag.DecodedWellKnownAttributeData, CommonModuleWellKnownAttributeData)?.ExperimentalAttributeData
                End If
 
                Dim mergedAttributes = DirectCast(Me.ContainingAssembly, SourceAssemblySymbol).GetAttributeDeclarations()
                If mergedAttributes.IsEmpty Then
                    Return Nothing
                End If
 
                Return ObsoleteAttributeData.Uninitialized
            End Get
        End Property
 
    End Class
End Namespace