File: Symbols\ReferenceManager.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.Immutable
Imports System.Runtime.InteropServices
Imports Microsoft.CodeAnalysis.Collections
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.Symbols.Retargeting
Imports MetadataOrDiagnostic = System.Object
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    Partial Public NotInheritable Class VisualBasicCompilation
        ''' <summary>
        ''' ReferenceManager encapsulates functionality to create an underlying SourceAssemblySymbol 
        ''' (with underlying ModuleSymbols) for Compilation and AssemblySymbols for referenced assemblies 
        ''' (with underlying ModuleSymbols) all properly linked together based on reference resolution 
        ''' between them.
        ''' 
        ''' ReferenceManager is also responsible for reuse of metadata readers for imported modules and 
        ''' assemblies as well as existing AssemblySymbols for referenced assemblies. In order to do that, 
        ''' it maintains global cache for metadata readers and AssemblySymbols associated with them. 
        ''' The cache uses WeakReferences to refer to the metadata readers and AssemblySymbols to allow 
        ''' memory and resources being reclaimed once they are no longer used. The tricky part about reusing 
        ''' existing AssemblySymbols is to find a set of AssemblySymbols that are created for the referenced 
        ''' assemblies, which (the AssemblySymbols from the set) are linked in a way, consistent with the 
        ''' reference resolution between the referenced assemblies.
        ''' 
        ''' When existing Compilation is used as a metadata reference, there are scenarios when its underlying 
        ''' SourceAssemblySymbol cannot be used to provide symbols in context of the new Compilation. Consider 
        ''' classic multi-targeting scenario: compilation C1 references v1 of Lib.dll and compilation C2 
        ''' references C1 and v2 of Lib.dll. In this case, SourceAssemblySymbol for C1 is linked to AssemblySymbol 
        ''' for v1 of Lib.dll. However, given the set of references for C2, the same reference for C1 should be 
        ''' resolved against v2 of Lib.dll. In other words, in context of C2, all types from v1 of Lib.dll 
        ''' leaking through C1 (through method signatures, etc.) must be retargeted to the types from v2 of Lib.dll.
        ''' In this case, ReferenceManager creates a special RetargetingAssemblySymbol for C1, which is responsible 
        ''' for the type retargeting. The RetargetingAssemblySymbols could also be reused for different 
        ''' Compilations, ReferenceManager maintains a cache of RetargetingAssemblySymbols (WeakReferences) for each 
        ''' Compilation.
        ''' 
        ''' The only public entry point of this class is CreateSourceAssembly() method.
        ''' </summary>
        Friend NotInheritable Class ReferenceManager
            Inherits CommonReferenceManager(Of VisualBasicCompilation, AssemblySymbol)
 
            Public Sub New(simpleAssemblyName As String, identityComparer As AssemblyIdentityComparer, observedMetadata As Dictionary(Of MetadataReference, MetadataOrDiagnostic))
                MyBase.New(simpleAssemblyName, identityComparer, observedMetadata)
            End Sub
 
            Protected Overrides Sub GetActualBoundReferencesUsedBy(assemblySymbol As AssemblySymbol, referencedAssemblySymbols As List(Of AssemblySymbol))
                Debug.Assert(referencedAssemblySymbols.IsEmpty())
                For Each [module] In assemblySymbol.Modules
                    referencedAssemblySymbols.AddRange([module].GetReferencedAssemblySymbols())
                Next
 
                For i As Integer = 0 To referencedAssemblySymbols.Count - 1 Step 1
                    If referencedAssemblySymbols(i).IsMissing Then
                        referencedAssemblySymbols(i) = Nothing ' Do not expose missing assembly symbols to ReferenceManager.Binder
                    End If
                Next
            End Sub
 
            Protected Overrides Function GetNoPiaResolutionAssemblies(candidateAssembly As AssemblySymbol) As ImmutableArray(Of AssemblySymbol)
                If TypeOf candidateAssembly Is SourceAssemblySymbol Then
                    ' This is an optimization, if candidateAssembly links something or explicitly declares local type, 
                    ' common reference binder shouldn't reuse this symbol because candidateAssembly won't be in the 
                    ' set returned by GetNoPiaResolutionAssemblies(). This also makes things clearer.
                    Return ImmutableArray(Of AssemblySymbol).Empty
                End If
 
                Return candidateAssembly.GetNoPiaResolutionAssemblies()
            End Function
 
            Protected Overrides Function IsLinked(candidateAssembly As AssemblySymbol) As Boolean
                Return candidateAssembly.IsLinked
            End Function
 
            Protected Overrides Function GetCorLibrary(candidateAssembly As AssemblySymbol) As AssemblySymbol
                Dim corLibrary As AssemblySymbol = candidateAssembly.CorLibrary
 
                ' Do not expose missing assembly symbols to ReferenceManager.Binder
                Return If(corLibrary.IsMissing, Nothing, corLibrary)
            End Function
 
            Protected Overrides ReadOnly Property MessageProvider As CommonMessageProvider
                Get
                    Return VisualBasic.MessageProvider.Instance
                End Get
            End Property
 
            Protected Overrides Function CreateAssemblyDataForFile(assembly As PEAssembly,
                                                                   cachedSymbols As WeakList(Of IAssemblySymbolInternal),
                                                                   documentationProvider As DocumentationProvider,
                                                                   sourceAssemblySimpleName As String,
                                                                   importOptions As MetadataImportOptions,
                                                                   embedInteropTypes As Boolean) As AssemblyData
                Return New AssemblyDataForFile(assembly,
                                               cachedSymbols,
                                               embedInteropTypes,
                                               documentationProvider,
                                               sourceAssemblySimpleName,
                                               importOptions)
            End Function
 
            Protected Overrides Function CreateAssemblyDataForCompilation(compilationReference As CompilationReference) As AssemblyData
                Dim vbReference = TryCast(compilationReference, VisualBasicCompilationReference)
                If vbReference Is Nothing Then
                    Throw New NotSupportedException(String.Format(VBResources.CantReferenceCompilationFromTypes, compilationReference.GetType(), "Visual Basic"))
                End If
 
                Dim result As New AssemblyDataForCompilation(vbReference.Compilation, vbReference.Properties.EmbedInteropTypes)
                Debug.Assert(vbReference.Compilation._lazyAssemblySymbol IsNot Nothing)
                Return result
            End Function
 
            Protected Overrides Function CheckPropertiesConsistency(primaryReference As MetadataReference, duplicateReference As MetadataReference, diagnostics As DiagnosticBag) As Boolean
                Return True
            End Function
 
            ''' <summary>
            ''' VB allows two weak assembly references of the same simple name be passed to a compilation 
            ''' as long as their versions are different. It ignores culture.
            ''' </summary>
            Protected Overrides Function WeakIdentityPropertiesEquivalent(identity1 As AssemblyIdentity, identity2 As AssemblyIdentity) As Boolean
                Return identity1.Version = identity2.Version
            End Function
 
            Public Sub CreateSourceAssemblyForCompilation(compilation As VisualBasicCompilation)
                ' We are reading the Reference Manager state outside of a lock by accessing 
                ' IsBound and HasCircularReference properties.
                ' Once isBound flag is flipped the state of the manager is available and doesn't change.
                ' 
                ' If two threads are building SourceAssemblySymbol and the first just updated 
                ' set isBound flag to 1 but not yet set lazySourceAssemblySymbol,
                ' the second thread may end up reusing the Reference Manager data the first thread calculated. 
                ' That's ok since 
                ' 1) the second thread would produce the same data,
                ' 2) all results calculated by the second thread will be thrown away since the first thread 
                '    already acquired SymbolCacheAndReferenceManagerStateGuard that is needed to publish the data.
 
                ' Given compilation is the first compilation that shares this manager and its symbols are requested.
                ' Perform full reference resolution and binding.
                If Not IsBound AndAlso CreateAndSetSourceAssemblyFullBind(compilation) Then
 
                    ' we have successfully bound the references for the compilation
 
                ElseIf Not HasCircularReference Then
                    ' Another compilation that shares the manager with the given compilation
                    ' already bound its references and produced tables that we can use to construct 
                    ' source assembly symbol faster.
 
                    CreateAndSetSourceAssemblyReuseData(compilation)
                Else
                    ' We encountered a circular reference while binding the previous compilation.
                    ' This compilation can't share bound references with other compilations. Create a new manager.
 
                    ' NOTE: The CreateSourceAssemblyFullBind is going to replace compilation's reference manager with newManager.
 
                    Dim newManager = New ReferenceManager(Me.SimpleAssemblyName, Me.IdentityComparer, Me.ObservedMetadata)
                    Dim successful = newManager.CreateAndSetSourceAssemblyFullBind(compilation)
 
                    ' The new manager isn't shared with any other compilation so there is no other 
                    ' thread but the current one could have initialized it.
                    Debug.Assert(successful)
 
                    newManager.AssertBound()
                End If
 
                AssertBound()
                Debug.Assert(compilation._lazyAssemblySymbol IsNot Nothing)
            End Sub
 
            '''  <summary>
            '''  Creates a <see cref="PEAssemblySymbol"/> from specified metadata. 
            '''  </summary>
            '''  <remarks>
            '''  Used by EnC to create symbols for emit baseline. The PE symbols are used by <see cref="VisualBasicSymbolMatcher"/>.
            '''  
            '''  The assembly references listed in the metadata AssemblyRef table are matched to the resolved references 
            '''  stored on this <see cref="ReferenceManager"/>. We assume that the dependencies of the baseline metadata are 
            '''  the same as the dependencies of the current compilation. This is not exactly true when the dependencies use 
            '''  time-based versioning pattern, e.g. AssemblyVersion("1.0.*"). In that case we assume only the version
            '''  changed And nothing else.
            '''  
            '''  Each AssemblyRef is matched against the assembly identities using an exact equality comparison modulo version. 
            '''  AssemblyRef with lower version in metadata is matched to a PE assembly symbol with the higher version 
            '''  (provided that the assembly name, culture, PKT And flags are the same) if there is no symbol with the exactly matching version. 
            '''  If there are multiple symbols with higher versions selects the one with the minimal version among them.
            '''  
            '''  Matching to a higher version is necessary to support EnC for projects whose P2P dependencies use time-based versioning pattern. 
            '''  The versions of the dependent projects seen from the IDE will be higher than 
            '''  the one written in the metadata at the time their respective baselines are built.
            '''  
            '''  No other unification or further resolution is performed.
            '''  </remarks>
            ''' <param name="metadata"></param>
            ''' <param name="importOptions"></param>
            ''' <param name="assemblyReferenceIdentityMap">
            ''' A map of the PE assembly symbol identities to the identities of the original metadata AssemblyRefs.
            ''' This map will be used in emit when serializing AssemblyRef table of the delta. For the delta to be compatible with
            ''' the original metadata we need to map the identities of the PE assembly symbols back to the original AssemblyRefs (if different).
            ''' In other words, we pretend that the versions of the dependencies haven't changed.
            ''' </param>
            Friend Function CreatePEAssemblyForAssemblyMetadata(metadata As AssemblyMetadata, importOptions As MetadataImportOptions, <Out> ByRef assemblyReferenceIdentityMap As ImmutableDictionary(Of AssemblyIdentity, AssemblyIdentity)) As PEAssemblySymbol
                AssertBound()
 
                ' If the compilation has a reference from metadata to source assembly we can't share the referenced PE symbols.
                Debug.Assert(Not HasCircularReference)
 
                Dim referencedAssembliesByIdentity = New AssemblyIdentityMap(Of AssemblySymbol)()
                For Each symbol In Me.ReferencedAssemblies
                    referencedAssembliesByIdentity.Add(symbol.Identity, symbol)
                Next
 
                Dim assembly = metadata.GetAssembly
                Dim peReferences = assembly.AssemblyReferences.SelectAsArray(AddressOf MapAssemblyIdentityToResolvedSymbol, referencedAssembliesByIdentity)
 
                assemblyReferenceIdentityMap = GetAssemblyReferenceIdentityBaselineMap(peReferences, assembly.AssemblyReferences)
 
                Dim assemblySymbol = New PEAssemblySymbol(assembly, DocumentationProvider.Default, isLinked:=False, importOptions:=importOptions)
 
                Dim unifiedAssemblies = Me.UnifiedAssemblies.WhereAsArray(
                    Function(unified, refAsmByIdentity) refAsmByIdentity.Contains(unified.OriginalReference, allowHigherVersion:=False), referencedAssembliesByIdentity)
 
                InitializeAssemblyReuseData(assemblySymbol, peReferences, unifiedAssemblies)
 
                If assembly.ContainsNoPiaLocalTypes() Then
                    assemblySymbol.SetNoPiaResolutionAssemblies(Me.ReferencedAssemblies)
                End If
 
                Return assemblySymbol
            End Function
 
            Private Shared Function MapAssemblyIdentityToResolvedSymbol(identity As AssemblyIdentity, map As AssemblyIdentityMap(Of AssemblySymbol)) As AssemblySymbol
                Dim symbol As AssemblySymbol = Nothing
                If map.TryGetValue(identity, symbol, AddressOf CompareVersionPartsSpecifiedInSource) Then
                    Return symbol
                End If
 
                If map.TryGetValue(identity, symbol, Function(v1, v2, s) True) Then
                    ' TODO: https://github.com/dotnet/roslyn/issues/9004
                    Throw New NotSupportedException(String.Format(CodeAnalysisResources.ChangingVersionOfAssemblyReferenceIsNotAllowedDuringDebugging, identity, symbol.Identity.Version))
                End If
 
                Return New MissingAssemblySymbol(identity)
            End Function
 
            Private Sub CreateAndSetSourceAssemblyReuseData(compilation As VisualBasicCompilation)
                AssertBound()
 
                ' If the compilation has a reference from metadata to source assembly we can't share the referenced PE symbols.
                Debug.Assert(Not HasCircularReference)
 
                Dim moduleName As String = compilation.MakeSourceModuleName()
                Dim assemblySymbol = New SourceAssemblySymbol(compilation, Me.SimpleAssemblyName, moduleName, Me.ReferencedModules)
 
                InitializeAssemblyReuseData(assemblySymbol, Me.ReferencedAssemblies, Me.UnifiedAssemblies)
 
                If compilation._lazyAssemblySymbol Is Nothing Then
                    SyncLock SymbolCacheAndReferenceManagerStateGuard
                        If compilation._lazyAssemblySymbol Is Nothing Then
                            compilation._lazyAssemblySymbol = assemblySymbol
                            Debug.Assert(compilation._referenceManager Is Me)
                        End If
                    End SyncLock
                End If
            End Sub
 
            Private Sub InitializeAssemblyReuseData(assemblySymbol As AssemblySymbol, referencedAssemblies As ImmutableArray(Of AssemblySymbol), unifiedAssemblies As ImmutableArray(Of UnifiedAssembly(Of AssemblySymbol)))
                AssertBound()
 
                assemblySymbol.SetCorLibrary(If(Me.CorLibraryOpt, assemblySymbol))
 
                Dim sourceModuleReferences = New ModuleReferences(Of AssemblySymbol)(referencedAssemblies.SelectAsArray(Function(a) a.Identity), referencedAssemblies, unifiedAssemblies)
                assemblySymbol.Modules(0).SetReferences(sourceModuleReferences)
 
                Dim assemblyModules = assemblySymbol.Modules
                Dim referencedModulesReferences = Me.ReferencedModulesReferences
                Debug.Assert(assemblyModules.Length = referencedModulesReferences.Length + 1)
 
                For i = 1 To assemblyModules.Length - 1
                    assemblyModules(i).SetReferences(referencedModulesReferences(i - 1))
                Next
            End Sub
 
            ' Returns false if another compilation sharing this manager finished binding earlier and we should reuse its results.
            Friend Function CreateAndSetSourceAssemblyFullBind(compilation As VisualBasicCompilation) As Boolean
 
                Dim resolutionDiagnostics = DiagnosticBag.GetInstance()
                Dim supersedeLowerVersions = compilation.Options.ReferencesSupersedeLowerVersions
                Dim assemblyReferencesBySimpleName = PooledDictionary(Of String, List(Of ReferencedAssemblyIdentity)).GetInstance()
 
                Try
                    Dim boundReferenceDirectiveMap As IDictionary(Of ValueTuple(Of String, String), MetadataReference) = Nothing
                    Dim boundReferenceDirectives As ImmutableArray(Of MetadataReference) = Nothing
                    Dim referencedAssemblies As ImmutableArray(Of AssemblyData) = Nothing
                    Dim modules As ImmutableArray(Of PEModule) = Nothing ' To make sure the modules are not collected ahead of time.
                    Dim explicitReferences As ImmutableArray(Of MetadataReference) = Nothing
 
                    Dim referenceMap As ImmutableArray(Of ResolvedReference) = ResolveMetadataReferences(
                        compilation,
                        assemblyReferencesBySimpleName,
                        explicitReferences,
                        boundReferenceDirectiveMap,
                        boundReferenceDirectives,
                        referencedAssemblies,
                        modules,
                        resolutionDiagnostics)
 
                    Dim assemblyBeingBuiltData As New AssemblyDataForAssemblyBeingBuilt(New AssemblyIdentity(name:=SimpleAssemblyName, noThrow:=True), referencedAssemblies, modules)
                    Dim explicitAssemblyData = referencedAssemblies.Insert(0, assemblyBeingBuiltData)
 
                    ' Let's bind all the references and resolve missing one (if resolver is available)
                    Dim hasCircularReference As Boolean
                    Dim corLibraryIndex As Integer
                    Dim implicitlyResolvedReferences As ImmutableArray(Of MetadataReference) = Nothing
                    Dim implicitlyResolvedReferenceMap As ImmutableArray(Of ResolvedReference) = Nothing
                    Dim allAssemblyData As ImmutableArray(Of AssemblyData) = Nothing
 
                    ' Avoid resolving previously resolved missing references. If we call to the resolver again we would create new assembly symbols for them,
                    ' which would not match the previously created ones. As a result we would get duplicate PE types And conversion errors.
                    Dim implicitReferenceResolutions = If(compilation.ScriptCompilationInfo?.PreviousScriptCompilation?.GetBoundReferenceManager().ImplicitReferenceResolutions,
                        ImmutableDictionary(Of AssemblyIdentity, PortableExecutableReference).Empty)
 
                    Dim bindingResult() As BoundInputAssembly = Bind(explicitAssemblyData,
                                                                     modules,
                                                                     explicitReferences,
                                                                     referenceMap,
                                                                     compilation.Options.MetadataReferenceResolver,
                                                                     compilation.Options.MetadataImportOptions,
                                                                     supersedeLowerVersions,
                                                                     assemblyReferencesBySimpleName,
                                                                     allAssemblyData,
                                                                     implicitlyResolvedReferences,
                                                                     implicitlyResolvedReferenceMap,
                                                                     implicitReferenceResolutions,
                                                                     resolutionDiagnostics,
                                                                     hasCircularReference,
                                                                     corLibraryIndex)
 
                    Debug.Assert(bindingResult.Length = allAssemblyData.Length)
 
                    Dim references = explicitReferences.AddRange(implicitlyResolvedReferences)
                    referenceMap = referenceMap.AddRange(implicitlyResolvedReferenceMap)
 
                    Dim referencedAssembliesMap As Dictionary(Of MetadataReference, Integer) = Nothing
                    Dim referencedModulesMap As Dictionary(Of MetadataReference, Integer) = Nothing
                    Dim aliasesOfReferencedAssemblies As ImmutableArray(Of ImmutableArray(Of String)) = Nothing
                    Dim mergedAssemblyReferencesMapOpt As Dictionary(Of MetadataReference, ImmutableArray(Of MetadataReference)) = Nothing
 
                    BuildReferencedAssembliesAndModulesMaps(
                        bindingResult,
                        references,
                        referenceMap,
                        modules.Length,
                        referencedAssemblies.Length,
                        assemblyReferencesBySimpleName,
                        supersedeLowerVersions,
                        referencedAssembliesMap,
                        referencedModulesMap,
                        aliasesOfReferencedAssemblies,
                        mergedAssemblyReferencesMapOpt)
 
                    ' Create AssemblySymbols for assemblies that can't use any existing symbols.
                    Dim newSymbols As New List(Of Integer)
 
                    For i As Integer = 1 To bindingResult.Length - 1 Step 1
                        If bindingResult(i).AssemblySymbol Is Nothing Then
                            ' symbol hasn't been found in the cache, create a new one
                            bindingResult(i).AssemblySymbol = DirectCast(allAssemblyData(i), AssemblyDataForMetadataOrCompilation).CreateAssemblySymbol()
                            newSymbols.Add(i)
                        End If
 
                        Debug.Assert(allAssemblyData(i).IsLinked = bindingResult(i).AssemblySymbol.IsLinked)
                    Next
 
                    Dim assemblySymbol = New SourceAssemblySymbol(compilation, SimpleAssemblyName, compilation.MakeSourceModuleName(), modules)
 
                    Dim corLibrary As AssemblySymbol
 
                    If corLibraryIndex = 0 Then
                        corLibrary = assemblySymbol
                    ElseIf corLibraryIndex > 0 Then
                        corLibrary = bindingResult(corLibraryIndex).AssemblySymbol
                    Else
                        corLibrary = MissingCorLibrarySymbol.Instance
                    End If
 
                    assemblySymbol.SetCorLibrary(corLibrary)
 
                    ' Setup bound references for newly created AssemblySymbols
                    ' This should be done after we created/found all AssemblySymbols 
                    Dim missingAssemblies As Dictionary(Of AssemblyIdentity, MissingAssemblySymbol) = Nothing
 
                    ' -1 for assembly being built
                    Dim totalReferencedAssemblyCount = allAssemblyData.Length - 1
 
                    ' Setup bound references for newly created SourceAssemblySymbol
                    Dim moduleReferences As ImmutableArray(Of ModuleReferences(Of AssemblySymbol)) = Nothing
                    SetupReferencesForSourceAssembly(assemblySymbol,
                                                     modules,
                                                     totalReferencedAssemblyCount,
                                                     bindingResult,
                                                     missingAssemblies,
                                                     moduleReferences)
 
                    If newSymbols.Count > 0 Then
                        ' Only if we detected that a referenced assembly refers to the assembly being built
                        ' we allow the references to get a hold of the assembly being built.
                        If hasCircularReference Then
                            bindingResult(0).AssemblySymbol = assemblySymbol
                        End If
 
                        InitializeNewSymbols(newSymbols, assemblySymbol, allAssemblyData, bindingResult, missingAssemblies)
                    End If
 
                    If compilation._lazyAssemblySymbol Is Nothing Then
                        SyncLock SymbolCacheAndReferenceManagerStateGuard
                            If compilation._lazyAssemblySymbol Is Nothing Then
 
                                If IsBound Then
                                    ' Another thread has finished constructing AssemblySymbol for another compilation that shares this manager.
                                    ' Drop the results and reuse the symbols that were created for the other compilation.
                                    Return False
                                End If
 
                                UpdateSymbolCacheNoLock(newSymbols, allAssemblyData, bindingResult)
 
                                InitializeNoLock(
                                    referencedAssembliesMap,
                                    referencedModulesMap,
                                    boundReferenceDirectiveMap,
                                    boundReferenceDirectives,
                                    explicitReferences,
                                    implicitReferenceResolutions,
                                    hasCircularReference,
                                    resolutionDiagnostics.ToReadOnly(),
                                    If(corLibrary Is assemblySymbol, Nothing, corLibrary),
                                    modules,
                                    moduleReferences,
                                    assemblySymbol.SourceModule.GetReferencedAssemblySymbols(),
                                    aliasesOfReferencedAssemblies,
                                    assemblySymbol.SourceModule.GetUnifiedAssemblies(),
                                    mergedAssemblyReferencesMapOpt)
 
                                ' Make sure that the given compilation holds on this instance of reference manager.
                                Debug.Assert(compilation._referenceManager Is Me OrElse hasCircularReference)
                                compilation._referenceManager = Me
 
                                ' Finally, publish the source symbol after all data have been written.
                                ' Once lazyAssemblySymbol is non-null other readers might start reading the data written above.
                                compilation._lazyAssemblySymbol = assemblySymbol
                            End If
                        End SyncLock
                    End If
 
                    Return True
                Finally
                    resolutionDiagnostics.Free()
                    assemblyReferencesBySimpleName.Free()
                End Try
            End Function
 
            Private Shared Sub InitializeNewSymbols(newSymbols As List(Of Integer),
                                                    assemblySymbol As SourceAssemblySymbol,
                                                    assemblies As ImmutableArray(Of AssemblyData),
                                                    bindingResult As BoundInputAssembly(),
                                                    missingAssemblies As Dictionary(Of AssemblyIdentity, MissingAssemblySymbol))
                Debug.Assert(newSymbols.Count > 0)
 
                Dim corLibrary = assemblySymbol.CorLibrary
                Debug.Assert(corLibrary IsNot Nothing)
 
                For Each i As Integer In newSymbols
                    Dim compilationData = TryCast(assemblies(i), AssemblyDataForCompilation)
 
                    If compilationData IsNot Nothing Then
                        SetupReferencesForRetargetingAssembly(bindingResult, i, missingAssemblies, sourceAssemblyDebugOnly:=assemblySymbol)
                    Else
                        Dim fileData = DirectCast(assemblies(i), AssemblyDataForFile)
                        SetupReferencesForFileAssembly(fileData, bindingResult, i, missingAssemblies, sourceAssemblyDebugOnly:=assemblySymbol)
                    End If
                Next
 
                Dim linkedReferencedAssembliesBuilder = ArrayBuilder(Of AssemblySymbol).GetInstance()
 
                ' Setup CorLibrary and NoPia stuff for newly created assemblies
 
                For Each i As Integer In newSymbols
                    If assemblies(i).ContainsNoPiaLocalTypes Then
                        bindingResult(i).AssemblySymbol.SetNoPiaResolutionAssemblies(
                            assemblySymbol.Modules(0).GetReferencedAssemblySymbols())
                    End If
 
                    ' Setup linked referenced assemblies.
                    linkedReferencedAssembliesBuilder.Clear()
 
                    If assemblies(i).IsLinked Then
                        linkedReferencedAssembliesBuilder.Add(bindingResult(i).AssemblySymbol)
                    End If
 
                    For Each referenceBinding In bindingResult(i).ReferenceBinding
                        If referenceBinding.IsBound AndAlso
                           assemblies(referenceBinding.DefinitionIndex).IsLinked Then
                            linkedReferencedAssembliesBuilder.Add(
                                bindingResult(referenceBinding.DefinitionIndex).AssemblySymbol)
                        End If
                    Next
 
                    If linkedReferencedAssembliesBuilder.Count > 0 Then
                        linkedReferencedAssembliesBuilder.RemoveDuplicates()
                        bindingResult(i).AssemblySymbol.SetLinkedReferencedAssemblies(linkedReferencedAssembliesBuilder.ToImmutable())
                    End If
 
                    bindingResult(i).AssemblySymbol.SetCorLibrary(corLibrary)
                Next
 
                linkedReferencedAssembliesBuilder.Free()
 
                If missingAssemblies IsNot Nothing Then
                    For Each missingAssembly In missingAssemblies.Values
                        missingAssembly.SetCorLibrary(corLibrary)
                    Next
                End If
            End Sub
 
            Private Sub UpdateSymbolCacheNoLock(newSymbols As List(Of Integer), assemblies As ImmutableArray(Of AssemblyData), bindingResult As BoundInputAssembly())
                ' Add new assembly symbols into the cache
                For Each i As Integer In newSymbols
                    Dim compilationData = TryCast(assemblies(i), AssemblyDataForCompilation)
 
                    If compilationData IsNot Nothing Then
                        compilationData.Compilation.CacheRetargetingAssemblySymbolNoLock(bindingResult(i).AssemblySymbol)
                    Else
                        Dim fileData = DirectCast(assemblies(i), AssemblyDataForFile)
                        fileData.CachedSymbols.Add(bindingResult(i).AssemblySymbol)
                    End If
                Next
            End Sub
 
            Private Shared Sub SetupReferencesForRetargetingAssembly(
                bindingResult() As BoundInputAssembly,
                bindingIndex As Integer,
                ByRef missingAssemblies As Dictionary(Of AssemblyIdentity, MissingAssemblySymbol),
                sourceAssemblyDebugOnly As SourceAssemblySymbol
            )
                Dim retargetingAssemblySymbol = DirectCast(bindingResult(bindingIndex).AssemblySymbol, Retargeting.RetargetingAssemblySymbol)
                Dim modules As ImmutableArray(Of ModuleSymbol) = retargetingAssemblySymbol.Modules
                Dim moduleCount = modules.Length
                Dim refsUsed As Integer = 0
 
                For j As Integer = 0 To moduleCount - 1 Step 1
                    Dim referencedAssemblies As ImmutableArray(Of AssemblyIdentity) = retargetingAssemblySymbol.UnderlyingAssembly.Modules(j).GetReferencedAssemblies()
 
                    ' For source module skip underlying linked references
                    If j = 0 Then
                        Dim underlyingReferencedAssemblySymbols As ImmutableArray(Of AssemblySymbol) =
                            retargetingAssemblySymbol.UnderlyingAssembly.Modules(0).GetReferencedAssemblySymbols()
 
                        Dim linkedUnderlyingReferences As Integer = 0
 
                        For Each asm As AssemblySymbol In underlyingReferencedAssemblySymbols
                            If asm.IsLinked Then
                                linkedUnderlyingReferences += 1
                            End If
                        Next
 
                        If linkedUnderlyingReferences > 0 Then
                            Dim filteredReferencedAssemblies As AssemblyIdentity() =
                                New AssemblyIdentity(referencedAssemblies.Length - linkedUnderlyingReferences - 1) {}
 
                            Dim newIndex As Integer = 0
 
                            For k As Integer = 0 To underlyingReferencedAssemblySymbols.Length - 1 Step 1
                                If Not underlyingReferencedAssemblySymbols(k).IsLinked Then
                                    filteredReferencedAssemblies(newIndex) = referencedAssemblies(k)
                                    newIndex += 1
                                End If
                            Next
 
                            Debug.Assert(newIndex = filteredReferencedAssemblies.Length)
                            referencedAssemblies = filteredReferencedAssemblies.AsImmutableOrNull()
                        End If
                    End If
 
                    Dim refsCount As Integer = referencedAssemblies.Length
                    Dim symbols(refsCount - 1) As AssemblySymbol
                    Dim unifiedAssemblies As ArrayBuilder(Of UnifiedAssembly(Of AssemblySymbol)) = Nothing
 
                    For k As Integer = 0 To refsCount - 1 Step 1
                        Dim referenceBinding = bindingResult(bindingIndex).ReferenceBinding(refsUsed + k)
                        If referenceBinding.IsBound Then
                            symbols(k) = GetAssemblyDefinitionSymbol(bindingResult, referenceBinding, unifiedAssemblies)
                        Else
                            symbols(k) = GetOrAddMissingAssemblySymbol(referencedAssemblies(k), missingAssemblies)
                        End If
                    Next
 
                    Dim moduleReferences As New ModuleReferences(Of AssemblySymbol)(referencedAssemblies, symbols.AsImmutableOrNull(), unifiedAssemblies.AsImmutableOrEmpty())
                    modules(j).SetReferences(moduleReferences, sourceAssemblyDebugOnly)
 
                    refsUsed += refsCount
                Next
            End Sub
 
            Private Shared Sub SetupReferencesForFileAssembly(
                fileData As AssemblyDataForFile,
                bindingResult() As BoundInputAssembly,
                bindingIndex As Integer,
                ByRef missingAssemblies As Dictionary(Of AssemblyIdentity, MissingAssemblySymbol),
                sourceAssemblyDebugOnly As SourceAssemblySymbol
            )
                Dim peAssemblySymbol = DirectCast(bindingResult(bindingIndex).AssemblySymbol, Symbols.Metadata.PE.PEAssemblySymbol)
 
                Dim modules As ImmutableArray(Of ModuleSymbol) = peAssemblySymbol.Modules
                Dim moduleCount = modules.Length
                Dim refsUsed As Integer = 0
 
                For j As Integer = 0 To moduleCount - 1 Step 1
                    Dim refsCount As Integer = fileData.Assembly.ModuleReferenceCounts(j)
                    Dim names(refsCount - 1) As AssemblyIdentity
                    Dim symbols(refsCount - 1) As AssemblySymbol
 
                    fileData.AssemblyReferences.CopyTo(refsUsed, names, 0, refsCount)
 
                    Dim unifiedAssemblies As ArrayBuilder(Of UnifiedAssembly(Of AssemblySymbol)) = Nothing
 
                    For k As Integer = 0 To refsCount - 1 Step 1
                        Dim referenceBinding = bindingResult(bindingIndex).ReferenceBinding(refsUsed + k)
                        If referenceBinding.IsBound Then
                            symbols(k) = GetAssemblyDefinitionSymbol(bindingResult, referenceBinding, unifiedAssemblies)
                        Else
                            symbols(k) = GetOrAddMissingAssemblySymbol(names(k), missingAssemblies)
                        End If
                    Next
 
                    Dim moduleReferences = New ModuleReferences(Of AssemblySymbol)(names.AsImmutableOrNull(), symbols.AsImmutableOrNull(), unifiedAssemblies.AsImmutableOrEmpty())
                    modules(j).SetReferences(moduleReferences, sourceAssemblyDebugOnly)
 
                    refsUsed += refsCount
                Next
            End Sub
 
            Private Shared Sub SetupReferencesForSourceAssembly(
                sourceAssembly As SourceAssemblySymbol,
                modules As ImmutableArray(Of PEModule),
                totalReferencedAssemblyCount As Integer,
                bindingResult() As BoundInputAssembly,
                ByRef missingAssemblies As Dictionary(Of AssemblyIdentity, MissingAssemblySymbol),
                ByRef moduleReferences As ImmutableArray(Of ModuleReferences(Of AssemblySymbol))
            )
                Dim moduleSymbols = sourceAssembly.Modules
                Debug.Assert(moduleSymbols.Length = 1 + modules.Length)
 
                Dim moduleReferencesBuilder = If(moduleSymbols.Length > 1, ArrayBuilder(Of ModuleReferences(Of AssemblySymbol)).GetInstance(), Nothing)
 
                Dim refsUsed As Integer = 0
                For moduleIndex As Integer = 0 To moduleSymbols.Length - 1 Step 1
                    Dim refsCount As Integer = If(moduleIndex = 0, totalReferencedAssemblyCount, modules(moduleIndex - 1).ReferencedAssemblies.Length)
 
                    Dim identities(refsCount - 1) As AssemblyIdentity
                    Dim symbols(refsCount - 1) As AssemblySymbol
 
                    Dim unifiedAssemblies As ArrayBuilder(Of UnifiedAssembly(Of AssemblySymbol)) = Nothing
 
                    For k As Integer = 0 To refsCount - 1 Step 1
                        Dim boundReference = bindingResult(0).ReferenceBinding(refsUsed + k)
                        If boundReference.IsBound Then
                            symbols(k) = GetAssemblyDefinitionSymbol(bindingResult, boundReference, unifiedAssemblies)
                        Else
                            symbols(k) = GetOrAddMissingAssemblySymbol(boundReference.ReferenceIdentity, missingAssemblies)
                        End If
 
                        identities(k) = boundReference.ReferenceIdentity
                    Next
 
                    Dim references = New ModuleReferences(Of AssemblySymbol)(identities.AsImmutableOrNull(),
                                                                             symbols.AsImmutableOrNull(),
                                                                             unifiedAssemblies.AsImmutableOrEmpty())
 
                    If moduleIndex > 0 Then
                        moduleReferencesBuilder.Add(references)
                    End If
 
                    moduleSymbols(moduleIndex).SetReferences(references, sourceAssembly)
 
                    refsUsed += refsCount
                Next
 
                moduleReferences = moduleReferencesBuilder.ToImmutableOrEmptyAndFree()
            End Sub
 
            Private Shared Function GetAssemblyDefinitionSymbol(bindingResult As BoundInputAssembly(),
                                                                referenceBinding As AssemblyReferenceBinding,
                                                                ByRef unifiedAssemblies As ArrayBuilder(Of UnifiedAssembly(Of AssemblySymbol))) As AssemblySymbol
                Debug.Assert(referenceBinding.IsBound)
                Dim assembly = bindingResult(referenceBinding.DefinitionIndex).AssemblySymbol
                Debug.Assert(assembly IsNot Nothing)
 
                If referenceBinding.VersionDifference <> 0 Then
                    If unifiedAssemblies Is Nothing Then
                        unifiedAssemblies = New ArrayBuilder(Of UnifiedAssembly(Of AssemblySymbol))()
                    End If
 
                    unifiedAssemblies.Add(New UnifiedAssembly(Of AssemblySymbol)(assembly, referenceBinding.ReferenceIdentity))
                End If
 
                Return assembly
            End Function
 
            Private Shared Function GetOrAddMissingAssemblySymbol(
                identity As AssemblyIdentity,
                ByRef missingAssemblies As Dictionary(Of AssemblyIdentity, MissingAssemblySymbol)
            ) As MissingAssemblySymbol
                Dim missingAssembly As MissingAssemblySymbol = Nothing
 
                If missingAssemblies Is Nothing Then
                    missingAssemblies = New Dictionary(Of AssemblyIdentity, MissingAssemblySymbol)()
                ElseIf missingAssemblies.TryGetValue(identity, missingAssembly) Then
                    Return missingAssembly
                End If
 
                missingAssembly = New MissingAssemblySymbol(identity)
                missingAssemblies.Add(identity, missingAssembly)
 
                Return missingAssembly
            End Function
 
            Private MustInherit Class AssemblyDataForMetadataOrCompilation
                Inherits AssemblyData
 
                Private _assemblies As ImmutableArray(Of AssemblySymbol)
                Private ReadOnly _identity As AssemblyIdentity
                Private ReadOnly _referencedAssemblies As ImmutableArray(Of AssemblyIdentity)
                Private ReadOnly _embedInteropTypes As Boolean
 
                Protected Sub New(identity As AssemblyIdentity,
                                  referencedAssemblies As ImmutableArray(Of AssemblyIdentity),
                                  embedInteropTypes As Boolean)
 
                    Debug.Assert(identity IsNot Nothing)
                    Debug.Assert(Not referencedAssemblies.IsDefault)
 
                    _embedInteropTypes = embedInteropTypes
                    _identity = identity
                    _referencedAssemblies = referencedAssemblies
                End Sub
 
                Friend MustOverride Function CreateAssemblySymbol() As AssemblySymbol
 
                Public Overrides ReadOnly Property Identity As AssemblyIdentity
                    Get
                        Return _identity
                    End Get
                End Property
 
                Public Overrides ReadOnly Property AvailableSymbols As ImmutableArray(Of AssemblySymbol)
                    Get
                        If (_assemblies.IsDefault) Then
                            Dim assemblies = ArrayBuilder(Of AssemblySymbol).GetInstance()
 
                            ' This should be done lazy because while we creating
                            ' instances of this type, creation of new SourceAssembly symbols
                            ' might change the set of available AssemblySymbols.
                            AddAvailableSymbols(assemblies)
 
                            _assemblies = assemblies.ToImmutableAndFree()
                        End If
 
                        Return _assemblies
                    End Get
                End Property
 
                Protected MustOverride Sub AddAvailableSymbols(assemblies As ArrayBuilder(Of AssemblySymbol))
 
                Public Overrides ReadOnly Property AssemblyReferences As ImmutableArray(Of AssemblyIdentity)
                    Get
                        Return _referencedAssemblies
                    End Get
                End Property
 
                Public Overrides Function BindAssemblyReferences(assemblies As MultiDictionary(Of String, (DefinitionData As AssemblyData, DefinitionIndex As Integer)), assemblyIdentityComparer As AssemblyIdentityComparer) As AssemblyReferenceBinding()
                    Return ResolveReferencedAssemblies(_referencedAssemblies, assemblies, resolveAgainstAssemblyBeingBuilt:=True, assemblyIdentityComparer:=assemblyIdentityComparer)
                End Function
 
                Public NotOverridable Overrides ReadOnly Property IsLinked As Boolean
                    Get
                        Return _embedInteropTypes
                    End Get
                End Property
            End Class
 
            Private NotInheritable Class AssemblyDataForFile
                Inherits AssemblyDataForMetadataOrCompilation
 
                Public ReadOnly Assembly As PEAssembly
 
                ''' <summary>
                ''' Guarded by <see cref="CommonReferenceManager.SymbolCacheAndReferenceManagerStateGuard"/>.
                ''' </summary>
                Public ReadOnly CachedSymbols As WeakList(Of IAssemblySymbolInternal)
 
                Public ReadOnly DocumentationProvider As DocumentationProvider
 
                ''' <summary>
                ''' Import options of the compilation being built.
                ''' </summary>
                Private ReadOnly _compilationImportOptions As MetadataImportOptions
 
                ' This is the name of the compilation that is being built. 
                ' This should be the assembly name w/o the extension. It is
                ' used to compute whether or not it is possible that this
                ' assembly will give friend access to the compilation.
                Private ReadOnly _sourceAssemblySimpleName As String
 
                Private _internalsVisibleComputed As Boolean = False
                Private _internalsPotentiallyVisibleToCompilation As Boolean = False
 
                Public Sub New(assembly As PEAssembly,
                               cachedSymbols As WeakList(Of IAssemblySymbolInternal),
                               embedInteropTypes As Boolean,
                               documentationProvider As DocumentationProvider,
                               sourceAssemblySimpleName As String,
                               compilationImportOptions As MetadataImportOptions)
 
                    MyBase.New(assembly.Identity, assembly.AssemblyReferences, embedInteropTypes)
 
                    Debug.Assert(documentationProvider IsNot Nothing)
                    Debug.Assert(cachedSymbols IsNot Nothing)
 
                    Me.CachedSymbols = cachedSymbols
                    Me.Assembly = assembly
                    Me.DocumentationProvider = documentationProvider
                    _compilationImportOptions = compilationImportOptions
                    _sourceAssemblySimpleName = sourceAssemblySimpleName
                End Sub
 
                Friend Overrides Function CreateAssemblySymbol() As AssemblySymbol
                    Return New PEAssemblySymbol(Assembly, DocumentationProvider, IsLinked, EffectiveImportOptions)
                End Function
 
                Friend ReadOnly Property InternalsMayBeVisibleToCompilation As Boolean
                    Get
                        If Not _internalsVisibleComputed Then
                            _internalsPotentiallyVisibleToCompilation = InternalsMayBeVisibleToAssemblyBeingCompiled(_sourceAssemblySimpleName, Assembly)
                            _internalsVisibleComputed = True
                        End If
 
                        Return _internalsPotentiallyVisibleToCompilation
                    End Get
                End Property
 
                Friend ReadOnly Property EffectiveImportOptions As MetadataImportOptions
                    Get
                        If InternalsMayBeVisibleToCompilation AndAlso _compilationImportOptions = MetadataImportOptions.Public Then
                            Return MetadataImportOptions.Internal
                        End If
 
                        Return _compilationImportOptions
                    End Get
                End Property
 
                Protected Overrides Sub AddAvailableSymbols(assemblies As ArrayBuilder(Of AssemblySymbol))
                    Dim internalsMayBeVisibleToCompilation = Me.InternalsMayBeVisibleToCompilation
 
                    ' accessing cached symbols requires a lock
                    SyncLock SymbolCacheAndReferenceManagerStateGuard
                        For Each assemblySymbol In CachedSymbols
                            Dim peAssembly = TryCast(assemblySymbol, PEAssemblySymbol)
                            If IsMatchingAssembly(peAssembly) Then
                                assemblies.Add(peAssembly)
                            End If
                        Next
                    End SyncLock
                End Sub
 
                Public Overrides Function IsMatchingAssembly(candidateAssembly As AssemblySymbol) As Boolean
                    Return IsMatchingAssembly(TryCast(candidateAssembly, PEAssemblySymbol))
                End Function
 
                Private Overloads Function IsMatchingAssembly(peAssembly As PEAssemblySymbol) As Boolean
                    If peAssembly Is Nothing Then
                        Return False
                    End If
 
                    If peAssembly.Assembly IsNot Me.Assembly Then
                        Return False
                    End If
 
                    If EffectiveImportOptions <> peAssembly.PrimaryModule.ImportOptions Then
                        Return False
                    End If
 
                    ' TODO (tomat): 
                    ' We shouldn't need to compare documentation providers. All symbols in the cachedSymbols list 
                    ' should share the same provider - as they share the same metadata.
                    ' Removing the Equals call also avoids calling user code while holding a lock.
                    If Not peAssembly.DocumentationProvider.Equals(DocumentationProvider) Then
                        Return False
                    End If
 
                    Return True
                End Function
 
                Public Overrides ReadOnly Property ContainsNoPiaLocalTypes() As Boolean
                    Get
                        Return Assembly.ContainsNoPiaLocalTypes()
                    End Get
                End Property
 
                Public Overrides ReadOnly Property DeclaresTheObjectClass As Boolean
                    Get
                        Return Assembly.DeclaresTheObjectClass
                    End Get
                End Property
 
                Public Overrides ReadOnly Property SourceCompilation As Compilation
                    Get
                        Return Nothing
                    End Get
                End Property
            End Class
 
            Private NotInheritable Class AssemblyDataForCompilation
                Inherits AssemblyDataForMetadataOrCompilation
 
                Public ReadOnly Compilation As VisualBasicCompilation
 
                Public Sub New(compilation As VisualBasicCompilation, embedInteropTypes As Boolean)
                    MyBase.New(compilation.Assembly.Identity, GetReferencedAssemblies(compilation), embedInteropTypes)
 
                    Debug.Assert(compilation IsNot Nothing)
                    Me.Compilation = compilation
                End Sub
 
                Private Shared Function GetReferencedAssemblies(compilation As VisualBasicCompilation) As ImmutableArray(Of AssemblyIdentity)
                    ' Collect information about references
                    Dim refs = ArrayBuilder(Of AssemblyIdentity).GetInstance()
 
                    Dim modules = compilation.Assembly.Modules
 
                    ' Filter out linked assemblies referenced by the source module.
                    Dim sourceReferencedAssemblies = modules(0).GetReferencedAssemblies()
                    Dim sourceReferencedAssemblySymbols = modules(0).GetReferencedAssemblySymbols()
 
                    Debug.Assert(sourceReferencedAssemblies.Length = sourceReferencedAssemblySymbols.Length)
 
                    For i = 0 To sourceReferencedAssemblies.Length - 1
                        If Not sourceReferencedAssemblySymbols(i).IsLinked Then
                            refs.Add(sourceReferencedAssemblies(i))
                        End If
                    Next
 
                    For i = 1 To modules.Length - 1
                        refs.AddRange(modules(i).GetReferencedAssemblies())
                    Next
 
                    Return refs.ToImmutableAndFree()
                End Function
 
                Friend Overrides Function CreateAssemblySymbol() As AssemblySymbol
                    Return New RetargetingAssemblySymbol(Compilation.SourceAssembly, IsLinked)
                End Function
 
                Protected Overrides Sub AddAvailableSymbols(assemblies As ArrayBuilder(Of AssemblySymbol))
                    assemblies.Add(Compilation.Assembly)
 
                    ' accessing cached symbols requires a lock
                    SyncLock SymbolCacheAndReferenceManagerStateGuard
                        Compilation.AddRetargetingAssemblySymbolsNoLock(assemblies)
                    End SyncLock
                End Sub
 
                Public Overrides Function IsMatchingAssembly(candidateAssembly As AssemblySymbol) As Boolean
                    Dim retargeting = TryCast(candidateAssembly, RetargetingAssemblySymbol)
                    Dim asm As AssemblySymbol
 
                    If retargeting IsNot Nothing Then
                        asm = retargeting.UnderlyingAssembly
                    Else
                        asm = TryCast(candidateAssembly, SourceAssemblySymbol)
                    End If
 
                    Debug.Assert(TypeOf asm IsNot RetargetingAssemblySymbol)
 
                    Return asm Is Compilation.Assembly
                End Function
 
                Public Overrides ReadOnly Property ContainsNoPiaLocalTypes As Boolean
                    Get
                        Return Compilation.MightContainNoPiaLocalTypes()
                    End Get
                End Property
 
                Public Overrides ReadOnly Property DeclaresTheObjectClass As Boolean
                    Get
                        Return Compilation.DeclaresTheObjectClass
                    End Get
                End Property
 
                Public Overrides ReadOnly Property SourceCompilation As Compilation
                    Get
                        Return Compilation
                    End Get
                End Property
            End Class
 
            ''' <summary>
            ''' For testing purposes only.
            ''' </summary>
            Friend Shared Function IsSourceAssemblySymbolCreated(compilation As VisualBasicCompilation) As Boolean
                Return compilation._lazyAssemblySymbol IsNot Nothing
            End Function
 
            ''' <summary>
            ''' For testing purposes only.
            ''' </summary>
            Friend Shared Function IsReferenceManagerInitialized(compilation As VisualBasicCompilation) As Boolean
                Return compilation._referenceManager.IsBound
            End Function
        End Class
    End Class
End Namespace