VisualBasicCompilation.vb 141.9 KB
Newer Older
1
' Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
P
Pilchie 已提交
2 3 4 5

Imports System.Collections.Concurrent
Imports System.Collections.Immutable
Imports System.IO
6
Imports System.Reflection.Metadata
P
Pilchie 已提交
7 8 9
Imports System.Runtime.InteropServices
Imports System.Threading
Imports System.Threading.Tasks
10
Imports Microsoft.Cci
P
Pilchie 已提交
11
Imports Microsoft.CodeAnalysis.CodeGen
12
Imports Microsoft.CodeAnalysis.Diagnostics
P
Pilchie 已提交
13
Imports Microsoft.CodeAnalysis.Emit
14
Imports Microsoft.CodeAnalysis.InternalUtilities
15
Imports Microsoft.CodeAnalysis.Operations
T
Tomas Matousek 已提交
16
Imports Microsoft.CodeAnalysis.PooledObjects
17
Imports Microsoft.CodeAnalysis.Symbols
P
Pilchie 已提交
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic

    ''' <summary>
    ''' The Compilation object is an immutable representation of a single invocation of the
    ''' compiler. Although immutable, a Compilation is also on-demand, in that a compilation can be
    ''' created quickly, but will that compiler parts or all of the code in order to respond to
    ''' method or properties. Also, a compilation can produce a new compilation with a small change
    ''' from the current compilation. This is, in many cases, more efficient than creating a new
    ''' compilation from scratch, as the new compilation can share information from the old
    ''' compilation.
    ''' </summary>
A
angocke 已提交
34
    Public NotInheritable Class VisualBasicCompilation
P
Pilchie 已提交
35 36 37 38 39 40 41 42 43 44
        Inherits Compilation

        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        '
        ' Changes to the public interface of this class should remain synchronized with the C#
        ' version. Do not make any changes to the public interface without making the corresponding
        ' change to the C# version.
        '
        ' !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

45 46 47 48
        ''' <summary>
        ''' most of time all compilation would use same MyTemplate. no reason to create (reparse) one for each compilation
        ''' as long as its parse option is same
        ''' </summary>
A
angocke 已提交
49 50
        Private Shared ReadOnly s_myTemplateCache As ConcurrentLruCache(Of VisualBasicParseOptions, SyntaxTree) =
            New ConcurrentLruCache(Of VisualBasicParseOptions, SyntaxTree)(capacity:=5)
51

P
Pilchie 已提交
52 53 54 55 56 57 58
        ''' <summary>
        ''' The SourceAssemblySymbol for this compilation. Do not access directly, use Assembly
        ''' property instead. This field is lazily initialized by ReferenceManager,
        ''' ReferenceManager.CacheLockObject must be locked while ReferenceManager "calculates" the
        ''' value and assigns it, several threads must not perform duplicate "calculation"
        ''' simultaneously.
        ''' </summary>
59
        Private _lazyAssemblySymbol As SourceAssemblySymbol
P
Pilchie 已提交
60 61 62 63 64 65 66 67

        ''' <summary>
        ''' Holds onto data related to reference binding.
        ''' The manager is shared among multiple compilations that we expect to have the same result of reference binding.
        ''' In most cases this can be determined without performing the binding. If the compilation however contains a circular 
        ''' metadata reference (a metadata reference that refers back to the compilation) we need to avoid sharing of the binding results.
        ''' We do so by creating a new reference manager for such compilation. 
        ''' </summary>
68
        Private _referenceManager As ReferenceManager
P
Pilchie 已提交
69 70 71 72

        ''' <summary>
        ''' The options passed to the constructor of the Compilation
        ''' </summary>
73
        Private ReadOnly _options As VisualBasicCompilationOptions
P
Pilchie 已提交
74 75 76 77

        ''' <summary>
        ''' The global namespace symbol. Lazily populated on first access.
        ''' </summary>
78
        Private _lazyGlobalNamespace As NamespaceSymbol
P
Pilchie 已提交
79 80 81 82

        ''' <summary>
        ''' The syntax trees explicitly given to the compilation at creation, in ordinal order.
        ''' </summary>
83
        Private ReadOnly _syntaxTrees As ImmutableArray(Of SyntaxTree)
P
Pilchie 已提交
84

85 86
        Private ReadOnly _syntaxTreeOrdinalMap As ImmutableDictionary(Of SyntaxTree, Integer)

P
Pilchie 已提交
87 88 89 90
        ''' <summary>
        ''' The syntax trees of this compilation plus all 'hidden' trees 
        ''' added to the compilation by compiler, e.g. Vb Core Runtime.
        ''' </summary>
91
        Private _lazyAllSyntaxTrees As ImmutableArray(Of SyntaxTree)
P
Pilchie 已提交
92 93 94 95 96

        ''' <summary>
        ''' A map between syntax trees and the root declarations in the declaration table.
        ''' Incrementally updated between compilation versions when source changes are made.
        ''' </summary>
97
        Private ReadOnly _rootNamespaces As ImmutableDictionary(Of SyntaxTree, DeclarationTableEntry)
P
Pilchie 已提交
98 99 100 101 102 103 104 105

        ''' <summary>
        ''' Imports appearing in <see cref="SyntaxTree"/>s in this compilation.
        ''' </summary>
        ''' <remarks>
        ''' Unlike in C#, we don't need to use a set because the <see cref="SourceFile"/> objects
        ''' that record the imports are persisted.
        ''' </remarks>
106
        Private _lazyImportInfos As ConcurrentQueue(Of ImportInfo)
P
Pilchie 已提交
107 108 109 110 111 112 113

        ''' <summary>
        ''' Cache the CLS diagnostics for the whole compilation so they aren't computed repeatedly.
        ''' </summary>
        ''' <remarks>
        ''' NOTE: Presently, we do not cache the per-tree diagnostics.
        ''' </remarks>
114
        Private _lazyClsComplianceDiagnostics As ImmutableArray(Of Diagnostic)
P
Pilchie 已提交
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132

        ''' <summary>
        ''' A SyntaxTree and the associated RootSingleNamespaceDeclaration for an embedded
        ''' syntax tree in the Compilation. Unlike the entries in m_rootNamespaces, the
        ''' SyntaxTree here is lazy since the tree cannot be evaluated until the references
        ''' have been resolved (as part of binding the source module), and at that point, the
        ''' SyntaxTree may be Nothing if the embedded tree is not needed for the Compilation.
        ''' </summary>
        Private Structure EmbeddedTreeAndDeclaration
            Public ReadOnly Tree As Lazy(Of SyntaxTree)
            Public ReadOnly DeclarationEntry As DeclarationTableEntry

            Public Sub New(treeOpt As Func(Of SyntaxTree), rootNamespaceOpt As Func(Of RootSingleNamespaceDeclaration))
                Me.Tree = New Lazy(Of SyntaxTree)(treeOpt)
                Me.DeclarationEntry = New DeclarationTableEntry(New Lazy(Of RootSingleNamespaceDeclaration)(rootNamespaceOpt), isEmbedded:=True)
            End Sub
        End Structure

133
        Private ReadOnly _embeddedTrees As ImmutableArray(Of EmbeddedTreeAndDeclaration)
P
Pilchie 已提交
134 135 136 137 138 139

        ''' <summary>
        ''' The declaration table that holds onto declarations from source. Incrementally updated
        ''' between compilation versions when source changes are made.
        ''' </summary>
        ''' <remarks></remarks>
140
        Private ReadOnly _declarationTable As DeclarationTable
P
Pilchie 已提交
141 142 143 144

        ''' <summary>
        ''' Manages anonymous types declared in this compilation. Unifies types that are structurally equivalent.
        ''' </summary>
145
        Private ReadOnly _anonymousTypeManager As AnonymousTypeManager
P
Pilchie 已提交
146 147 148 149

        ''' <summary>
        ''' Manages automatically embedded content.
        ''' </summary>
150
        Private _lazyEmbeddedSymbolManager As EmbeddedSymbolManager
P
Pilchie 已提交
151 152

        ''' <summary>
153
        ''' MyTemplate automatically embedded from resource in the compiler.
P
Pilchie 已提交
154 155 156 157 158 159
        ''' It doesn't feel like it should be managed by EmbeddedSymbolManager
        ''' because MyTemplate is treated as user code, i.e. can be extended via
        ''' partial declarations, doesn't require "on-demand" metadata generation, etc.
        ''' 
        ''' SyntaxTree.Dummy means uninitialized.
        ''' </summary>
160
        Private _lazyMyTemplate As SyntaxTree = VisualBasicSyntaxTree.Dummy
P
Pilchie 已提交
161

162
        Private ReadOnly _scriptClass As Lazy(Of ImplicitNamedTypeSymbol)
P
Pilchie 已提交
163 164 165 166

        ''' <summary>
        ''' Contains the main method of this assembly, if there is one.
        ''' </summary>
167
        Private _lazyEntryPoint As EntryPoint
P
Pilchie 已提交
168

169 170 171
        ''' <summary>
        ''' The set of trees for which a <see cref="CompilationUnitCompletedEvent"/> has been added to the queue.
        ''' </summary>
172
        Private _lazyCompilationUnitCompletedTrees As HashSet(Of SyntaxTree)
173

174 175 176
        ''' <summary>
        ''' The common language version among the trees of the compilation.
        ''' </summary>
177
        Private ReadOnly _languageVersion As LanguageVersion
178

P
Pilchie 已提交
179 180 181 182 183 184 185 186 187 188 189 190 191 192
        Public Overrides ReadOnly Property Language As String
            Get
                Return LanguageNames.VisualBasic
            End Get
        End Property

        Public Overrides ReadOnly Property IsCaseSensitive As Boolean
            Get
                Return False
            End Get
        End Property

        Friend ReadOnly Property Declarations As DeclarationTable
            Get
193
                Return _declarationTable
P
Pilchie 已提交
194 195 196
            End Get
        End Property

197 198 199 200 201 202
        Friend ReadOnly Property MergedRootDeclaration As MergedNamespaceDeclaration
            Get
                Return Declarations.GetMergedRoot(Me)
            End Get
        End Property

A
angocke 已提交
203
        Public Shadows ReadOnly Property Options As VisualBasicCompilationOptions
P
Pilchie 已提交
204
            Get
205
                Return _options
P
Pilchie 已提交
206 207 208
            End Get
        End Property

209 210 211 212 213
        ''' <summary>
        ''' The language version that was used to parse the syntax trees of this compilation.
        ''' </summary>
        Public ReadOnly Property LanguageVersion As LanguageVersion
            Get
214
                Return _languageVersion
215 216 217
            End Get
        End Property

P
Pilchie 已提交
218 219
        Friend ReadOnly Property AnonymousTypeManager As AnonymousTypeManager
            Get
220
                Return Me._anonymousTypeManager
P
Pilchie 已提交
221 222 223
            End Get
        End Property

224 225
        Friend Overrides ReadOnly Property CommonAnonymousTypeManager As CommonAnonymousTypeManager
            Get
226
                Return Me._anonymousTypeManager
227 228 229
            End Get
        End Property

P
Pilchie 已提交
230 231 232 233 234
        ''' <summary>
        ''' SyntaxTree of MyTemplate for the compilation. Settable for testing purposes only.
        ''' </summary>
        Friend Property MyTemplate As SyntaxTree
            Get
235
                If _lazyMyTemplate Is VisualBasicSyntaxTree.Dummy Then
236 237
                    Dim compilationOptions = Me.Options
                    If compilationOptions.EmbedVbCoreRuntime OrElse compilationOptions.SuppressEmbeddedDeclarations Then
238
                        _lazyMyTemplate = Nothing
P
Pilchie 已提交
239
                    Else
240
                        ' first see whether we can use one from global cache
241
                        Dim parseOptions = If(compilationOptions.ParseOptions, VisualBasicParseOptions.Default)
242 243

                        Dim tree As SyntaxTree = Nothing
244

245 246
                        If s_myTemplateCache.TryGetValue(parseOptions, tree) Then
                            Debug.Assert(tree IsNot Nothing)
A
angocke 已提交
247
                            Debug.Assert(tree IsNot VisualBasicSyntaxTree.Dummy)
248 249
                            Debug.Assert(tree.IsMyTemplate)

J
Jonathon Marolf 已提交
250
                            Interlocked.CompareExchange(_lazyMyTemplate, tree, VisualBasicSyntaxTree.Dummy)
251 252 253
                        Else
                            ' we need to make one.
                            Dim text As String = EmbeddedResources.VbMyTemplateText
254 255 256 257

                            ' The My template regularly makes use of more recent language features.  Care is
                            ' taken to ensure these are compatible with 2.0 runtimes so there is no danger
                            ' with allowing the newer syntax here.
G
gafter 已提交
258
                            Dim options = parseOptions.WithLanguageVersion(LanguageVersion.Default)
259
                            tree = VisualBasicSyntaxTree.ParseText(text, options:=options, isMyTemplate:=True)
260

261 262 263 264
                            If tree.GetDiagnostics().Any() Then
                                Throw ExceptionUtilities.Unreachable
                            End If

J
Jonathon Marolf 已提交
265
                            If Interlocked.CompareExchange(_lazyMyTemplate, tree, VisualBasicSyntaxTree.Dummy) Is VisualBasicSyntaxTree.Dummy Then
266 267 268
                                ' set global cache
                                s_myTemplateCache(parseOptions) = tree
                            End If
269
                        End If
P
Pilchie 已提交
270
                    End If
271
                    Debug.Assert(_lazyMyTemplate Is Nothing OrElse _lazyMyTemplate.IsMyTemplate)
P
Pilchie 已提交
272 273
                End If

274
                Return _lazyMyTemplate
P
Pilchie 已提交
275 276
            End Get
            Set(value As SyntaxTree)
277
                Debug.Assert(_lazyMyTemplate Is VisualBasicSyntaxTree.Dummy)
A
angocke 已提交
278
                Debug.Assert(value IsNot VisualBasicSyntaxTree.Dummy)
279
                Debug.Assert(value Is Nothing OrElse value.IsMyTemplate)
P
Pilchie 已提交
280

281 282 283 284
                If value?.GetDiagnostics().Any() Then
                    Throw ExceptionUtilities.Unreachable
                End If

285
                _lazyMyTemplate = value
P
Pilchie 已提交
286 287 288 289 290
            End Set
        End Property

        Friend ReadOnly Property EmbeddedSymbolManager As EmbeddedSymbolManager
            Get
291
                If _lazyEmbeddedSymbolManager Is Nothing Then
P
Pilchie 已提交
292 293 294 295 296
                    Dim embedded = If(Options.EmbedVbCoreRuntime, EmbeddedSymbolKind.VbCore, EmbeddedSymbolKind.None) Or
                                        If(IncludeInternalXmlHelper(), EmbeddedSymbolKind.XmlHelper, EmbeddedSymbolKind.None)
                    If embedded <> EmbeddedSymbolKind.None Then
                        embedded = embedded Or EmbeddedSymbolKind.EmbeddedAttribute
                    End If
297
                    Interlocked.CompareExchange(_lazyEmbeddedSymbolManager, New EmbeddedSymbolManager(embedded), Nothing)
P
Pilchie 已提交
298
                End If
299
                Return _lazyEmbeddedSymbolManager
P
Pilchie 已提交
300 301 302 303
            End Get
        End Property

#Region "Constructors and Factories"
304

P
Pilchie 已提交
305 306 307 308 309 310 311 312 313 314 315 316
        ''' <summary>
        ''' Create a new compilation from scratch.
        ''' </summary>
        ''' <param name="assemblyName">Simple assembly name.</param>
        ''' <param name="syntaxTrees">The syntax trees with the source code for the new compilation.</param>
        ''' <param name="references">The references for the new compilation.</param>
        ''' <param name="options">The compiler options to use.</param>
        ''' <returns>A new compilation.</returns>
        Public Shared Function Create(
            assemblyName As String,
            Optional syntaxTrees As IEnumerable(Of SyntaxTree) = Nothing,
            Optional references As IEnumerable(Of MetadataReference) = Nothing,
A
angocke 已提交
317 318
            Optional options As VisualBasicCompilationOptions = Nothing
        ) As VisualBasicCompilation
P
Pilchie 已提交
319 320 321 322 323 324 325 326 327 328 329 330 331
            Return Create(assemblyName,
                          options,
                          If(syntaxTrees IsNot Nothing, syntaxTrees.Cast(Of SyntaxTree), Nothing),
                          references,
                          previousSubmission:=Nothing,
                          returnType:=Nothing,
                          hostObjectType:=Nothing,
                          isSubmission:=False)
        End Function

        ''' <summary> 
        ''' Creates a new compilation that can be used in scripting. 
        ''' </summary>
332
        Friend Shared Function CreateScriptCompilation(
P
Pilchie 已提交
333 334 335
            assemblyName As String,
            Optional syntaxTree As SyntaxTree = Nothing,
            Optional references As IEnumerable(Of MetadataReference) = Nothing,
A
angocke 已提交
336
            Optional options As VisualBasicCompilationOptions = Nothing,
337
            Optional previousScriptCompilation As VisualBasicCompilation = Nothing,
P
Pilchie 已提交
338
            Optional returnType As Type = Nothing,
339
            Optional globalsType As Type = Nothing) As VisualBasicCompilation
P
Pilchie 已提交
340 341

            CheckSubmissionOptions(options)
342
            ValidateScriptCompilationParameters(previousScriptCompilation, returnType, globalsType)
P
Pilchie 已提交
343 344 345

            Return Create(
                assemblyName,
346
                If(options, New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary)).WithReferencesSupersedeLowerVersions(True),
347
                If((syntaxTree IsNot Nothing), {syntaxTree}, SpecializedCollections.EmptyEnumerable(Of SyntaxTree)()),
P
Pilchie 已提交
348
                references,
349
                previousScriptCompilation,
P
Pilchie 已提交
350
                returnType,
351
                globalsType,
P
Pilchie 已提交
352 353 354 355 356
                isSubmission:=True)
        End Function

        Private Shared Function Create(
            assemblyName As String,
A
angocke 已提交
357
            options As VisualBasicCompilationOptions,
P
Pilchie 已提交
358 359
            syntaxTrees As IEnumerable(Of SyntaxTree),
            references As IEnumerable(Of MetadataReference),
A
angocke 已提交
360
            previousSubmission As VisualBasicCompilation,
P
Pilchie 已提交
361 362 363
            returnType As Type,
            hostObjectType As Type,
            isSubmission As Boolean
A
angocke 已提交
364
        ) As VisualBasicCompilation
365 366
            Debug.Assert(Not isSubmission OrElse options.ReferencesSupersedeLowerVersions)

P
Pilchie 已提交
367
            If options Is Nothing Then
A
angocke 已提交
368
                options = New VisualBasicCompilationOptions(OutputKind.ConsoleApplication)
P
Pilchie 已提交
369 370 371 372
            End If

            Dim validatedReferences = ValidateReferences(Of VisualBasicCompilationReference)(references)

A
angocke 已提交
373 374
            Dim c As VisualBasicCompilation = Nothing
            Dim embeddedTrees = CreateEmbeddedTrees(New Lazy(Of VisualBasicCompilation)(Function() c))
P
Pilchie 已提交
375 376 377
            Dim declMap = ImmutableDictionary.Create(Of SyntaxTree, DeclarationTableEntry)()
            Dim declTable = AddEmbeddedTrees(DeclarationTable.Empty, embeddedTrees)

A
angocke 已提交
378
            c = New VisualBasicCompilation(
P
Pilchie 已提交
379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397
                assemblyName,
                options,
                validatedReferences,
                ImmutableArray(Of SyntaxTree).Empty,
                ImmutableDictionary.Create(Of SyntaxTree, Integer)(),
                declMap,
                embeddedTrees,
                declTable,
                previousSubmission,
                returnType,
                hostObjectType,
                isSubmission,
                referenceManager:=Nothing,
                reuseReferenceManager:=False)

            If syntaxTrees IsNot Nothing Then
                c = c.AddSyntaxTrees(syntaxTrees)
            End If

398
            Debug.Assert(c._lazyAssemblySymbol Is Nothing)
P
Pilchie 已提交
399 400 401 402 403 404

            Return c
        End Function

        Private Sub New(
            assemblyName As String,
A
angocke 已提交
405
            options As VisualBasicCompilationOptions,
P
Pilchie 已提交
406 407 408 409 410 411
            references As ImmutableArray(Of MetadataReference),
            syntaxTrees As ImmutableArray(Of SyntaxTree),
            syntaxTreeOrdinalMap As ImmutableDictionary(Of SyntaxTree, Integer),
            rootNamespaces As ImmutableDictionary(Of SyntaxTree, DeclarationTableEntry),
            embeddedTrees As ImmutableArray(Of EmbeddedTreeAndDeclaration),
            declarationTable As DeclarationTable,
A
angocke 已提交
412
            previousSubmission As VisualBasicCompilation,
P
Pilchie 已提交
413 414 415 416
            submissionReturnType As Type,
            hostObjectType As Type,
            isSubmission As Boolean,
            referenceManager As ReferenceManager,
417 418
            reuseReferenceManager As Boolean,
            Optional eventQueue As AsyncQueue(Of CompilationEvent) = Nothing
P
Pilchie 已提交
419
        )
420
            MyBase.New(assemblyName, references, SyntaxTreeCommonFeatures(syntaxTrees), isSubmission, eventQueue)
P
Pilchie 已提交
421

422 423
            Debug.Assert(rootNamespaces IsNot Nothing)
            Debug.Assert(declarationTable IsNot Nothing)
P
Pilchie 已提交
424

425 426
            Debug.Assert(syntaxTrees.All(Function(tree) syntaxTrees(syntaxTreeOrdinalMap(tree)) Is tree))
            Debug.Assert(syntaxTrees.SetEquals(rootNamespaces.Keys.AsImmutable(), EqualityComparer(Of SyntaxTree).Default))
427
            Debug.Assert(embeddedTrees.All(Function(treeAndDeclaration) declarationTable.Contains(treeAndDeclaration.DeclarationEntry)))
P
Pilchie 已提交
428

429 430
            _options = options
            _syntaxTrees = syntaxTrees
431
            _syntaxTreeOrdinalMap = syntaxTreeOrdinalMap
432 433 434 435 436
            _rootNamespaces = rootNamespaces
            _embeddedTrees = embeddedTrees
            _declarationTable = declarationTable
            _anonymousTypeManager = New AnonymousTypeManager(Me)
            _languageVersion = CommonLanguageVersion(syntaxTrees)
P
Pilchie 已提交
437

438
            _scriptClass = New Lazy(Of ImplicitNamedTypeSymbol)(AddressOf BindScriptClass)
P
Pilchie 已提交
439

440 441
            If isSubmission Then
                Debug.Assert(previousSubmission Is Nothing OrElse previousSubmission.HostObjectType Is hostObjectType)
442
                Me.ScriptCompilationInfo = New VisualBasicScriptCompilationInfo(previousSubmission, submissionReturnType, hostObjectType)
443 444 445
            Else
                Debug.Assert(previousSubmission Is Nothing AndAlso submissionReturnType Is Nothing AndAlso hostObjectType Is Nothing)
            End If
P
Pilchie 已提交
446

447 448
            If reuseReferenceManager Then
                referenceManager.AssertCanReuseForCompilation(Me)
449
                _referenceManager = referenceManager
450
            Else
451
                _referenceManager = New ReferenceManager(MakeSourceAssemblySimpleName(),
P
Pilchie 已提交
452 453
                                                              options.AssemblyIdentityComparer,
                                                              If(referenceManager IsNot Nothing, referenceManager.ObservedMetadata, Nothing))
454
            End If
P
Pilchie 已提交
455

456
            Debug.Assert(_lazyAssemblySymbol Is Nothing)
457
            If Me.EventQueue IsNot Nothing Then
458
                Me.EventQueue.TryEnqueue(New CompilationStartedEvent(Me))
459
            End If
P
Pilchie 已提交
460 461
        End Sub

462 463 464 465 466 467 468 469 470 471
        Friend Overrides Sub ValidateDebugEntryPoint(debugEntryPoint As IMethodSymbol, diagnostics As DiagnosticBag)
            Debug.Assert(debugEntryPoint IsNot Nothing)

            ' Debug entry point has to be a method definition from this compilation.
            Dim methodSymbol = TryCast(debugEntryPoint, MethodSymbol)
            If methodSymbol?.DeclaringCompilation IsNot Me OrElse Not methodSymbol.IsDefinition Then
                diagnostics.Add(ERRID.ERR_DebugEntryPointNotSourceMethodDefinition, Location.None)
            End If
        End Sub

472 473 474 475 476
        Private Function CommonLanguageVersion(syntaxTrees As ImmutableArray(Of SyntaxTree)) As LanguageVersion
            ' We don't check m_Options.ParseOptions.LanguageVersion for consistency, because
            ' it isn't consistent in practice.  In fact sometimes m_Options.ParseOptions is Nothing.
            Dim result As LanguageVersion? = Nothing
            For Each tree In syntaxTrees
A
angocke 已提交
477
                Dim version = CType(tree.Options, VisualBasicParseOptions).LanguageVersion
478 479 480
                If result Is Nothing Then
                    result = version
                ElseIf result <> version Then
481
                    Throw New ArgumentException(CodeAnalysisResources.InconsistentLanguageVersions, NameOf(syntaxTrees))
482 483 484
                End If
            Next

485
            Return If(result, LanguageVersion.Default.MapSpecifiedToEffectiveVersion)
486 487
        End Function

P
Pilchie 已提交
488 489 490
        ''' <summary>
        ''' Create a duplicate of this compilation with different symbol instances
        ''' </summary>
A
angocke 已提交
491 492
        Public Shadows Function Clone() As VisualBasicCompilation
            Return New VisualBasicCompilation(
P
Pilchie 已提交
493
                Me.AssemblyName,
494
                _options,
P
Pilchie 已提交
495
                Me.ExternalReferences,
496
                _syntaxTrees,
497
                _syntaxTreeOrdinalMap,
498 499 500
                _rootNamespaces,
                _embeddedTrees,
                _declarationTable,
501
                Me.PreviousSubmission,
P
Pilchie 已提交
502 503 504
                Me.SubmissionReturnType,
                Me.HostObjectType,
                Me.IsSubmission,
505
                _referenceManager,
506 507
                reuseReferenceManager:=True,
                eventQueue:=Nothing) ' no event queue when cloning
P
Pilchie 已提交
508 509 510 511 512 513 514
        End Function

        Private Function UpdateSyntaxTrees(
            syntaxTrees As ImmutableArray(Of SyntaxTree),
            syntaxTreeOrdinalMap As ImmutableDictionary(Of SyntaxTree, Integer),
            rootNamespaces As ImmutableDictionary(Of SyntaxTree, DeclarationTableEntry),
            declarationTable As DeclarationTable,
A
angocke 已提交
515
            referenceDirectivesChanged As Boolean) As VisualBasicCompilation
P
Pilchie 已提交
516

A
angocke 已提交
517
            Return New VisualBasicCompilation(
P
Pilchie 已提交
518
                Me.AssemblyName,
519
                _options,
P
Pilchie 已提交
520 521 522 523
                Me.ExternalReferences,
                syntaxTrees,
                syntaxTreeOrdinalMap,
                rootNamespaces,
524
                _embeddedTrees,
P
Pilchie 已提交
525
                declarationTable,
526
                Me.PreviousSubmission,
P
Pilchie 已提交
527 528 529
                Me.SubmissionReturnType,
                Me.HostObjectType,
                Me.IsSubmission,
530
                _referenceManager,
P
Pilchie 已提交
531 532 533 534 535 536
                reuseReferenceManager:=Not referenceDirectivesChanged)
        End Function

        ''' <summary>
        ''' Creates a new compilation with the specified name.
        ''' </summary>
A
angocke 已提交
537
        Public Shadows Function WithAssemblyName(assemblyName As String) As VisualBasicCompilation
P
Pilchie 已提交
538 539 540 541
            ' Can't reuse references since the source assembly name changed and the referenced symbols might 
            ' have internals-visible-to relationship with this compilation or they might had a circular reference 
            ' to this compilation.

A
angocke 已提交
542
            Return New VisualBasicCompilation(
P
Pilchie 已提交
543 544 545
                assemblyName,
                Me.Options,
                Me.ExternalReferences,
546
                _syntaxTrees,
547
                _syntaxTreeOrdinalMap,
548 549 550
                _rootNamespaces,
                _embeddedTrees,
                _declarationTable,
551
                Me.PreviousSubmission,
P
Pilchie 已提交
552 553 554
                Me.SubmissionReturnType,
                Me.HostObjectType,
                Me.IsSubmission,
555
                _referenceManager,
P
Pilchie 已提交
556 557 558
                reuseReferenceManager:=String.Equals(assemblyName, Me.AssemblyName, StringComparison.Ordinal))
        End Function

A
angocke 已提交
559
        Public Shadows Function WithReferences(ParamArray newReferences As MetadataReference()) As VisualBasicCompilation
P
Pilchie 已提交
560 561 562 563 564 565 566
            Return WithReferences(DirectCast(newReferences, IEnumerable(Of MetadataReference)))
        End Function

        ''' <summary>
        ''' Creates a new compilation with the specified references.
        ''' </summary>
        ''' <remarks>
A
angocke 已提交
567
        ''' The new <see cref="VisualBasicCompilation"/> will query the given <see cref="MetadataReference"/> for the underlying 
P
Pilchie 已提交
568 569 570 571 572 573
        ''' metadata as soon as the are needed. 
        ''' 
        ''' The New compilation uses whatever metadata is currently being provided by the <see cref="MetadataReference"/>.
        ''' E.g. if the current compilation references a metadata file that has changed since the creation of the compilation
        ''' the New compilation is going to use the updated version, while the current compilation will be using the previous (it doesn't change).
        ''' </remarks>
A
angocke 已提交
574
        Public Shadows Function WithReferences(newReferences As IEnumerable(Of MetadataReference)) As VisualBasicCompilation
575
            Dim declTable = RemoveEmbeddedTrees(_declarationTable, _embeddedTrees)
A
angocke 已提交
576 577
            Dim c As VisualBasicCompilation = Nothing
            Dim embeddedTrees = CreateEmbeddedTrees(New Lazy(Of VisualBasicCompilation)(Function() c))
P
Pilchie 已提交
578 579 580 581 582
            declTable = AddEmbeddedTrees(declTable, embeddedTrees)

            ' References might have changed, don't reuse reference manager.
            ' Don't even reuse observed metadata - let the manager query for the metadata again.

A
angocke 已提交
583
            c = New VisualBasicCompilation(
P
Pilchie 已提交
584 585 586
                Me.AssemblyName,
                Me.Options,
                ValidateReferences(Of VisualBasicCompilationReference)(newReferences),
587
                _syntaxTrees,
588
                _syntaxTreeOrdinalMap,
589
                _rootNamespaces,
P
Pilchie 已提交
590 591
                embeddedTrees,
                declTable,
592
                Me.PreviousSubmission,
P
Pilchie 已提交
593 594 595 596 597 598 599 600
                Me.SubmissionReturnType,
                Me.HostObjectType,
                Me.IsSubmission,
                referenceManager:=Nothing,
                reuseReferenceManager:=False)
            Return c
        End Function

A
angocke 已提交
601
        Public Shadows Function WithOptions(newOptions As VisualBasicCompilationOptions) As VisualBasicCompilation
P
Pilchie 已提交
602
            If newOptions Is Nothing Then
603
                Throw New ArgumentNullException(NameOf(newOptions))
P
Pilchie 已提交
604 605
            End If

A
angocke 已提交
606
            Dim c As VisualBasicCompilation = Nothing
607 608 609
            Dim embeddedTrees = _embeddedTrees
            Dim declTable = _declarationTable
            Dim declMap = Me._rootNamespaces
P
Pilchie 已提交
610 611 612 613 614 615 616 617 618 619 620

            If Not String.Equals(Me.Options.RootNamespace, newOptions.RootNamespace, StringComparison.Ordinal) Then
                ' If the root namespace was updated we have to update declaration table 
                ' entries for all the syntax trees of the compilation
                '
                ' NOTE: we use case-sensitive comparison so that the new compilation
                '       gets a root namespace with correct casing

                declMap = ImmutableDictionary.Create(Of SyntaxTree, DeclarationTableEntry)()
                declTable = DeclarationTable.Empty

A
angocke 已提交
621
                embeddedTrees = CreateEmbeddedTrees(New Lazy(Of VisualBasicCompilation)(Function() c))
P
Pilchie 已提交
622 623 624 625
                declTable = AddEmbeddedTrees(declTable, embeddedTrees)

                Dim discardedReferenceDirectivesChanged As Boolean = False

626
                For Each tree In _syntaxTrees
P
Pilchie 已提交
627 628 629 630
                    AddSyntaxTreeToDeclarationMapAndTable(tree, newOptions, Me.IsSubmission, declMap, declTable, discardedReferenceDirectivesChanged) ' declMap and declTable passed ByRef
                Next

            ElseIf Me.Options.EmbedVbCoreRuntime <> newOptions.EmbedVbCoreRuntime OrElse Me.Options.ParseOptions <> newOptions.ParseOptions Then
631
                declTable = RemoveEmbeddedTrees(declTable, _embeddedTrees)
A
angocke 已提交
632
                embeddedTrees = CreateEmbeddedTrees(New Lazy(Of VisualBasicCompilation)(Function() c))
P
Pilchie 已提交
633 634 635
                declTable = AddEmbeddedTrees(declTable, embeddedTrees)
            End If

A
angocke 已提交
636
            c = New VisualBasicCompilation(
P
Pilchie 已提交
637 638 639
                Me.AssemblyName,
                newOptions,
                Me.ExternalReferences,
640
                _syntaxTrees,
641
                _syntaxTreeOrdinalMap,
P
Pilchie 已提交
642 643 644
                declMap,
                embeddedTrees,
                declTable,
645
                Me.PreviousSubmission,
P
Pilchie 已提交
646 647 648
                Me.SubmissionReturnType,
                Me.HostObjectType,
                Me.IsSubmission,
649 650
                _referenceManager,
                reuseReferenceManager:=_options.CanReuseCompilationReferenceManager(newOptions))
P
Pilchie 已提交
651 652 653 654 655 656
            Return c
        End Function

        ''' <summary>
        ''' Returns a new compilation with the given compilation set as the previous submission. 
        ''' </summary>
657 658 659
        Friend Shadows Function WithScriptCompilationInfo(info As VisualBasicScriptCompilationInfo) As VisualBasicCompilation
            If info Is ScriptCompilationInfo Then
                Return Me
P
Pilchie 已提交
660 661 662 663
            End If

            ' Reference binding doesn't depend on previous submission so we can reuse it.

A
angocke 已提交
664
            Return New VisualBasicCompilation(
P
Pilchie 已提交
665 666 667
                Me.AssemblyName,
                Me.Options,
                Me.ExternalReferences,
668
                _syntaxTrees,
669
                _syntaxTreeOrdinalMap,
670 671 672
                _rootNamespaces,
                _embeddedTrees,
                _declarationTable,
673
                info?.PreviousScriptCompilation,
674
                info?.ReturnTypeOpt,
675 676
                info?.GlobalsType,
                info IsNot Nothing,
677
                _referenceManager,
P
Pilchie 已提交
678 679 680
                reuseReferenceManager:=True)
        End Function

681
        ''' <summary>
682
        ''' Returns a new compilation with a given event queue.
683
        ''' </summary>
684
        Friend Overrides Function WithEventQueue(eventQueue As AsyncQueue(Of CompilationEvent)) As Compilation
A
angocke 已提交
685
            Return New VisualBasicCompilation(
686 687 688
                Me.AssemblyName,
                Me.Options,
                Me.ExternalReferences,
689
                _syntaxTrees,
690
                _syntaxTreeOrdinalMap,
691 692 693
                _rootNamespaces,
                _embeddedTrees,
                _declarationTable,
694
                Me.PreviousSubmission,
695 696 697
                Me.SubmissionReturnType,
                Me.HostObjectType,
                Me.IsSubmission,
698
                _referenceManager,
699 700 701 702
                reuseReferenceManager:=True,
                eventQueue:=eventQueue)
        End Function

P
Pilchie 已提交
703 704 705 706
#End Region

#Region "Submission"

707 708 709 710 711 712 713 714
        Friend Shadows ReadOnly Property ScriptCompilationInfo As VisualBasicScriptCompilationInfo

        Friend Overrides ReadOnly Property CommonScriptCompilationInfo As ScriptCompilationInfo
            Get
                Return ScriptCompilationInfo
            End Get
        End Property

A
angocke 已提交
715
        Friend Shadows ReadOnly Property PreviousSubmission As VisualBasicCompilation
P
Pilchie 已提交
716
            Get
717
                Return ScriptCompilationInfo?.PreviousScriptCompilation
P
Pilchie 已提交
718 719 720
            End Get
        End Property

721
        Friend Overrides Function HasSubmissionResult() As Boolean
722
            Debug.Assert(IsSubmission)
P
Pilchie 已提交
723

724
            ' submission can be empty or comprise of a script file
P
Pilchie 已提交
725
            Dim tree = SyntaxTrees.SingleOrDefault()
726 727 728 729 730 731 732 733
            If tree Is Nothing Then
                Return False
            End If

            Dim root = tree.GetCompilationUnitRoot()
            If root.HasErrors Then
                Return False
            End If
P
Pilchie 已提交
734

T
Tomas Matousek 已提交
735 736 737
            ' TODO: look for return statements
            ' https://github.com/dotnet/roslyn/issues/5773

738
            Dim lastStatement = root.Members.LastOrDefault()
P
Pilchie 已提交
739
            If lastStatement Is Nothing Then
740
                Return False
P
Pilchie 已提交
741 742 743 744 745 746 747
            End If

            Dim model = GetSemanticModel(tree)
            Select Case lastStatement.Kind
                Case SyntaxKind.PrintStatement
                    Dim expression = DirectCast(lastStatement, PrintStatementSyntax).Expression
                    Dim info = model.GetTypeInfo(expression)
748 749
                    ' always true, even for info.Type = Void
                    Return True
P
Pilchie 已提交
750 751 752 753

                Case SyntaxKind.ExpressionStatement
                    Dim expression = DirectCast(lastStatement, ExpressionStatementSyntax).Expression
                    Dim info = model.GetTypeInfo(expression)
754
                    Return info.Type.SpecialType <> SpecialType.System_Void
P
Pilchie 已提交
755 756 757 758

                Case SyntaxKind.CallStatement
                    Dim expression = DirectCast(lastStatement, CallStatementSyntax).Invocation
                    Dim info = model.GetTypeInfo(expression)
759
                    Return info.Type.SpecialType <> SpecialType.System_Void
P
Pilchie 已提交
760 761

                Case Else
762
                    Return False
P
Pilchie 已提交
763 764 765
            End Select
        End Function

C
Charles Stoner 已提交
766 767 768 769 770 771
        Friend Function GetSubmissionInitializer() As SynthesizedInteractiveInitializerMethod
            Return If(IsSubmission AndAlso ScriptClass IsNot Nothing,
                ScriptClass.GetScriptInitializer(),
                Nothing)
        End Function

P
Pilchie 已提交
772 773 774 775 776 777 778 779 780
#End Region

#Region "Syntax Trees"

        ''' <summary>
        ''' Get a read-only list of the syntax trees that this compilation was created with.
        ''' </summary>
        Public Shadows ReadOnly Property SyntaxTrees As ImmutableArray(Of SyntaxTree)
            Get
781
                Return _syntaxTrees
P
Pilchie 已提交
782 783 784 785 786 787 788 789 790
            End Get
        End Property

        ''' <summary>
        ''' Get a read-only list of the syntax trees that this compilation was created with PLUS
        ''' the trees that were automatically added to it, i.e. Vb Core Runtime tree.
        ''' </summary>
        Friend Shadows ReadOnly Property AllSyntaxTrees As ImmutableArray(Of SyntaxTree)
            Get
791
                If _lazyAllSyntaxTrees.IsDefault Then
P
Pilchie 已提交
792
                    Dim builder = ArrayBuilder(Of SyntaxTree).GetInstance()
793
                    builder.AddRange(_syntaxTrees)
794
                    For Each embeddedTree In _embeddedTrees
P
Pilchie 已提交
795 796 797 798 799
                        Dim tree = embeddedTree.Tree.Value
                        If tree IsNot Nothing Then
                            builder.Add(tree)
                        End If
                    Next
800
                    ImmutableInterlocked.InterlockedInitialize(_lazyAllSyntaxTrees, builder.ToImmutableAndFree())
P
Pilchie 已提交
801 802
                End If

803
                Return _lazyAllSyntaxTrees
P
Pilchie 已提交
804 805 806 807 808 809 810 811
            End Get
        End Property

        ''' <summary>
        ''' Is the passed in syntax tree in this compilation?
        ''' </summary>
        Public Shadows Function ContainsSyntaxTree(syntaxTree As SyntaxTree) As Boolean
            If syntaxTree Is Nothing Then
812
                Throw New ArgumentNullException(NameOf(syntaxTree))
P
Pilchie 已提交
813 814
            End If

815
            Dim vbtree = syntaxTree
816
            Return vbtree IsNot Nothing AndAlso _rootNamespaces.ContainsKey(vbtree)
P
Pilchie 已提交
817 818
        End Function

A
angocke 已提交
819
        Public Shadows Function AddSyntaxTrees(ParamArray trees As SyntaxTree()) As VisualBasicCompilation
P
Pilchie 已提交
820 821 822
            Return AddSyntaxTrees(DirectCast(trees, IEnumerable(Of SyntaxTree)))
        End Function

A
angocke 已提交
823
        Public Shadows Function AddSyntaxTrees(trees As IEnumerable(Of SyntaxTree)) As VisualBasicCompilation
824
            If trees Is Nothing Then
825
                Throw New ArgumentNullException(NameOf(trees))
826
            End If
P
Pilchie 已提交
827

828 829 830
            If Not trees.Any() Then
                Return Me
            End If
P
Pilchie 已提交
831

832 833 834 835 836 837 838
            ' We're using a try-finally for this builder because there's a test that 
            ' specifically checks for one or more of the argument exceptions below
            ' and we don't want to see console spew (even though we don't generally
            ' care about pool "leaks" in exceptional cases).  Alternatively, we
            ' could create a new ArrayBuilder.
            Dim builder = ArrayBuilder(Of SyntaxTree).GetInstance()
            Try
839
                builder.AddRange(_syntaxTrees)
P
Pilchie 已提交
840

841
                Dim referenceDirectivesChanged = False
842
                Dim oldTreeCount = _syntaxTrees.Length
P
Pilchie 已提交
843

844
                Dim ordinalMap = _syntaxTreeOrdinalMap
845 846
                Dim declMap = _rootNamespaces
                Dim declTable = _declarationTable
847
                Dim i = 0
P
Pilchie 已提交
848

849 850 851 852
                For Each tree As SyntaxTree In trees
                    If tree Is Nothing Then
                        Throw New ArgumentNullException(String.Format(VBResources.Trees0, i))
                    End If
P
Pilchie 已提交
853

854 855 856
                    If Not tree.HasCompilationUnitRoot Then
                        Throw New ArgumentException(String.Format(VBResources.TreesMustHaveRootNode, i))
                    End If
P
Pilchie 已提交
857

858 859
                    If tree.IsEmbeddedOrMyTemplateTree() Then
                        Throw New ArgumentException(VBResources.CannotAddCompilerSpecialTree)
P
Pilchie 已提交
860 861
                    End If

862 863 864 865
                    If declMap.ContainsKey(tree) Then
                        Throw New ArgumentException(VBResources.SyntaxTreeAlreadyPresent, String.Format(VBResources.Trees0, i))
                    End If

866
                    AddSyntaxTreeToDeclarationMapAndTable(tree, _options, Me.IsSubmission, declMap, declTable, referenceDirectivesChanged) ' declMap and declTable passed ByRef
867 868 869 870 871 872
                    builder.Add(tree)
                    ordinalMap = ordinalMap.Add(tree, oldTreeCount + i)
                    i += 1
                Next

                If IsSubmission AndAlso declMap.Count > 1 Then
873
                    Throw New ArgumentException(VBResources.SubmissionCanHaveAtMostOneSyntaxTree, NameOf(trees))
874 875 876 877 878 879
                End If

                Return UpdateSyntaxTrees(builder.ToImmutable(), ordinalMap, declMap, declTable, referenceDirectivesChanged)
            Finally
                builder.Free()
            End Try
P
Pilchie 已提交
880 881 882 883
        End Function

        Private Shared Sub AddSyntaxTreeToDeclarationMapAndTable(
                tree As SyntaxTree,
A
angocke 已提交
884
                compilationOptions As VisualBasicCompilationOptions,
P
Pilchie 已提交
885 886 887 888 889 890 891
                isSubmission As Boolean,
                ByRef declMap As ImmutableDictionary(Of SyntaxTree, DeclarationTableEntry),
                ByRef declTable As DeclarationTable,
                ByRef referenceDirectivesChanged As Boolean
            )

            Dim entry = New DeclarationTableEntry(New Lazy(Of RootSingleNamespaceDeclaration)(Function() ForTree(tree, compilationOptions, isSubmission)), isEmbedded:=False)
892
            declMap = declMap.Add(tree, entry) ' Callers are responsible for checking for existing entries.
P
Pilchie 已提交
893 894 895 896
            declTable = declTable.AddRootDeclaration(entry)
            referenceDirectivesChanged = referenceDirectivesChanged OrElse tree.HasReferenceDirectives
        End Sub

A
angocke 已提交
897
        Private Shared Function ForTree(tree As SyntaxTree, options As VisualBasicCompilationOptions, isSubmission As Boolean) As RootSingleNamespaceDeclaration
P
Pilchie 已提交
898 899 900
            Return DeclarationTreeBuilder.ForTree(tree, options.GetRootNamespaceParts(), If(options.ScriptClassName, ""), isSubmission)
        End Function

A
angocke 已提交
901
        Public Shadows Function RemoveSyntaxTrees(ParamArray trees As SyntaxTree()) As VisualBasicCompilation
P
Pilchie 已提交
902 903 904
            Return RemoveSyntaxTrees(DirectCast(trees, IEnumerable(Of SyntaxTree)))
        End Function

A
angocke 已提交
905
        Public Shadows Function RemoveSyntaxTrees(trees As IEnumerable(Of SyntaxTree)) As VisualBasicCompilation
906
            If trees Is Nothing Then
907
                Throw New ArgumentNullException(NameOf(trees))
908
            End If
P
Pilchie 已提交
909

910 911 912
            If Not trees.Any() Then
                Return Me
            End If
P
Pilchie 已提交
913

914 915
            Dim referenceDirectivesChanged = False
            Dim removeSet As New HashSet(Of SyntaxTree)()
916 917
            Dim declMap = _rootNamespaces
            Dim declTable = _declarationTable
P
Pilchie 已提交
918

919 920 921 922
            For Each tree As SyntaxTree In trees
                If tree.IsEmbeddedOrMyTemplateTree() Then
                    Throw New ArgumentException(VBResources.CannotRemoveCompilerSpecialTree)
                End If
P
Pilchie 已提交
923

924 925 926
                RemoveSyntaxTreeFromDeclarationMapAndTable(tree, declMap, declTable, referenceDirectivesChanged)
                removeSet.Add(tree)
            Next
P
Pilchie 已提交
927

928
            Debug.Assert(removeSet.Count > 0)
P
Pilchie 已提交
929

930 931 932
            ' We're going to have to revise the ordinals of all
            ' trees after the first one removed, so just build
            ' a new map.
P
Pilchie 已提交
933

934 935 936
            ' CONSIDER: an alternative approach would be to set the map to empty and
            ' re-calculate it the next time we need it.  This might save us time in the
            ' case where remove calls are made sequentially (rare?).
P
Pilchie 已提交
937

938 939 940
            Dim ordinalMap = ImmutableDictionary.Create(Of SyntaxTree, Integer)()
            Dim builder = ArrayBuilder(Of SyntaxTree).GetInstance()
            Dim i = 0
P
Pilchie 已提交
941

942
            For Each tree In _syntaxTrees
943 944 945 946 947 948
                If Not removeSet.Contains(tree) Then
                    builder.Add(tree)
                    ordinalMap = ordinalMap.Add(tree, i)
                    i += 1
                End If
            Next
P
Pilchie 已提交
949

950
            Return UpdateSyntaxTrees(builder.ToImmutableAndFree(), ordinalMap, declMap, declTable, referenceDirectivesChanged)
P
Pilchie 已提交
951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968
        End Function

        Private Shared Sub RemoveSyntaxTreeFromDeclarationMapAndTable(
                tree As SyntaxTree,
                ByRef declMap As ImmutableDictionary(Of SyntaxTree, DeclarationTableEntry),
            ByRef declTable As DeclarationTable,
            ByRef referenceDirectivesChanged As Boolean
            )
            Dim root As DeclarationTableEntry = Nothing
            If Not declMap.TryGetValue(tree, root) Then
                Throw New ArgumentException(String.Format(VBResources.SyntaxTreeNotFoundToRemove, tree))
            End If

            declTable = declTable.RemoveRootDeclaration(root)
            declMap = declMap.Remove(tree)
            referenceDirectivesChanged = referenceDirectivesChanged OrElse tree.HasReferenceDirectives
        End Sub

A
angocke 已提交
969
        Public Shadows Function RemoveAllSyntaxTrees() As VisualBasicCompilation
P
Pilchie 已提交
970 971 972
            Return UpdateSyntaxTrees(ImmutableArray(Of SyntaxTree).Empty,
                                     ImmutableDictionary.Create(Of SyntaxTree, Integer)(),
                                     ImmutableDictionary.Create(Of SyntaxTree, DeclarationTableEntry)(),
973
                                     AddEmbeddedTrees(DeclarationTable.Empty, _embeddedTrees),
974
                                     referenceDirectivesChanged:=_declarationTable.ReferenceDirectives.Any())
P
Pilchie 已提交
975 976
        End Function

A
angocke 已提交
977
        Public Shadows Function ReplaceSyntaxTree(oldTree As SyntaxTree, newTree As SyntaxTree) As VisualBasicCompilation
978
            If oldTree Is Nothing Then
979
                Throw New ArgumentNullException(NameOf(oldTree))
980
            End If
P
Pilchie 已提交
981

982 983 984 985 986
            If newTree Is Nothing Then
                Return Me.RemoveSyntaxTrees(oldTree)
            ElseIf newTree Is oldTree Then
                Return Me
            End If
P
Pilchie 已提交
987

988
            If Not newTree.HasCompilationUnitRoot Then
989
                Throw New ArgumentException(VBResources.TreeMustHaveARootNodeWithCompilationUnit, NameOf(newTree))
990
            End If
P
Pilchie 已提交
991

992 993
            Dim vbOldTree = oldTree
            Dim vbNewTree = newTree
P
Pilchie 已提交
994

995 996 997
            If vbOldTree.IsEmbeddedOrMyTemplateTree() Then
                Throw New ArgumentException(VBResources.CannotRemoveCompilerSpecialTree)
            End If
P
Pilchie 已提交
998

999 1000 1001
            If vbNewTree.IsEmbeddedOrMyTemplateTree() Then
                Throw New ArgumentException(VBResources.CannotAddCompilerSpecialTree)
            End If
P
Pilchie 已提交
1002

1003
            Dim declMap = _rootNamespaces
1004 1005 1006 1007 1008

            If declMap.ContainsKey(vbNewTree) Then
                Throw New ArgumentException(VBResources.SyntaxTreeAlreadyPresent, NameOf(newTree))
            End If

1009
            Dim declTable = _declarationTable
1010
            Dim referenceDirectivesChanged = False
P
Pilchie 已提交
1011

1012 1013 1014
            ' TODO(tomat): Consider comparing #r's of the old and the new tree. If they are exactly the same we could still reuse.
            ' This could be a perf win when editing a script file in the IDE. The services create a new compilation every keystroke 
            ' that replaces the tree with a new one.
P
Pilchie 已提交
1015

1016
            RemoveSyntaxTreeFromDeclarationMapAndTable(vbOldTree, declMap, declTable, referenceDirectivesChanged)
1017
            AddSyntaxTreeToDeclarationMapAndTable(vbNewTree, _options, Me.IsSubmission, declMap, declTable, referenceDirectivesChanged)
P
Pilchie 已提交
1018

1019
            Dim ordinalMap = _syntaxTreeOrdinalMap
P
Pilchie 已提交
1020

1021 1022
            Debug.Assert(ordinalMap.ContainsKey(oldTree)) ' Checked by RemoveSyntaxTreeFromDeclarationMapAndTable
            Dim oldOrdinal = ordinalMap(oldTree)
P
Pilchie 已提交
1023

1024
            Dim newArray = _syntaxTrees.ToArray()
1025
            newArray(oldOrdinal) = vbNewTree
P
Pilchie 已提交
1026

1027 1028 1029
            ' CONSIDER: should this be an operation on ImmutableDictionary?
            ordinalMap = ordinalMap.Remove(oldTree)
            ordinalMap = ordinalMap.Add(newTree, oldOrdinal)
P
Pilchie 已提交
1030

1031
            Return UpdateSyntaxTrees(newArray.AsImmutableOrNull(), ordinalMap, declMap, declTable, referenceDirectivesChanged)
P
Pilchie 已提交
1032 1033
        End Function

A
angocke 已提交
1034
        Private Shared Function CreateEmbeddedTrees(compReference As Lazy(Of VisualBasicCompilation)) As ImmutableArray(Of EmbeddedTreeAndDeclaration)
1035
            Return ImmutableArray.Create(
P
Pilchie 已提交
1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
                New EmbeddedTreeAndDeclaration(
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.Options.EmbedVbCoreRuntime Or compilation.IncludeInternalXmlHelper,
                                  EmbeddedSymbolManager.EmbeddedSyntax,
                                  Nothing)
                    End Function,
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.Options.EmbedVbCoreRuntime Or compilation.IncludeInternalXmlHelper,
1046
                                  ForTree(EmbeddedSymbolManager.EmbeddedSyntax, compilation.Options, isSubmission:=False),
P
Pilchie 已提交
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058
                                  Nothing)
                    End Function),
                New EmbeddedTreeAndDeclaration(
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.Options.EmbedVbCoreRuntime,
                                  EmbeddedSymbolManager.VbCoreSyntaxTree,
                                  Nothing)
                    End Function,
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.Options.EmbedVbCoreRuntime,
1059
                                  ForTree(EmbeddedSymbolManager.VbCoreSyntaxTree, compilation.Options, isSubmission:=False),
P
Pilchie 已提交
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071
                                  Nothing)
                    End Function),
                New EmbeddedTreeAndDeclaration(
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.IncludeInternalXmlHelper(),
                                  EmbeddedSymbolManager.InternalXmlHelperSyntax,
                                  Nothing)
                    End Function,
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.IncludeInternalXmlHelper(),
1072
                                  ForTree(EmbeddedSymbolManager.InternalXmlHelperSyntax, compilation.Options, isSubmission:=False),
P
Pilchie 已提交
1073 1074 1075 1076 1077 1078 1079 1080 1081 1082
                                  Nothing)
                    End Function),
                New EmbeddedTreeAndDeclaration(
                    Function()
                        Dim compilation = compReference.Value
                        Return compilation.MyTemplate
                    End Function,
                    Function()
                        Dim compilation = compReference.Value
                        Return If(compilation.MyTemplate IsNot Nothing,
1083
                                  ForTree(compilation.MyTemplate, compilation.Options, isSubmission:=False),
P
Pilchie 已提交
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111
                                  Nothing)
                    End Function))
        End Function

        Private Shared Function AddEmbeddedTrees(
            declTable As DeclarationTable,
            embeddedTrees As ImmutableArray(Of EmbeddedTreeAndDeclaration)
        ) As DeclarationTable

            For Each embeddedTree In embeddedTrees
                declTable = declTable.AddRootDeclaration(embeddedTree.DeclarationEntry)
            Next
            Return declTable
        End Function

        Private Shared Function RemoveEmbeddedTrees(
            declTable As DeclarationTable,
            embeddedTrees As ImmutableArray(Of EmbeddedTreeAndDeclaration)
        ) As DeclarationTable

            For Each embeddedTree In embeddedTrees
                declTable = declTable.RemoveRootDeclaration(embeddedTree.DeclarationEntry)
            Next
            Return declTable
        End Function

        ''' <summary>
        ''' Returns True if the set of references contains those assemblies needed for XML
1112
        ''' literals.
P
Pilchie 已提交
1113 1114 1115 1116
        ''' If those assemblies are included, we should include the InternalXmlHelper
        ''' SyntaxTree in the Compilation so the helper methods are available for binding XML.
        ''' </summary>
        Private Function IncludeInternalXmlHelper() As Boolean
1117 1118 1119
            ' In new flavors of the framework, types, that XML helpers depend upon, are
            ' defined in assemblies with different names. Let's not hardcode these names, 
            ' let's check for presence of types instead.
1120 1121
            Return Not Me.Options.SuppressEmbeddedDeclarations AndAlso
                   InternalXmlHelperDependencyIsSatisfied(WellKnownType.System_Linq_Enumerable) AndAlso
1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
                   InternalXmlHelperDependencyIsSatisfied(WellKnownType.System_Xml_Linq_XElement) AndAlso
                   InternalXmlHelperDependencyIsSatisfied(WellKnownType.System_Xml_Linq_XName) AndAlso
                   InternalXmlHelperDependencyIsSatisfied(WellKnownType.System_Xml_Linq_XAttribute) AndAlso
                   InternalXmlHelperDependencyIsSatisfied(WellKnownType.System_Xml_Linq_XNamespace)
        End Function

        Private Function InternalXmlHelperDependencyIsSatisfied(type As WellKnownType) As Boolean

            Dim metadataName = MetadataTypeName.FromFullName(WellKnownTypes.GetMetadataName(type), useCLSCompliantNameArityEncoding:=True)
            Dim sourceAssembly = Me.SourceAssembly

            ' Lookup only in references. An attempt to lookup in assembly being built will get us in a cycle.
            ' We are explicitly ignoring scenario where the type might be defined in an added module.
            For Each reference As AssemblySymbol In sourceAssembly.SourceModule.GetReferencedAssemblySymbols()
                Debug.Assert(Not reference.IsMissing)
                Dim candidate As NamedTypeSymbol = reference.LookupTopLevelMetadataType(metadataName, digThroughForwardedTypes:=False)

                If sourceAssembly.IsValidWellKnownType(candidate) AndAlso AssemblySymbol.IsAcceptableMatchForGetTypeByNameAndArity(candidate) Then
                    Return True
                End If
P
Pilchie 已提交
1142 1143
            Next

1144
            Return False
P
Pilchie 已提交
1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156
        End Function

        ' TODO: This comparison probably will change to compiler command line order, or at least needs 
        ' TODO: to be resolved. See bug 8520.

        ''' <summary>
        ''' Compare two source locations, using their containing trees, and then by Span.First within a tree. 
        ''' Can be used to get a total ordering on declarations, for example.
        ''' </summary>
        Friend Overrides Function CompareSourceLocations(first As Location, second As Location) As Integer
            Return LexicalSortKey.Compare(first, second, Me)
        End Function
1157 1158 1159 1160 1161 1162 1163 1164

        ''' <summary>
        ''' Compare two source locations, using their containing trees, and then by Span.First within a tree. 
        ''' Can be used to get a total ordering on declarations, for example.
        ''' </summary>
        Friend Overrides Function CompareSourceLocations(first As SyntaxReference, second As SyntaxReference) As Integer
            Return LexicalSortKey.Compare(first, second, Me)
        End Function
P
Pilchie 已提交
1165

1166 1167 1168 1169 1170
        Friend Overrides Function GetSyntaxTreeOrdinal(tree As SyntaxTree) As Integer
            Debug.Assert(Me.ContainsSyntaxTree(tree))
            Return _syntaxTreeOrdinalMap(tree)
        End Function

P
Pilchie 已提交
1171 1172 1173 1174 1175 1176 1177 1178
#End Region

#Region "References"
        Friend Overrides Function CommonGetBoundReferenceManager() As CommonReferenceManager
            Return GetBoundReferenceManager()
        End Function

        Friend Shadows Function GetBoundReferenceManager() As ReferenceManager
1179 1180 1181
            If _lazyAssemblySymbol Is Nothing Then
                _referenceManager.CreateSourceAssemblyForCompilation(Me)
                Debug.Assert(_lazyAssemblySymbol IsNot Nothing)
P
Pilchie 已提交
1182 1183 1184 1185
            End If

            ' referenceManager can only be accessed after we initialized the lazyAssemblySymbol.
            ' In fact, initialization of the assembly symbol might change the reference manager.
1186
            Return _referenceManager
P
Pilchie 已提交
1187 1188 1189
        End Function

        ' for testing only:
A
angocke 已提交
1190
        Friend Function ReferenceManagerEquals(other As VisualBasicCompilation) As Boolean
1191
            Return _referenceManager Is other._referenceManager
P
Pilchie 已提交
1192 1193 1194 1195 1196 1197 1198 1199
        End Function

        Public Overrides ReadOnly Property DirectiveReferences As ImmutableArray(Of MetadataReference)
            Get
                Return GetBoundReferenceManager().DirectiveReferences
            End Get
        End Property

A
Andy Gocke 已提交
1200
        Friend Overrides ReadOnly Property ReferenceDirectiveMap As IDictionary(Of (path As String, content As String), MetadataReference)
P
Pilchie 已提交
1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214
            Get
                Return GetBoundReferenceManager().ReferenceDirectiveMap
            End Get
        End Property

        ''' <summary>
        ''' Gets the <see cref="AssemblySymbol"/> or <see cref="ModuleSymbol"/> for a metadata reference used to create this compilation.
        ''' </summary>
        ''' <returns><see cref="AssemblySymbol"/> or <see cref="ModuleSymbol"/> corresponding to the given reference or Nothing if there is none.</returns>
        ''' <remarks>
        ''' Uses object identity when comparing two references. 
        ''' </remarks>
        Friend Shadows Function GetAssemblyOrModuleSymbol(reference As MetadataReference) As Symbol
            If (reference Is Nothing) Then
1215
                Throw New ArgumentNullException(NameOf(reference))
P
Pilchie 已提交
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
            End If

            If reference.Properties.Kind = MetadataImageKind.Assembly Then
                Return GetBoundReferenceManager().GetReferencedAssemblySymbol(reference)
            Else
                Debug.Assert(reference.Properties.Kind = MetadataImageKind.Module)
                Dim index As Integer = GetBoundReferenceManager().GetReferencedModuleIndex(reference)
                Return If(index < 0, Nothing, Me.Assembly.Modules(index))
            End If
        End Function

        ''' <summary>
        ''' Gets the <see cref="MetadataReference"/> that corresponds to the assembly symbol.
        ''' </summary>
        Friend Shadows Function GetMetadataReference(assemblySymbol As AssemblySymbol) As MetadataReference
1231
            Return Me.GetBoundReferenceManager().GetMetadataReference(assemblySymbol)
P
Pilchie 已提交
1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
        End Function

        Public Overrides ReadOnly Property ReferencedAssemblyNames As IEnumerable(Of AssemblyIdentity)
            Get
                Return [Assembly].Modules.SelectMany(Function(m) m.GetReferencedAssemblies())
            End Get
        End Property

        Friend Overrides ReadOnly Property ReferenceDirectives As IEnumerable(Of ReferenceDirective)
            Get
1242
                Return _declarationTable.ReferenceDirectives
P
Pilchie 已提交
1243 1244 1245
            End Get
        End Property

1246 1247
        Public Overrides Function ToMetadataReference(Optional aliases As ImmutableArray(Of String) = Nothing, Optional embedInteropTypes As Boolean = False) As CompilationReference
            Return New VisualBasicCompilationReference(Me, aliases, embedInteropTypes)
P
Pilchie 已提交
1248 1249
        End Function

A
angocke 已提交
1250 1251
        Public Shadows Function AddReferences(ParamArray references As MetadataReference()) As VisualBasicCompilation
            Return DirectCast(MyBase.AddReferences(references), VisualBasicCompilation)
P
Pilchie 已提交
1252 1253
        End Function

A
angocke 已提交
1254 1255
        Public Shadows Function AddReferences(references As IEnumerable(Of MetadataReference)) As VisualBasicCompilation
            Return DirectCast(MyBase.AddReferences(references), VisualBasicCompilation)
P
Pilchie 已提交
1256 1257
        End Function

A
angocke 已提交
1258 1259
        Public Shadows Function RemoveReferences(ParamArray references As MetadataReference()) As VisualBasicCompilation
            Return DirectCast(MyBase.RemoveReferences(references), VisualBasicCompilation)
P
Pilchie 已提交
1260 1261
        End Function

A
angocke 已提交
1262 1263
        Public Shadows Function RemoveReferences(references As IEnumerable(Of MetadataReference)) As VisualBasicCompilation
            Return DirectCast(MyBase.RemoveReferences(references), VisualBasicCompilation)
P
Pilchie 已提交
1264 1265
        End Function

A
angocke 已提交
1266 1267
        Public Shadows Function RemoveAllReferences() As VisualBasicCompilation
            Return DirectCast(MyBase.RemoveAllReferences(), VisualBasicCompilation)
P
Pilchie 已提交
1268 1269
        End Function

A
angocke 已提交
1270 1271
        Public Shadows Function ReplaceReference(oldReference As MetadataReference, newReference As MetadataReference) As VisualBasicCompilation
            Return DirectCast(MyBase.ReplaceReference(oldReference, newReference), VisualBasicCompilation)
P
Pilchie 已提交
1272 1273
        End Function

1274 1275 1276 1277 1278 1279 1280
        ''' <summary>
        ''' Determine if enum arrays can be initialized using block initialization.
        ''' </summary>
        ''' <returns>True if it's safe to use block initialization for enum arrays.</returns>
        ''' <remarks>
        ''' In NetFx 4.0, block array initializers do not work on all combinations of {32/64 X Debug/Retail} when array elements are enums.
        ''' This is fixed in 4.5 thus enabling block array initialization for a very common case.
N
Nikita Potapenko 已提交
1281
        ''' We look for the presence of <see cref="System.Runtime.GCLatencyMode.SustainedLowLatency"/> which was introduced in .NET Framework 4.5
1282 1283 1284 1285 1286 1287 1288 1289
        ''' </remarks>
        Friend ReadOnly Property EnableEnumArrayBlockInitialization As Boolean
            Get
                Dim sustainedLowLatency = GetWellKnownTypeMember(WellKnownMember.System_Runtime_GCLatencyMode__SustainedLowLatency)
                Return sustainedLowLatency IsNot Nothing AndAlso sustainedLowLatency.ContainingAssembly = Assembly.CorLibrary
            End Get
        End Property

P
Pilchie 已提交
1290 1291 1292 1293 1294 1295 1296
#End Region

#Region "Symbols"

        Friend ReadOnly Property SourceAssembly As SourceAssemblySymbol
            Get
                GetBoundReferenceManager()
1297
                Return _lazyAssemblySymbol
P
Pilchie 已提交
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327
            End Get
        End Property

        ''' <summary>
        ''' Gets the AssemblySymbol that represents the assembly being created.
        ''' </summary>
        Friend Shadows ReadOnly Property Assembly As AssemblySymbol
            Get
                Return Me.SourceAssembly
            End Get
        End Property

        ''' <summary>
        ''' Get a ModuleSymbol that refers to the module being created by compiling all of the code. By
        ''' getting the GlobalNamespace property of that module, all of the namespace and types defined in source code 
        ''' can be obtained.
        ''' </summary>
        Friend Shadows ReadOnly Property SourceModule As ModuleSymbol
            Get
                Return Me.Assembly.Modules(0)
            End Get
        End Property

        ''' <summary>
        ''' Gets the merged root namespace that contains all namespaces and types defined in source code or in 
        ''' referenced metadata, merged into a single namespace hierarchy. This namespace hierarchy is how the compiler
        ''' binds types that are referenced in code.
        ''' </summary>
        Friend Shadows ReadOnly Property GlobalNamespace As NamespaceSymbol
            Get
1328 1329
                If _lazyGlobalNamespace Is Nothing Then
                    Interlocked.CompareExchange(_lazyGlobalNamespace, MergedNamespaceSymbol.CreateGlobalNamespace(Me), Nothing)
P
Pilchie 已提交
1330 1331
                End If

1332
                Return _lazyGlobalNamespace
P
Pilchie 已提交
1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353
            End Get
        End Property

        ''' <summary>
        ''' Get the "root" or default namespace that all source types are declared inside. This may be the 
        ''' global namespace or may be another namespace. 
        ''' </summary>
        Friend ReadOnly Property RootNamespace As NamespaceSymbol
            Get
                Return DirectCast(Me.SourceModule, SourceModuleSymbol).RootNamespace
            End Get
        End Property

        ''' <summary>
        ''' Given a namespace symbol, returns the corresponding namespace symbol with Compilation extent
        ''' that refers to that namespace in this compilation. Returns Nothing if there is no corresponding 
        ''' namespace. This should not occur if the namespace symbol came from an assembly referenced by this
        ''' compilation. 
        ''' </summary>
        Friend Shadows Function GetCompilationNamespace(namespaceSymbol As INamespaceSymbol) As NamespaceSymbol
            If namespaceSymbol Is Nothing Then
1354
                Throw New ArgumentNullException(NameOf(namespaceSymbol))
P
Pilchie 已提交
1355 1356
            End If

1357
            Dim vbNs = TryCast(namespaceSymbol, NamespaceSymbol)
P
Pilchie 已提交
1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371
            If vbNs IsNot Nothing AndAlso vbNs.Extent.Kind = NamespaceKind.Compilation AndAlso vbNs.Extent.Compilation Is Me Then
                ' If we already have a namespace with the right extent, use that.
                Return vbNs
            ElseIf namespaceSymbol.ContainingNamespace Is Nothing Then
                ' If is the root namespace, return the merged root namespace
                Debug.Assert(namespaceSymbol.Name = "", "Namespace with Nothing container should be root namespace with empty name")
                Return GlobalNamespace
            Else
                Dim containingNs = GetCompilationNamespace(namespaceSymbol.ContainingNamespace)
                If containingNs Is Nothing Then
                    Return Nothing
                End If

                ' Get the child namespace of the given name, if any.
1372
                Return containingNs.GetMembers(namespaceSymbol.Name).OfType(Of NamespaceSymbol)().FirstOrDefault()
P
Pilchie 已提交
1373 1374 1375 1376 1377 1378 1379 1380 1381
            End If
        End Function

        Friend Shadows Function GetEntryPoint(cancellationToken As CancellationToken) As MethodSymbol
            Dim entryPoint As EntryPoint = GetEntryPointAndDiagnostics(cancellationToken)
            Return If(entryPoint Is Nothing, Nothing, entryPoint.MethodSymbol)
        End Function

        Friend Function GetEntryPointAndDiagnostics(cancellationToken As CancellationToken) As EntryPoint
C
Charles Stoner 已提交
1382
            If Not Me.Options.OutputKind.IsApplication() AndAlso ScriptClass Is Nothing Then
P
Pilchie 已提交
1383 1384 1385 1386 1387 1388 1389 1390
                Return Nothing
            End If

            If Me.Options.MainTypeName IsNot Nothing AndAlso Not Me.Options.MainTypeName.IsValidClrTypeName() Then
                Debug.Assert(Not Me.Options.Errors.IsDefaultOrEmpty)
                Return New EntryPoint(Nothing, ImmutableArray(Of Diagnostic).Empty)
            End If

1391
            If _lazyEntryPoint Is Nothing Then
P
Pilchie 已提交
1392
                Dim diagnostics As ImmutableArray(Of Diagnostic) = Nothing
C
Charles Stoner 已提交
1393
                Dim entryPoint = FindEntryPoint(cancellationToken, diagnostics)
1394
                Interlocked.CompareExchange(_lazyEntryPoint, New EntryPoint(entryPoint, diagnostics), Nothing)
P
Pilchie 已提交
1395 1396
            End If

1397
            Return _lazyEntryPoint
P
Pilchie 已提交
1398 1399
        End Function

C
Charles Stoner 已提交
1400 1401 1402
        Private Function FindEntryPoint(cancellationToken As CancellationToken, ByRef sealedDiagnostics As ImmutableArray(Of Diagnostic)) As MethodSymbol
            Dim diagnostics = DiagnosticBag.GetInstance()
            Dim entryPointCandidates = ArrayBuilder(Of MethodSymbol).GetInstance()
P
Pilchie 已提交
1403

1404 1405
            Try
                Dim mainType As SourceMemberContainerTypeSymbol
P
Pilchie 已提交
1406

1407 1408
                Dim mainTypeName As String = Me.Options.MainTypeName
                Dim globalNamespace As NamespaceSymbol = Me.SourceModule.GlobalNamespace
P
Pilchie 已提交
1409

1410
                Dim errorTarget As Object
P
Pilchie 已提交
1411

1412 1413
                If mainTypeName IsNot Nothing Then
                    ' Global code is the entry point, ignore all other Mains.
C
Charles Stoner 已提交
1414
                    If ScriptClass IsNot Nothing Then
1415 1416
                        ' CONSIDER: we could use the symbol instead of just the name.
                        diagnostics.Add(ERRID.WRN_MainIgnored, NoLocation.Singleton, mainTypeName)
C
Charles Stoner 已提交
1417
                        Return ScriptClass.GetScriptEntryPoint()
1418
                    End If
P
Pilchie 已提交
1419

1420 1421 1422
                    Dim mainTypeOrNamespace = globalNamespace.GetNamespaceOrTypeByQualifiedName(mainTypeName.Split("."c)).OfType(Of NamedTypeSymbol)().OfMinimalArity()
                    If mainTypeOrNamespace Is Nothing Then
                        diagnostics.Add(ERRID.ERR_StartupCodeNotFound1, NoLocation.Singleton, mainTypeName)
C
Charles Stoner 已提交
1423
                        Return Nothing
1424
                    End If
P
Pilchie 已提交
1425

1426 1427 1428
                    mainType = TryCast(mainTypeOrNamespace, SourceMemberContainerTypeSymbol)
                    If mainType Is Nothing OrElse (mainType.TypeKind <> TypeKind.Class AndAlso mainType.TypeKind <> TypeKind.Structure AndAlso mainType.TypeKind <> TypeKind.Module) Then
                        diagnostics.Add(ERRID.ERR_StartupCodeNotFound1, NoLocation.Singleton, mainType)
C
Charles Stoner 已提交
1429
                        Return Nothing
1430
                    End If
P
Pilchie 已提交
1431

1432 1433 1434
                    ' Dev10 reports ERR_StartupCodeNotFound1 but that doesn't make much sense
                    If mainType.IsGenericType Then
                        diagnostics.Add(ERRID.ERR_GenericSubMainsFound1, NoLocation.Singleton, mainType)
C
Charles Stoner 已提交
1435
                        Return Nothing
1436
                    End If
P
Pilchie 已提交
1437

1438
                    errorTarget = mainType
P
Pilchie 已提交
1439

1440 1441 1442 1443 1444
                    ' NOTE: unlike in C#, we're not going search the member list of mainType directly.
                    ' Instead, we're going to mimic dev10's behavior by doing a lookup for "Main",
                    ' starting in mainType.  Among other things, this implies that the entrypoint
                    ' could be in a base class and that it could be hidden by a non-method member
                    ' named "Main".
P
Pilchie 已提交
1445

1446 1447 1448 1449
                    Dim binder As Binder = BinderBuilder.CreateBinderForType(mainType.ContainingSourceModule, mainType.SyntaxReferences(0).SyntaxTree, mainType)
                    Dim lookupResult As LookupResult = LookupResult.GetInstance()
                    Dim entryPointLookupOptions As LookupOptions = LookupOptions.AllMethodsOfAnyArity Or LookupOptions.IgnoreExtensionMethods
                    binder.LookupMember(lookupResult, mainType, WellKnownMemberNames.EntryPointMethodName, arity:=0, options:=entryPointLookupOptions, useSiteDiagnostics:=Nothing)
P
Pilchie 已提交
1450

1451 1452
                    If (Not lookupResult.IsGoodOrAmbiguous) OrElse lookupResult.Symbols(0).Kind <> SymbolKind.Method Then
                        diagnostics.Add(ERRID.ERR_StartupCodeNotFound1, NoLocation.Singleton, mainType)
P
Pilchie 已提交
1453
                        lookupResult.Free()
C
Charles Stoner 已提交
1454
                        Return Nothing
1455
                    End If
P
Pilchie 已提交
1456

1457 1458 1459 1460 1461 1462 1463 1464
                    For Each candidate In lookupResult.Symbols
                        ' The entrypoint cannot be in another assembly.
                        ' NOTE: filter these out here, rather than below, so that we
                        ' report "not found", rather than "invalid", as in dev10.
                        If candidate.ContainingAssembly = Me.Assembly Then
                            entryPointCandidates.Add(DirectCast(candidate, MethodSymbol))
                        End If
                    Next
P
Pilchie 已提交
1465

1466
                    lookupResult.Free()
P
Pilchie 已提交
1467

1468 1469
                Else
                    mainType = Nothing
P
Pilchie 已提交
1470

1471
                    errorTarget = Me.AssemblyName
C
Cyrus Najmabadi 已提交
1472 1473 1474 1475 1476 1477
                    For Each candidate In Me.GetSymbolsWithName(WellKnownMemberNames.EntryPointMethodName, SymbolFilter.Member, cancellationToken)
                        Dim method = TryCast(candidate, MethodSymbol)
                        If method?.IsEntryPointCandidate = True Then
                            entryPointCandidates.Add(method)
                        End If
                    Next
P
Pilchie 已提交
1478

1479
                    ' Global code is the entry point, ignore all other Mains.
C
Charles Stoner 已提交
1480
                    If ScriptClass IsNot Nothing Then
1481 1482 1483
                        For Each main In entryPointCandidates
                            diagnostics.Add(ERRID.WRN_MainIgnored, main.Locations.First(), main)
                        Next
C
Charles Stoner 已提交
1484
                        Return ScriptClass.GetScriptEntryPoint()
P
Pilchie 已提交
1485
                    End If
1486
                End If
P
Pilchie 已提交
1487

1488 1489
                If entryPointCandidates.Count = 0 Then
                    diagnostics.Add(ERRID.ERR_StartupCodeNotFound1, NoLocation.Singleton, errorTarget)
C
Charles Stoner 已提交
1490
                    Return Nothing
1491
                End If
P
Pilchie 已提交
1492

1493 1494
                Dim hasViableGenericEntryPoints As Boolean = False
                Dim viableEntryPoints = ArrayBuilder(Of MethodSymbol).GetInstance()
P
Pilchie 已提交
1495

1496 1497 1498 1499
                For Each candidate In entryPointCandidates
                    If Not candidate.IsViableMainMethod Then
                        Continue For
                    End If
P
Pilchie 已提交
1500

1501 1502 1503 1504 1505 1506 1507
                    If candidate.IsGenericMethod OrElse candidate.ContainingType.IsGenericType Then
                        hasViableGenericEntryPoints = True
                    Else
                        viableEntryPoints.Add(candidate)
                    End If
                Next

C
Charles Stoner 已提交
1508
                Dim entryPoint As MethodSymbol = Nothing
1509 1510 1511 1512 1513 1514 1515 1516 1517
                If viableEntryPoints.Count = 0 Then
                    If hasViableGenericEntryPoints Then
                        diagnostics.Add(ERRID.ERR_GenericSubMainsFound1, NoLocation.Singleton, errorTarget)
                    Else
                        diagnostics.Add(ERRID.ERR_InValidSubMainsFound1, NoLocation.Singleton, errorTarget)
                    End If
                ElseIf viableEntryPoints.Count > 1 Then
                    viableEntryPoints.Sort(LexicalOrderSymbolComparer.Instance)
                    diagnostics.Add(ERRID.ERR_MoreThanOneValidMainWasFound2,
P
Pilchie 已提交
1518 1519 1520
                                        NoLocation.Singleton,
                                        Me.AssemblyName,
                                        New FormattedSymbolList(viableEntryPoints.ToArray(), CustomSymbolDisplayFormatter.ErrorMessageFormatNoModifiersNoReturnType))
1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538
                Else
                    entryPoint = viableEntryPoints(0)

                    If entryPoint.IsAsync Then
                        ' The rule we follow:
                        ' First determine the Sub Main using pre-async rules, and give the pre-async errors if there were 0 or >1 results
                        ' If there was exactly one result, but it was async, then give an error. Otherwise proceed.
                        ' This doesn't follow the same pattern as "error due to being generic". That's because
                        ' maybe one day we'll want to allow Async Sub Main but without breaking back-compat.                    
                        Dim sourceMethod = TryCast(entryPoint, SourceMemberMethodSymbol)
                        Debug.Assert(sourceMethod IsNot Nothing)

                        If sourceMethod IsNot Nothing Then
                            Dim location As Location = sourceMethod.NonMergedLocation
                            Debug.Assert(location IsNot Nothing)

                            If location IsNot Nothing Then
                                Binder.ReportDiagnostic(diagnostics, location, ERRID.ERR_AsyncSubMain)
P
Pilchie 已提交
1539 1540 1541
                            End If
                        End If
                    End If
1542
                End If
P
Pilchie 已提交
1543

1544
                viableEntryPoints.Free()
C
Charles Stoner 已提交
1545
                Return entryPoint
P
Pilchie 已提交
1546

1547
            Finally
C
Charles Stoner 已提交
1548
                entryPointCandidates.Free()
1549 1550
                sealedDiagnostics = diagnostics.ToReadOnlyAndFree()
            End Try
C
Charles Stoner 已提交
1551
        End Function
P
Pilchie 已提交
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580

        Friend Class EntryPoint
            Public ReadOnly MethodSymbol As MethodSymbol
            Public ReadOnly Diagnostics As ImmutableArray(Of Diagnostic)

            Public Sub New(methodSymbol As MethodSymbol, diagnostics As ImmutableArray(Of Diagnostic))
                Me.MethodSymbol = methodSymbol
                Me.Diagnostics = diagnostics
            End Sub
        End Class

        ''' <summary>
        ''' Returns the list of member imports that apply to all syntax trees in this compilation.
        ''' </summary>
        Friend ReadOnly Property MemberImports As ImmutableArray(Of NamespaceOrTypeSymbol)
            Get
                Return DirectCast(Me.SourceModule, SourceModuleSymbol).MemberImports.SelectAsArray(Function(m) m.NamespaceOrType)
            End Get
        End Property

        ''' <summary>
        ''' Returns the list of alias imports that apply to all syntax trees in this compilation.
        ''' </summary>
        Friend ReadOnly Property AliasImports As ImmutableArray(Of AliasSymbol)
            Get
                Return DirectCast(Me.SourceModule, SourceModuleSymbol).AliasImports.SelectAsArray(Function(a) a.Alias)
            End Get
        End Property

C
Charles Stoner 已提交
1581
        Friend Overrides Sub ReportUnusedImports(filterTree As SyntaxTree, diagnostics As DiagnosticBag, cancellationToken As CancellationToken)
1582
            If _lazyImportInfos IsNot Nothing AndAlso (filterTree Is Nothing OrElse filterTree.Options.DocumentationMode <> DocumentationMode.None) Then
1583
                Dim unusedBuilder As ArrayBuilder(Of TextSpan) = Nothing
P
Pilchie 已提交
1584

1585
                For Each info As ImportInfo In _lazyImportInfos
1586
                    cancellationToken.ThrowIfCancellationRequested()
P
Pilchie 已提交
1587

1588
                    Dim infoTree As SyntaxTree = info.Tree
1589
                    If (filterTree Is Nothing OrElse filterTree Is infoTree) AndAlso infoTree.Options.DocumentationMode <> DocumentationMode.None Then
1590 1591
                        Dim clauseSpans = info.ClauseSpans
                        Dim numClauseSpans = clauseSpans.Length
P
Pilchie 已提交
1592

1593 1594 1595
                        If numClauseSpans = 1 Then
                            ' Do less work in common case (one clause per statement).
                            If Not Me.IsImportDirectiveUsed(infoTree, clauseSpans(0).Start) Then
1596
                                diagnostics.Add(ERRID.HDN_UnusedImportStatement, infoTree.GetLocation(info.StatementSpan))
1597 1598 1599 1600 1601
                            End If
                        Else
                            If unusedBuilder IsNot Nothing Then
                                unusedBuilder.Clear()
                            End If
P
Pilchie 已提交
1602

1603 1604 1605 1606 1607 1608
                            For Each clauseSpan In info.ClauseSpans
                                If Not Me.IsImportDirectiveUsed(infoTree, clauseSpan.Start) Then
                                    If unusedBuilder Is Nothing Then
                                        unusedBuilder = ArrayBuilder(Of TextSpan).GetInstance()
                                    End If
                                    unusedBuilder.Add(clauseSpan)
P
Pilchie 已提交
1609
                                End If
1610
                            Next
P
Pilchie 已提交
1611

1612 1613
                            If unusedBuilder IsNot Nothing AndAlso unusedBuilder.Count > 0 Then
                                If unusedBuilder.Count = numClauseSpans Then
1614
                                    diagnostics.Add(ERRID.HDN_UnusedImportStatement, infoTree.GetLocation(info.StatementSpan))
1615 1616
                                Else
                                    For Each clauseSpan In unusedBuilder
1617
                                        diagnostics.Add(ERRID.HDN_UnusedImportClause, infoTree.GetLocation(clauseSpan))
1618 1619
                                    Next
                                End If
P
Pilchie 已提交
1620 1621 1622
                            End If
                        End If
                    End If
1623 1624 1625 1626 1627 1628 1629
                Next

                If unusedBuilder IsNot Nothing Then
                    unusedBuilder.Free()
                End If
            End If

1630 1631 1632 1633
            CompleteTrees(filterTree)
        End Sub

        Friend Overrides Sub CompleteTrees(filterTree As SyntaxTree)
1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
            ' By definition, a tree Is complete when all of its compiler diagnostics have been reported.
            ' Since unused imports are the last thing we compute And report, a tree Is complete when
            ' the unused imports have been reported.
            If EventQueue IsNot Nothing Then
                If filterTree IsNot Nothing Then
                    CompleteTree(filterTree)
                Else
                    For Each tree As SyntaxTree In SyntaxTrees
                        CompleteTree(tree)
                    Next
                End If
            End If
        End Sub

        Private Sub CompleteTree(tree As SyntaxTree)
1649 1650 1651 1652 1653 1654 1655
            If tree.IsEmbeddedOrMyTemplateTree Then
                ' The syntax trees added to AllSyntaxTrees by the compiler
                ' do not count toward completion.
                Return
            End If

            Debug.Assert(AllSyntaxTrees.Contains(tree))
1656

1657 1658
            If _lazyCompilationUnitCompletedTrees Is Nothing Then
                Interlocked.CompareExchange(_lazyCompilationUnitCompletedTrees, New HashSet(Of SyntaxTree)(), Nothing)
1659 1660
            End If

1661 1662
            SyncLock _lazyCompilationUnitCompletedTrees
                If _lazyCompilationUnitCompletedTrees.Add(tree) Then
1663 1664 1665
                    ' signal the end of the compilation unit
                    EventQueue.TryEnqueue(New CompilationUnitCompletedEvent(Me, tree))

1666
                    If _lazyCompilationUnitCompletedTrees.Count = SyntaxTrees.Length Then
1667
                        ' if that was the last tree, signal the end of compilation
M
Manish Vasani 已提交
1668
                        CompleteCompilationEventQueue_NoLock()
1669
                    End If
P
Pilchie 已提交
1670
                End If
1671
            End SyncLock
P
Pilchie 已提交
1672 1673
        End Sub

1674
        Friend Function ShouldAddEvent(symbol As Symbol) As Boolean
M
Manish Vasani 已提交
1675
            Return EventQueue IsNot Nothing AndAlso symbol.IsInSource()
1676 1677
        End Function

1678
        Friend Sub SymbolDeclaredEvent(symbol As Symbol)
1679
            If ShouldAddEvent(symbol) Then
1680
                EventQueue.TryEnqueue(New SymbolDeclaredCompilationEvent(Me, symbol))
1681
            End If
1682 1683
        End Sub

P
Pilchie 已提交
1684
        Friend Sub RecordImports(syntax As ImportsStatementSyntax)
1685
            LazyInitializer.EnsureInitialized(_lazyImportInfos).Enqueue(New ImportInfo(syntax))
P
Pilchie 已提交
1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733
        End Sub

        Private Structure ImportInfo
            Public ReadOnly Tree As SyntaxTree
            Public ReadOnly StatementSpan As TextSpan
            Public ReadOnly ClauseSpans As ImmutableArray(Of TextSpan)

            ' CONSIDER: ClauseSpans will usually be a singleton.  If we're
            ' creating too much garbage, it might be worthwhile to store
            ' a single clause span in a separate field.

            Public Sub New(syntax As ImportsStatementSyntax)
                Me.Tree = syntax.SyntaxTree
                Me.StatementSpan = syntax.Span

                Dim builder = ArrayBuilder(Of TextSpan).GetInstance()

                For Each clause In syntax.ImportsClauses
                    builder.Add(clause.Span)
                Next

                Me.ClauseSpans = builder.ToImmutableAndFree()
            End Sub

        End Structure

        Friend ReadOnly Property DeclaresTheObjectClass As Boolean
            Get
                Return SourceAssembly.DeclaresTheObjectClass
            End Get
        End Property

        Friend Function MightContainNoPiaLocalTypes() As Boolean
            Return SourceAssembly.MightContainNoPiaLocalTypes()
        End Function

        ' NOTE(cyrusn): There is a bit of a discoverability problem with this method and the same
        ' named method in SyntaxTreeSemanticModel.  Technically, i believe these are the appropriate
        ' locations for these methods.  This method has no dependencies on anything but the
        ' compilation, while the other method needs a bindings object to determine what bound node
        ' an expression syntax binds to.  Perhaps when we document these methods we should explain
        ' where a user can find the other.

        ''' <summary>
        ''' Determine what kind of conversion, if any, there is between the types 
        ''' "source" and "destination".
        ''' </summary>
        Public Shadows Function ClassifyConversion(source As ITypeSymbol, destination As ITypeSymbol) As Conversion
1734
            If source Is Nothing Then
1735
                Throw New ArgumentNullException(NameOf(source))
1736
            End If
P
Pilchie 已提交
1737

1738
            If destination Is Nothing Then
1739
                Throw New ArgumentNullException(NameOf(destination))
1740
            End If
P
Pilchie 已提交
1741

1742 1743
            Dim vbsource = source.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(source))
            Dim vbdest = destination.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(destination))
P
Pilchie 已提交
1744

1745 1746 1747
            If vbsource.IsErrorType() OrElse vbdest.IsErrorType() Then
                Return New Conversion(Nothing) ' No conversion
            End If
P
Pilchie 已提交
1748

1749
            Return New Conversion(Conversions.ClassifyConversion(vbsource, vbdest, Nothing))
P
Pilchie 已提交
1750 1751
        End Function

1752 1753 1754 1755
        Public Overrides Function ClassifyCommonConversion(source As ITypeSymbol, destination As ITypeSymbol) As CommonConversion
            Return ClassifyConversion(source, destination).ToCommonConversion()
        End Function

1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782
        Friend Overrides Function ClassifyConvertibleConversion(source As IOperation, destination As ITypeSymbol, ByRef constantValue As [Optional](Of Object)) As IConvertibleConversion
            constantValue = Nothing

            If destination Is Nothing Then
                Return New Conversion(Nothing) ' No conversion
            End If

            Dim sourceType As ITypeSymbol = source.Type

            If sourceType Is Nothing Then
                If source.ConstantValue.HasValue AndAlso source.ConstantValue.Value Is Nothing AndAlso destination.IsReferenceType Then
                    constantValue = source.ConstantValue
                    Return New Conversion(New KeyValuePair(Of ConversionKind, MethodSymbol)(ConversionKind.WideningNothingLiteral, Nothing))
                End If

                Return New Conversion(Nothing) ' No conversion
            End If

            Dim result As Conversion = ClassifyConversion(sourceType, destination)

            If result.IsReference AndAlso source.ConstantValue.HasValue AndAlso source.ConstantValue.Value Is Nothing Then
                constantValue = source.ConstantValue
            End If

            Return result
        End Function

P
Pilchie 已提交
1783 1784 1785 1786 1787 1788 1789 1790 1791 1792 1793 1794
        ''' <summary>
        ''' A symbol representing the implicit Script class. This is null if the class is not
        ''' defined in the compilation.
        ''' </summary>
        Friend Shadows ReadOnly Property ScriptClass As NamedTypeSymbol
            Get
                Return SourceScriptClass
            End Get
        End Property

        Friend ReadOnly Property SourceScriptClass As ImplicitNamedTypeSymbol
            Get
1795
                Return _scriptClass.Value
P
Pilchie 已提交
1796 1797 1798 1799 1800
            End Get
        End Property

        ''' <summary>
        ''' Resolves a symbol that represents script container (Script class). 
1801
        ''' Uses the full name of the container class stored in <see cref="CompilationOptions.ScriptClassName"/>  to find the symbol.
P
Pilchie 已提交
1802 1803 1804 1805 1806
        ''' </summary> 
        ''' <returns>
        ''' The Script class symbol or null if it is not defined.
        ''' </returns>
        Private Function BindScriptClass() As ImplicitNamedTypeSymbol
1807
            Return DirectCast(CommonBindScriptClass(), ImplicitNamedTypeSymbol)
P
Pilchie 已提交
1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825
        End Function

        ''' <summary>
        ''' Get symbol for predefined type from Cor Library referenced by this compilation.
        ''' </summary>
        Friend Shadows Function GetSpecialType(typeId As SpecialType) As NamedTypeSymbol
            Dim result = Assembly.GetSpecialType(typeId)
            Debug.Assert(result.SpecialType = typeId)
            Return result
        End Function

        ''' <summary>
        ''' Get symbol for predefined type member from Cor Library referenced by this compilation.
        ''' </summary>
        Friend Shadows Function GetSpecialTypeMember(memberId As SpecialMember) As Symbol
            Return Assembly.GetSpecialTypeMember(memberId)
        End Function

1826 1827 1828 1829
        Friend Overrides Function CommonGetSpecialTypeMember(specialMember As SpecialMember) As ISymbol
            Return GetSpecialTypeMember(specialMember)
        End Function

C
Charles Stoner 已提交
1830 1831 1832 1833 1834
        Friend Function GetTypeByReflectionType(type As Type, diagnostics As DiagnosticBag) As TypeSymbol
            ' TODO: See CSharpCompilation.GetTypeByReflectionType
            Return GetSpecialType(SpecialType.System_Object)
        End Function

P
Pilchie 已提交
1835 1836 1837 1838 1839 1840 1841 1842 1843 1844
        ''' <summary>
        ''' Lookup a type within the compilation's assembly and all referenced assemblies
        ''' using its canonical CLR metadata name (names are compared case-sensitively).
        ''' </summary>
        ''' <param name="fullyQualifiedMetadataName">
        ''' </param>
        ''' <returns>
        ''' Symbol for the type or null if type cannot be found or is ambiguous. 
        ''' </returns>
        Friend Shadows Function GetTypeByMetadataName(fullyQualifiedMetadataName As String) As NamedTypeSymbol
1845
            Return Me.Assembly.GetTypeByMetadataName(fullyQualifiedMetadataName, includeReferences:=True, isWellKnownType:=False, conflicts:=Nothing)
P
Pilchie 已提交
1846 1847 1848 1849 1850 1851 1852 1853 1854 1855
        End Function

        Friend Shadows ReadOnly Property ObjectType As NamedTypeSymbol
            Get
                Return Assembly.ObjectType
            End Get
        End Property

        Friend Shadows Function CreateArrayTypeSymbol(elementType As TypeSymbol, Optional rank As Integer = 1) As ArrayTypeSymbol
            If elementType Is Nothing Then
1856
                Throw New ArgumentNullException(NameOf(elementType))
P
Pilchie 已提交
1857 1858
            End If

1859
            Return ArrayTypeSymbol.CreateVBArray(elementType, Nothing, rank, Me)
P
Pilchie 已提交
1860 1861
        End Function

1862 1863 1864 1865 1866 1867 1868 1869
        Friend ReadOnly Property HasTupleNamesAttributes As Boolean
            Get
                Return GetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_TupleElementNamesAttribute__ctorTransformNames) IsNot Nothing
            End Get
        End Property

        Friend Function CanEmitSpecialType(type As SpecialType) As Boolean
            Dim typeSymbol = GetSpecialType(type)
V
VSadov 已提交
1870 1871
            Dim diagnostic = typeSymbol.GetUseSiteErrorInfo
            Return diagnostic Is Nothing OrElse diagnostic.Severity <> DiagnosticSeverity.Error
1872 1873
        End Function

1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
        Private Protected Overrides Function IsSymbolAccessibleWithinCore(symbol As ISymbol, within As ISymbol, throughType As ITypeSymbol) As Boolean
            Dim symbol0 = symbol.EnsureVbSymbolOrNothing(Of Symbol)(NameOf(symbol))
            Dim within0 = within.EnsureVbSymbolOrNothing(Of Symbol)(NameOf(within))
            Dim throughType0 = throughType.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(throughType))
            Return If(within0.Kind = SymbolKind.Assembly,
                AccessCheck.IsSymbolAccessible(symbol0, DirectCast(within0, AssemblySymbol), useSiteDiagnostics:=Nothing),
                AccessCheck.IsSymbolAccessible(symbol0, DirectCast(within0, NamedTypeSymbol), throughType0, useSiteDiagnostics:=Nothing))
        End Function

        <Obsolete("Compilation.IsSymbolAccessibleWithin is not designed for use within the compilers", True)>
        Friend Shadows Function IsSymbolAccessibleWithin(symbol As ISymbol, within As ISymbol, Optional throughType As ITypeSymbol = Nothing) As Boolean
            Throw New NotImplementedException
        End Function

P
Pilchie 已提交
1888 1889 1890 1891 1892 1893 1894 1895 1896
#End Region

#Region "Binding"

        '''<summary> 
        ''' Get a fresh SemanticModel.  Note that each invocation gets a fresh SemanticModel, each of
        ''' which has a cache.  Therefore, one effectively clears the cache by discarding the
        ''' SemanticModel.
        '''</summary> 
1897 1898
        Public Shadows Function GetSemanticModel(syntaxTree As SyntaxTree, Optional ignoreAccessibility As Boolean = False) As SemanticModel
            Return New SyntaxTreeSemanticModel(Me, DirectCast(Me.SourceModule, SourceModuleSymbol), syntaxTree, ignoreAccessibility)
P
Pilchie 已提交
1899 1900
        End Function

1901 1902 1903 1904 1905 1906
        Friend ReadOnly Property FeatureStrictEnabled As Boolean
            Get
                Return Me.Feature("strict") IsNot Nothing
            End Get
        End Property

P
Pilchie 已提交
1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924
#End Region

#Region "Diagnostics"

        Friend Overrides ReadOnly Property MessageProvider As CommonMessageProvider
            Get
                Return VisualBasic.MessageProvider.Instance
            End Get
        End Property

        ''' <summary>
        ''' Get all diagnostics for the entire compilation. This includes diagnostics from parsing, declarations, and
        ''' the bodies of methods. Getting all the diagnostics is potentially a length operations, as it requires parsing and
        ''' compiling all the code. The set of diagnostics is not caches, so each call to this method will recompile all
        ''' methods.
        ''' </summary>
        ''' <param name="cancellationToken">Cancellation token to allow cancelling the operation.</param>
        Public Overrides Function GetDiagnostics(Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of Diagnostic)
1925
            Return GetDiagnostics(DefaultDiagnosticsStage, True, cancellationToken)
P
Pilchie 已提交
1926 1927 1928 1929 1930 1931 1932 1933
        End Function

        ''' <summary>
        ''' Get parse diagnostics for the entire compilation. This includes diagnostics from parsing BUT NOT from declarations and
        ''' the bodies of methods or initializers. The set of parse diagnostics is cached, so calling this method a second time
        ''' should be fast.
        ''' </summary>
        Public Overrides Function GetParseDiagnostics(Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of Diagnostic)
1934
            Return GetDiagnostics(CompilationStage.Parse, False, cancellationToken)
P
Pilchie 已提交
1935 1936 1937 1938 1939 1940 1941 1942 1943
        End Function

        ''' <summary>
        ''' Get declarations diagnostics for the entire compilation. This includes diagnostics from declarations, BUT NOT
        ''' the bodies of methods or initializers. The set of declaration diagnostics is cached, so calling this method a second time
        ''' should be fast.
        ''' </summary>
        ''' <param name="cancellationToken">Cancellation token to allow cancelling the operation.</param>
        Public Overrides Function GetDeclarationDiagnostics(Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of Diagnostic)
1944
            Return GetDiagnostics(CompilationStage.Declare, False, cancellationToken)
P
Pilchie 已提交
1945 1946 1947 1948 1949 1950 1951 1952 1953
        End Function

        ''' <summary>
        ''' Get method body diagnostics for the entire compilation. This includes diagnostics only from 
        ''' the bodies of methods and initializers. These diagnostics are NOT cached, so calling this method a second time
        ''' repeats significant work.
        ''' </summary>
        ''' <param name="cancellationToken">Cancellation token to allow cancelling the operation.</param>
        Public Overrides Function GetMethodBodyDiagnostics(Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of Diagnostic)
1954
            Return GetDiagnostics(CompilationStage.Compile, False, cancellationToken)
P
Pilchie 已提交
1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965
        End Function

        ''' <summary>
        ''' Get all errors in the compilation, up through the given compilation stage. Note that this may
        ''' require significant work by the compiler, as all source code must be compiled to the given
        ''' level in order to get the errors. Errors on Options should be inspected by the user prior to constructing the compilation.
        ''' </summary>
        ''' <returns>
        ''' Returns all errors. The errors are not sorted in any particular order, and the client
        ''' should sort the errors as desired.
        ''' </returns>
1966
        Friend Overloads Function GetDiagnostics(stage As CompilationStage, Optional includeEarlierStages As Boolean = True, Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of Diagnostic)
1967 1968 1969 1970 1971 1972 1973 1974 1975 1976
            Dim diagnostics = DiagnosticBag.GetInstance()
            GetDiagnostics(stage, includeEarlierStages, diagnostics, cancellationToken)
            Return diagnostics.ToReadOnlyAndFree()
        End Function

        Friend Overrides Sub GetDiagnostics(stage As CompilationStage,
                                             includeEarlierStages As Boolean,
                                             diagnostics As DiagnosticBag,
                                             Optional cancellationToken As CancellationToken = Nothing)

1977
            Dim builder = DiagnosticBag.GetInstance()
P
Pilchie 已提交
1978

1979 1980
            ' Add all parsing errors.
            If (stage = CompilationStage.Parse OrElse stage > CompilationStage.Parse AndAlso includeEarlierStages) Then
1981

1982 1983 1984
                ' Embedded trees shouldn't have any errors, let's avoid making decision if they should be added too early.
                ' Otherwise IDE performance might be affect.
                If Options.ConcurrentBuild Then
O
Omar Tawfik 已提交
1985 1986 1987
                    Dim options = New ParallelOptions() With {.CancellationToken = cancellationToken}
                    Parallel.For(0, SyntaxTrees.Length, options,
                            UICultureUtilities.WithCurrentUICulture(Sub(i As Integer) builder.AddRange(SyntaxTrees(i).GetDiagnostics(cancellationToken))))
1988 1989 1990 1991 1992
                Else
                    For Each tree In SyntaxTrees
                        cancellationToken.ThrowIfCancellationRequested()
                        builder.AddRange(tree.GetDiagnostics(cancellationToken))
                    Next
P
Pilchie 已提交
1993
                End If
O
Omar Tawfik 已提交
1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008

                Dim parseOptionsReported = New HashSet(Of ParseOptions)
                If Options.ParseOptions IsNot Nothing Then
                    parseOptionsReported.Add(Options.ParseOptions) ' This is reported in Options.Errors at CompilationStage.Declare
                End If

                For Each tree In SyntaxTrees
                    cancellationToken.ThrowIfCancellationRequested()
                    If Not tree.Options.Errors.IsDefaultOrEmpty AndAlso parseOptionsReported.Add(tree.Options) Then
                        Dim location = tree.GetLocation(TextSpan.FromBounds(0, 0))
                        For Each err In tree.Options.Errors
                            builder.Add(err.WithLocation(location))
                        Next
                    End If
                Next
2009
            End If
P
Pilchie 已提交
2010

2011 2012
            ' Add declaration errors
            If (stage = CompilationStage.Declare OrElse stage > CompilationStage.Declare AndAlso includeEarlierStages) Then
2013
                CheckAssemblyName(builder)
2014 2015 2016 2017
                builder.AddRange(Options.Errors)
                builder.AddRange(GetBoundReferenceManager().Diagnostics)
                builder.AddRange(SourceAssembly.GetAllDeclarationErrors(cancellationToken))
                builder.AddRange(GetClsComplianceDiagnostics(cancellationToken))
2018

M
Manish Vasani 已提交
2019 2020
                If EventQueue IsNot Nothing AndAlso SyntaxTrees.Length = 0 Then
                    EnsureCompilationEventQueueCompleted()
2021
                End If
2022
            End If
P
Pilchie 已提交
2023

2024 2025 2026 2027 2028 2029 2030 2031
            ' Add method body compilation errors.
            If (stage = CompilationStage.Compile OrElse stage > CompilationStage.Compile AndAlso includeEarlierStages) Then
                ' Note: this phase does not need to be parallelized because 
                '       it is already implemented in method compiler
                Dim methodBodyDiagnostics = DiagnosticBag.GetInstance()
                GetDiagnosticsForAllMethodBodies(builder.HasAnyErrors(), methodBodyDiagnostics, stage, cancellationToken)
                builder.AddRangeAndFree(methodBodyDiagnostics)
            End If
P
Pilchie 已提交
2032

2033 2034
            ' Before returning diagnostics, we filter some of them
            ' to honor the compiler options (e.g., /nowarn and /warnaserror)
2035 2036
            FilterAndAppendAndFreeDiagnostics(diagnostics, builder)
        End Sub
P
Pilchie 已提交
2037 2038 2039 2040 2041 2042 2043 2044 2045

        Private Function GetClsComplianceDiagnostics(cancellationToken As CancellationToken, Optional filterTree As SyntaxTree = Nothing, Optional filterSpanWithinTree As TextSpan? = Nothing) As ImmutableArray(Of Diagnostic)
            If filterTree IsNot Nothing Then
                Dim builder = DiagnosticBag.GetInstance()
                ClsComplianceChecker.CheckCompliance(Me, builder, cancellationToken, filterTree, filterSpanWithinTree)
                Return builder.ToReadOnlyAndFree()
            End If

            Debug.Assert(filterSpanWithinTree Is Nothing)
2046
            If _lazyClsComplianceDiagnostics.IsDefault Then
P
Pilchie 已提交
2047 2048
                Dim builder = DiagnosticBag.GetInstance()
                ClsComplianceChecker.CheckCompliance(Me, builder, cancellationToken)
2049
                ImmutableInterlocked.InterlockedInitialize(_lazyClsComplianceDiagnostics, builder.ToReadOnlyAndFree())
P
Pilchie 已提交
2050 2051
            End If

2052 2053
            Debug.Assert(Not _lazyClsComplianceDiagnostics.IsDefault)
            Return _lazyClsComplianceDiagnostics
P
Pilchie 已提交
2054 2055 2056 2057
        End Function

        Private Shared Iterator Function FilterDiagnosticsByLocation(diagnostics As IEnumerable(Of Diagnostic), tree As SyntaxTree, filterSpanWithinTree As TextSpan?) As IEnumerable(Of Diagnostic)
            For Each diagnostic In diagnostics
2058
                If diagnostic.HasIntersectingLocation(tree, filterSpanWithinTree) Then
P
Pilchie 已提交
2059 2060 2061 2062 2063
                    Yield diagnostic
                End If
            Next
        End Function

2064
        Friend Function GetDiagnosticsForSyntaxTree(stage As CompilationStage,
P
Pilchie 已提交
2065 2066 2067
                                              tree As SyntaxTree,
                                              filterSpanWithinTree As TextSpan?,
                                              includeEarlierStages As Boolean,
2068
                                              Optional cancellationToken As CancellationToken = Nothing) As ImmutableArray(Of Diagnostic)
P
Pilchie 已提交
2069
            If Not SyntaxTrees.Contains(tree) Then
2070
                Throw New ArgumentException("Cannot GetDiagnosticsForSyntax for a tree that is not part of the compilation", NameOf(tree))
P
Pilchie 已提交
2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082
            End If

            Dim builder = DiagnosticBag.GetInstance()

            If (stage = CompilationStage.Parse OrElse stage > CompilationStage.Parse AndAlso includeEarlierStages) Then
                ' Add all parsing errors.
                cancellationToken.ThrowIfCancellationRequested()
                Dim syntaxDiagnostics = tree.GetDiagnostics(cancellationToken)
                syntaxDiagnostics = FilterDiagnosticsByLocation(syntaxDiagnostics, tree, filterSpanWithinTree)
                builder.AddRange(syntaxDiagnostics)
            End If

2083
            ' Add declaring errors
P
Pilchie 已提交
2084 2085 2086 2087 2088 2089 2090 2091 2092 2093
            If (stage = CompilationStage.Declare OrElse stage > CompilationStage.Declare AndAlso includeEarlierStages) Then
                Dim declarationDiags = DirectCast(SourceModule, SourceModuleSymbol).GetDeclarationErrorsInTree(tree, filterSpanWithinTree, AddressOf FilterDiagnosticsByLocation, cancellationToken)
                Dim filteredDiags = FilterDiagnosticsByLocation(declarationDiags, tree, filterSpanWithinTree)
                builder.AddRange(filteredDiags)
                builder.AddRange(GetClsComplianceDiagnostics(cancellationToken, tree, filterSpanWithinTree))
            End If

            ' Add method body declaring errors.
            If (stage = CompilationStage.Compile OrElse stage > CompilationStage.Compile AndAlso includeEarlierStages) Then
                Dim methodBodyDiagnostics = DiagnosticBag.GetInstance()
T
TomasMatousek 已提交
2094
                GetDiagnosticsForMethodBodiesInTree(tree, filterSpanWithinTree, builder.HasAnyErrors(), methodBodyDiagnostics, stage, cancellationToken)
P
Pilchie 已提交
2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107

                ' This diagnostics can include diagnostics for initializers that do not belong to the tree.
                ' Let's filter them out.
                If Not methodBodyDiagnostics.IsEmptyWithoutResolution Then
                    Dim allDiags = methodBodyDiagnostics.AsEnumerableWithoutResolution()
                    Dim filteredDiags = FilterDiagnosticsByLocation(allDiags, tree, filterSpanWithinTree)
                    For Each diag In filteredDiags
                        builder.Add(diag)
                    Next
                End If
            End If

            Dim result = DiagnosticBag.GetInstance()
2108
            FilterAndAppendAndFreeDiagnostics(result, builder)
P
Pilchie 已提交
2109 2110 2111 2112
            Return result.ToReadOnlyAndFree(Of Diagnostic)()
        End Function

        ' Get diagnostics by compiling all method bodies.
T
TomasMatousek 已提交
2113
        Private Sub GetDiagnosticsForAllMethodBodies(hasDeclarationErrors As Boolean, diagnostics As DiagnosticBag, stage As CompilationStage, cancellationToken As CancellationToken)
P
Pilchie 已提交
2114 2115 2116 2117 2118 2119
            MethodCompiler.GetCompileDiagnostics(Me, SourceModule.GlobalNamespace, Nothing, Nothing, hasDeclarationErrors, diagnostics, stage >= CompilationStage.Emit, cancellationToken)
            DocumentationCommentCompiler.WriteDocumentationCommentXml(Me, Nothing, Nothing, diagnostics, cancellationToken)
            Me.ReportUnusedImports(Nothing, diagnostics, cancellationToken)
        End Sub

        ' Get diagnostics by compiling all method bodies in the given tree.
T
TomasMatousek 已提交
2120
        Private Sub GetDiagnosticsForMethodBodiesInTree(tree As SyntaxTree, filterSpanWithinTree As TextSpan?, hasDeclarationErrors As Boolean, diagnostics As DiagnosticBag, stage As CompilationStage, cancellationToken As CancellationToken)
P
Pilchie 已提交
2121 2122 2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140
            Dim sourceMod = DirectCast(SourceModule, SourceModuleSymbol)

            MethodCompiler.GetCompileDiagnostics(Me,
                                                 SourceModule.GlobalNamespace,
                                                 tree,
                                                 filterSpanWithinTree,
                                                 hasDeclarationErrors,
                                                 diagnostics,
                                                 stage >= CompilationStage.Emit,
                                                 cancellationToken)

            DocumentationCommentCompiler.WriteDocumentationCommentXml(Me, Nothing, Nothing, diagnostics, cancellationToken, tree, filterSpanWithinTree)

            ' Report unused import diagnostics only if computing diagnostics for the entire tree.
            ' Otherwise we cannot determine if a particular directive is used outside of the given sub-span within the tree.
            If Not filterSpanWithinTree.HasValue OrElse filterSpanWithinTree.Value = tree.GetRoot(cancellationToken).FullSpan Then
                Me.ReportUnusedImports(tree, diagnostics, cancellationToken)
            End If
        End Sub

2141
        Friend Overrides Function AnalyzerForLanguage(analyzers As ImmutableArray(Of DiagnosticAnalyzer), analyzerManager As AnalyzerManager) As AnalyzerDriver
2142
            Dim getKind As Func(Of SyntaxNode, SyntaxKind) = Function(node As SyntaxNode) node.Kind
2143 2144
            Dim isComment As Func(Of SyntaxTrivia, Boolean) = Function(trivia As SyntaxTrivia) trivia.Kind() = SyntaxKind.CommentTrivia
            Return New AnalyzerDriver(Of SyntaxKind)(analyzers, getKind, analyzerManager, isComment)
2145
        End Function
P
Pilchie 已提交
2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171

#End Region

#Region "Resources"
        Protected Overrides Sub AppendDefaultVersionResource(resourceStream As Stream)
            Dim fileVersion As String = If(SourceAssembly.FileVersion, SourceAssembly.Identity.Version.ToString())

            'for some parameters, alink used to supply whitespace instead of null.
            Win32ResourceConversions.AppendVersionToResourceStream(resourceStream,
                Not Me.Options.OutputKind.IsApplication(),
                fileVersion:=fileVersion,
                originalFileName:=Me.SourceModule.Name,
                internalName:=Me.SourceModule.Name,
                productVersion:=If(SourceAssembly.InformationalVersion, fileVersion),
                assemblyVersion:=SourceAssembly.Identity.Version,
                fileDescription:=If(SourceAssembly.Title, " "),
                legalCopyright:=If(SourceAssembly.Copyright, " "),
                legalTrademarks:=SourceAssembly.Trademark,
                productName:=SourceAssembly.Product,
                comments:=SourceAssembly.Description,
                companyName:=SourceAssembly.Company)
        End Sub
#End Region

#Region "Emit"

2172 2173 2174 2175 2176 2177
        Friend Overrides ReadOnly Property LinkerMajorVersion As Byte
            Get
                Return &H50
            End Get
        End Property

2178
        Friend Overrides ReadOnly Property IsDelaySigned As Boolean
P
Pilchie 已提交
2179
            Get
2180
                Return SourceAssembly.IsDelaySigned
P
Pilchie 已提交
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190
            End Get
        End Property

        Friend Overrides ReadOnly Property StrongNameKeys As StrongNameKeys
            Get
                Return SourceAssembly.StrongNameKeys
            End Get
        End Property

        Friend Overrides Function CreateModuleBuilder(
2191
            emitOptions As EmitOptions,
2192
            debugEntryPoint As IMethodSymbol,
2193
            sourceLinkStream As Stream,
2194
            embeddedTexts As IEnumerable(Of EmbeddedText),
P
Pilchie 已提交
2195 2196
            manifestResources As IEnumerable(Of ResourceDescription),
            testData As CompilationTestData,
2197 2198
            diagnostics As DiagnosticBag,
            cancellationToken As CancellationToken) As CommonPEModuleBuilder
P
Pilchie 已提交
2199

2200
            Return CreateModuleBuilder(
2201
                emitOptions,
2202
                debugEntryPoint,
2203
                sourceLinkStream,
2204
                embeddedTexts,
2205 2206 2207
                manifestResources,
                testData,
                diagnostics,
2208 2209
                ImmutableArray(Of NamedTypeSymbol).Empty,
                cancellationToken)
2210 2211 2212
        End Function

        Friend Overloads Function CreateModuleBuilder(
2213
            emitOptions As EmitOptions,
2214
            debugEntryPoint As IMethodSymbol,
2215
            sourceLinkStream As Stream,
2216
            embeddedTexts As IEnumerable(Of EmbeddedText),
2217 2218 2219
            manifestResources As IEnumerable(Of ResourceDescription),
            testData As CompilationTestData,
            diagnostics As DiagnosticBag,
2220 2221
            additionalTypes As ImmutableArray(Of NamedTypeSymbol),
            cancellationToken As CancellationToken) As CommonPEModuleBuilder
2222

2223
            Debug.Assert(Not IsSubmission OrElse HasCodeToEmit())
P
Pilchie 已提交
2224 2225

            ' Get the runtime metadata version from the cor library. If this fails we have no reasonable value to give.
2226
            Dim runtimeMetadataVersion = GetRuntimeMetadataVersion()
P
Pilchie 已提交
2227

2228
            Dim moduleSerializationProperties = ConstructModuleSerializationProperties(emitOptions, runtimeMetadataVersion)
P
Pilchie 已提交
2229 2230 2231 2232 2233 2234 2235
            If manifestResources Is Nothing Then
                manifestResources = SpecializedCollections.EmptyEnumerable(Of ResourceDescription)()
            End If

            ' if there is no stream to write to, then there is no need for a module
            Dim moduleBeingBuilt As PEModuleBuilder
            If Options.OutputKind.IsNetModule() Then
2236 2237
                Debug.Assert(additionalTypes.IsEmpty)

P
Pilchie 已提交
2238 2239
                moduleBeingBuilt = New PENetModuleBuilder(
                    DirectCast(Me.SourceModule, SourceModuleSymbol),
2240
                    emitOptions,
P
Pilchie 已提交
2241
                    moduleSerializationProperties,
2242
                    manifestResources)
P
Pilchie 已提交
2243 2244
            Else
                Dim kind = If(Options.OutputKind.IsValid(), Options.OutputKind, OutputKind.DynamicallyLinkedLibrary)
2245
                moduleBeingBuilt = New PEAssemblyBuilder(
P
Pilchie 已提交
2246
                        SourceAssembly,
2247
                        emitOptions,
P
Pilchie 已提交
2248 2249 2250
                        kind,
                        moduleSerializationProperties,
                        manifestResources,
2251
                        additionalTypes)
P
Pilchie 已提交
2252 2253
            End If

2254 2255 2256 2257
            If debugEntryPoint IsNot Nothing Then
                moduleBeingBuilt.SetDebugEntryPoint(DirectCast(debugEntryPoint, MethodSymbol), diagnostics)
            End If

2258 2259
            moduleBeingBuilt.SourceLinkStreamOpt = sourceLinkStream

2260 2261 2262 2263
            If embeddedTexts IsNot Nothing Then
                moduleBeingBuilt.EmbeddedTexts = embeddedTexts
            End If

P
Pilchie 已提交
2264 2265 2266 2267 2268 2269 2270 2271
            If testData IsNot Nothing Then
                moduleBeingBuilt.SetMethodTestData(testData.Methods)
                testData.Module = moduleBeingBuilt
            End If

            Return moduleBeingBuilt
        End Function

C
Charles Stoner 已提交
2272
        Friend Overrides Function CompileMethods(
P
Pilchie 已提交
2273
            moduleBuilder As CommonPEModuleBuilder,
2274
            emittingPdb As Boolean,
2275 2276
            emitMetadataOnly As Boolean,
            emitTestCoverageData As Boolean,
2277
            diagnostics As DiagnosticBag,
2278 2279
            filterOpt As Predicate(Of ISymbol),
            cancellationToken As CancellationToken) As Boolean
2280 2281 2282

            ' The diagnostics should include syntax and declaration errors. We insert these before calling Emitter.Emit, so that we don't emit
            ' metadata if there are declaration errors or method body errors (but we do insert all errors from method body binding...)
2283
            Dim hasDeclarationErrors = Not FilterAndAppendDiagnostics(diagnostics, GetDiagnostics(CompilationStage.Declare, True, cancellationToken), exclude:=Nothing)
P
Pilchie 已提交
2284 2285 2286 2287 2288

            Dim moduleBeingBuilt = DirectCast(moduleBuilder, PEModuleBuilder)

            Me.EmbeddedSymbolManager.MarkAllDeferredSymbolsAsReferenced(Me)

2289 2290 2291 2292 2293 2294
            ' The translation of global imports assumes absence of error symbols.
            ' We don't need to translate them if there are any declaration errors since 
            ' we are not going to emit the metadata.
            If Not hasDeclarationErrors Then
                moduleBeingBuilt.TranslateImports(diagnostics)
            End If
2295

2296
            If emitMetadataOnly Then
P
Pilchie 已提交
2297 2298 2299 2300
                If hasDeclarationErrors Then
                    Return False
                End If

2301 2302 2303 2304 2305 2306
                If moduleBeingBuilt.SourceModule.HasBadAttributes Then
                    ' If there were errors but no declaration diagnostics, explicitly add a "Failed to emit module" error.
                    diagnostics.Add(ERRID.ERR_ModuleEmitFailure, NoLocation.Singleton, moduleBeingBuilt.SourceModule.Name)
                    Return False
                End If

P
Pilchie 已提交
2307 2308 2309
                SynthesizedMetadataCompiler.ProcessSynthesizedMembers(Me, moduleBeingBuilt, cancellationToken)
            Else
                ' start generating PDB checksums if we need to emit PDBs
2310
                If (emittingPdb OrElse emitTestCoverageData) AndAlso
2311
                   Not CreateDebugDocuments(moduleBeingBuilt.DebugDocumentsBuilder, moduleBeingBuilt.EmbeddedTexts, diagnostics) Then
2312
                    Return False
P
Pilchie 已提交
2313 2314
                End If

2315
                ' Perform initial bind of method bodies in spite of earlier errors. This is the same
P
Pilchie 已提交
2316 2317 2318 2319 2320 2321 2322 2323
                ' behavior as when calling GetDiagnostics()

                ' Use a temporary bag so we don't have to refilter pre-existing diagnostics.
                Dim methodBodyDiagnosticBag = DiagnosticBag.GetInstance()

                MethodCompiler.CompileMethodBodies(
                    Me,
                    moduleBeingBuilt,
2324
                    emittingPdb,
2325
                    emitTestCoverageData,
P
Pilchie 已提交
2326
                    hasDeclarationErrors,
2327
                    filterOpt,
P
Pilchie 已提交
2328 2329
                    methodBodyDiagnosticBag,
                    cancellationToken)
T
TomasMatousek 已提交
2330

2331
                Dim hasMethodBodyErrors As Boolean = Not FilterAndAppendAndFreeDiagnostics(diagnostics, methodBodyDiagnosticBag)
P
Pilchie 已提交
2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342
                If hasDeclarationErrors OrElse hasMethodBodyErrors Then
                    Return False
                End If
            End If

            cancellationToken.ThrowIfCancellationRequested()

            ' TODO (tomat): XML doc comments diagnostics
            Return True
        End Function

C
Charles Stoner 已提交
2343 2344 2345
        Friend Overrides Function GenerateResourcesAndDocumentationComments(
            moduleBuilder As CommonPEModuleBuilder,
            xmlDocStream As Stream,
C
Charles Stoner 已提交
2346
            win32Resources As Stream,
2347
            outputNameOverride As String,
C
Charles Stoner 已提交
2348 2349 2350 2351
            diagnostics As DiagnosticBag,
            cancellationToken As CancellationToken) As Boolean

            ' Use a temporary bag so we don't have to refilter pre-existing diagnostics.
2352
            Dim resourceDiagnostics = DiagnosticBag.GetInstance()
C
Charles Stoner 已提交
2353

2354
            SetupWin32Resources(moduleBuilder, win32Resources, resourceDiagnostics)
C
Charles Stoner 已提交
2355 2356 2357

            ' give the name of any added modules, but not the name of the primary module.
            ReportManifestResourceDuplicates(
2358 2359 2360 2361
                moduleBuilder.ManifestResources,
                SourceAssembly.Modules.Skip(1).Select(Function(x) x.Name),
                AddedModulesResourceNames(resourceDiagnostics),
                resourceDiagnostics)
C
Charles Stoner 已提交
2362

2363 2364 2365 2366 2367 2368 2369 2370
            If Not FilterAndAppendAndFreeDiagnostics(diagnostics, resourceDiagnostics) Then
                Return False
            End If

            cancellationToken.ThrowIfCancellationRequested()

            ' Use a temporary bag so we don't have to refilter pre-existing diagnostics.
            Dim xmlDiagnostics = DiagnosticBag.GetInstance()
C
Charles Stoner 已提交
2371

2372
            Dim assemblyName = FileNameUtilities.ChangeExtension(outputNameOverride, extension:=Nothing)
2373 2374 2375
            DocumentationCommentCompiler.WriteDocumentationCommentXml(Me, assemblyName, xmlDocStream, xmlDiagnostics, cancellationToken)

            Return FilterAndAppendAndFreeDiagnostics(diagnostics, xmlDiagnostics)
C
Charles Stoner 已提交
2376 2377
        End Function

P
Pilchie 已提交
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393
        Private Iterator Function AddedModulesResourceNames(diagnostics As DiagnosticBag) As IEnumerable(Of String)
            Dim modules As ImmutableArray(Of ModuleSymbol) = SourceAssembly.Modules

            For i As Integer = 1 To modules.Length - 1
                Dim m = DirectCast(modules(i), Symbols.Metadata.PE.PEModuleSymbol)

                Try
                    For Each resource In m.Module.GetEmbeddedResourcesOrThrow()
                        Yield resource.Name
                    Next
                Catch mrEx As BadImageFormatException
                    diagnostics.Add(ERRID.ERR_UnsupportedModule1, NoLocation.Singleton, m)
                End Try
            Next
        End Function

2394 2395 2396
        Friend Overrides Function EmitDifference(
            baseline As EmitBaseline,
            edits As IEnumerable(Of SemanticEdit),
2397
            isAddedSymbol As Func(Of ISymbol, Boolean),
2398 2399 2400
            metadataStream As Stream,
            ilStream As Stream,
            pdbStream As Stream,
A
angocke 已提交
2401
            updatedMethods As ICollection(Of MethodDefinitionHandle),
2402 2403
            testData As CompilationTestData,
            cancellationToken As CancellationToken) As EmitDifferenceResult
P
Pilchie 已提交
2404

2405
            Return EmitHelpers.EmitDifference(
P
Pilchie 已提交
2406
                Me,
2407 2408
                baseline,
                edits,
2409
                isAddedSymbol,
2410 2411 2412
                metadataStream,
                ilStream,
                pdbStream,
2413
                updatedMethods,
2414 2415
                testData,
                cancellationToken)
P
Pilchie 已提交
2416 2417
        End Function

2418 2419 2420
        Friend Function GetRuntimeMetadataVersion() As String
            Dim corLibrary = TryCast(Assembly.CorLibrary, Symbols.Metadata.PE.PEAssemblySymbol)
            Return If(corLibrary Is Nothing, String.Empty, corLibrary.Assembly.ManifestModule.MetadataVersion)
P
Pilchie 已提交
2421 2422
        End Function

2423 2424
        Friend Overrides Sub AddDebugSourceDocumentsForChecksumDirectives(
            documentsBuilder As DebugDocumentsBuilder,
P
Pilchie 已提交
2425 2426 2427 2428 2429 2430 2431
            tree As SyntaxTree,
            diagnosticBag As DiagnosticBag)

            Dim checksumDirectives = tree.GetRoot().GetDirectives(Function(d) d.Kind = SyntaxKind.ExternalChecksumDirectiveTrivia AndAlso
                                                                              Not d.ContainsDiagnostics)

            For Each directive In checksumDirectives
2432 2433
                Dim checksumDirective As ExternalChecksumDirectiveTriviaSyntax = DirectCast(directive, ExternalChecksumDirectiveTriviaSyntax)
                Dim path = checksumDirective.ExternalSource.ValueText
P
Pilchie 已提交
2434

2435
                Dim checkSumText = checksumDirective.Checksum.ValueText
2436 2437
                Dim normalizedPath = documentsBuilder.NormalizeDebugDocumentPath(path, basePath:=tree.FilePath)
                Dim existingDoc = documentsBuilder.TryGetDebugDocumentForNormalizedPath(normalizedPath)
P
Pilchie 已提交
2438 2439 2440 2441 2442 2443

                If existingDoc IsNot Nothing Then
                    ' directive matches a file path on an actual tree.
                    ' Dev12 compiler just ignores the directive in this case which means that
                    ' checksum of the actual tree always wins and no warning is given.
                    ' We will continue doing the same.
2444
                    If existingDoc.IsComputedChecksum Then
P
Pilchie 已提交
2445 2446 2447
                        Continue For
                    End If

2448 2449 2450
                    Dim sourceInfo = existingDoc.GetSourceInfo()

                    If CheckSumMatches(checkSumText, sourceInfo.Checksum) Then
2451
                        Dim guid As Guid = Guid.Parse(checksumDirective.Guid.ValueText)
2452
                        If guid = sourceInfo.ChecksumAlgorithmId Then
P
Pilchie 已提交
2453 2454 2455 2456 2457 2458 2459
                            ' all parts match, nothing to do
                            Continue For
                        End If
                    End If

                    ' did not match to an existing document
                    ' produce a warning and ignore the directive
2460
                    diagnosticBag.Add(ERRID.WRN_MultipleDeclFileExtChecksum, New SourceLocation(checksumDirective), path)
P
Pilchie 已提交
2461 2462

                Else
2463
                    Dim newDocument = New DebugSourceDocument(
P
Pilchie 已提交
2464
                        normalizedPath,
2465
                        DebugSourceDocument.CorSymLanguageTypeBasic,
2466 2467
                        MakeCheckSumBytes(checksumDirective.Checksum.ValueText),
                        Guid.Parse(checksumDirective.Guid.ValueText))
P
Pilchie 已提交
2468

2469
                    documentsBuilder.AddDebugDocument(newDocument)
P
Pilchie 已提交
2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505
                End If
            Next
        End Sub

        Private Shared Function CheckSumMatches(bytesText As String, bytes As ImmutableArray(Of Byte)) As Boolean
            If bytesText.Length <> bytes.Length * 2 Then
                Return False
            End If

            For i As Integer = 0 To bytesText.Length \ 2 - 1
                ' 1A  in text becomes   0x1A
                Dim b As Integer = SyntaxFacts.IntegralLiteralCharacterValue(bytesText(i * 2)) * 16 +
                                   SyntaxFacts.IntegralLiteralCharacterValue(bytesText(i * 2 + 1))

                If b <> bytes(i) Then
                    Return False
                End If
            Next

            Return True
        End Function

        Private Shared Function MakeCheckSumBytes(bytesText As String) As ImmutableArray(Of Byte)
            Dim builder As ArrayBuilder(Of Byte) = ArrayBuilder(Of Byte).GetInstance()

            For i As Integer = 0 To bytesText.Length \ 2 - 1
                ' 1A  in text becomes   0x1A
                Dim b As Byte = CByte(SyntaxFacts.IntegralLiteralCharacterValue(bytesText(i * 2)) * 16 +
                                      SyntaxFacts.IntegralLiteralCharacterValue(bytesText(i * 2 + 1)))

                builder.Add(b)
            Next

            Return builder.ToImmutableAndFree()
        End Function

2506 2507 2508 2509 2510
        Friend Overrides ReadOnly Property DebugSourceDocumentLanguageId As Guid
            Get
                Return DebugSourceDocument.CorSymLanguageTypeBasic
            End Get
        End Property
P
Pilchie 已提交
2511

2512
        Friend Overrides Function HasCodeToEmit() As Boolean
P
Pilchie 已提交
2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524
            For Each syntaxTree In SyntaxTrees
                Dim unit = syntaxTree.GetCompilationUnitRoot()
                If unit.Members.Count > 0 Then
                    Return True
                End If
            Next

            Return False
        End Function

#End Region

2525
#Region "Common Members"
P
Pilchie 已提交
2526 2527 2528 2529 2530 2531 2532 2533 2534

        Protected Overrides Function CommonWithReferences(newReferences As IEnumerable(Of MetadataReference)) As Compilation
            Return WithReferences(newReferences)
        End Function

        Protected Overrides Function CommonWithAssemblyName(assemblyName As String) As Compilation
            Return WithAssemblyName(assemblyName)
        End Function

2535
        Protected Overrides Function CommonWithScriptCompilationInfo(info As ScriptCompilationInfo) As Compilation
2536
            Return WithScriptCompilationInfo(DirectCast(info, VisualBasicScriptCompilationInfo))
P
Pilchie 已提交
2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556
        End Function

        Protected Overrides ReadOnly Property CommonAssembly As IAssemblySymbol
            Get
                Return Me.Assembly
            End Get
        End Property

        Protected Overrides ReadOnly Property CommonGlobalNamespace As INamespaceSymbol
            Get
                Return Me.GlobalNamespace
            End Get
        End Property

        Protected Overrides ReadOnly Property CommonOptions As CompilationOptions
            Get
                Return Options
            End Get
        End Property

2557 2558
        Protected Overrides Function CommonGetSemanticModel(syntaxTree As SyntaxTree, ignoreAccessibility As Boolean) As SemanticModel
            Return Me.GetSemanticModel(syntaxTree, ignoreAccessibility)
P
Pilchie 已提交
2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573
        End Function

        Protected Overrides ReadOnly Property CommonSyntaxTrees As IEnumerable(Of SyntaxTree)
            Get
                Return Me.SyntaxTrees
            End Get
        End Property

        Protected Overrides Function CommonAddSyntaxTrees(trees As IEnumerable(Of SyntaxTree)) As Compilation
            Dim array = TryCast(trees, SyntaxTree())
            If array IsNot Nothing Then
                Return Me.AddSyntaxTrees(array)
            End If

            If trees Is Nothing Then
2574
                Throw New ArgumentNullException(NameOf(trees))
P
Pilchie 已提交
2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586
            End If

            Return Me.AddSyntaxTrees(trees.Cast(Of SyntaxTree)())
        End Function

        Protected Overrides Function CommonRemoveSyntaxTrees(trees As IEnumerable(Of SyntaxTree)) As Compilation
            Dim array = TryCast(trees, SyntaxTree())
            If array IsNot Nothing Then
                Return Me.RemoveSyntaxTrees(array)
            End If

            If trees Is Nothing Then
2587
                Throw New ArgumentNullException(NameOf(trees))
P
Pilchie 已提交
2588 2589 2590 2591 2592 2593 2594 2595 2596 2597
            End If

            Return Me.RemoveSyntaxTrees(trees.Cast(Of SyntaxTree)())
        End Function

        Protected Overrides Function CommonRemoveAllSyntaxTrees() As Compilation
            Return Me.RemoveAllSyntaxTrees()
        End Function

        Protected Overrides Function CommonReplaceSyntaxTree(oldTree As SyntaxTree, newTree As SyntaxTree) As Compilation
2598
            Return Me.ReplaceSyntaxTree(oldTree, newTree)
P
Pilchie 已提交
2599 2600 2601
        End Function

        Protected Overrides Function CommonWithOptions(options As CompilationOptions) As Compilation
A
angocke 已提交
2602
            Return Me.WithOptions(DirectCast(options, VisualBasicCompilationOptions))
P
Pilchie 已提交
2603 2604 2605
        End Function

        Protected Overrides Function CommonContainsSyntaxTree(syntaxTree As SyntaxTree) As Boolean
2606
            Return Me.ContainsSyntaxTree(syntaxTree)
P
Pilchie 已提交
2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634
        End Function

        Protected Overrides Function CommonGetAssemblyOrModuleSymbol(reference As MetadataReference) As ISymbol
            Return Me.GetAssemblyOrModuleSymbol(reference)
        End Function

        Protected Overrides Function CommonClone() As Compilation
            Return Me.Clone()
        End Function

        Protected Overrides ReadOnly Property CommonSourceModule As IModuleSymbol
            Get
                Return Me.SourceModule
            End Get
        End Property

        Protected Overrides Function CommonGetSpecialType(specialType As SpecialType) As INamedTypeSymbol
            Return Me.GetSpecialType(specialType)
        End Function

        Protected Overrides Function CommonGetCompilationNamespace(namespaceSymbol As INamespaceSymbol) As INamespaceSymbol
            Return Me.GetCompilationNamespace(namespaceSymbol)
        End Function

        Protected Overrides Function CommonGetTypeByMetadataName(metadataName As String) As INamedTypeSymbol
            Return Me.GetTypeByMetadataName(metadataName)
        End Function

2635
        Protected Overrides ReadOnly Property CommonScriptClass As INamedTypeSymbol
P
Pilchie 已提交
2636 2637 2638 2639 2640
            Get
                Return Me.ScriptClass
            End Get
        End Property

2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
        Protected Overrides Function CommonCreateErrorTypeSymbol(container As INamespaceOrTypeSymbol, name As String, arity As Integer) As INamedTypeSymbol
            Return New ExtendedErrorTypeSymbol(
                       container.EnsureVbSymbolOrNothing(Of NamespaceOrTypeSymbol)(NameOf(container)),
                       name, arity)
        End Function

        Protected Overrides Function CommonCreateErrorNamespaceSymbol(container As INamespaceSymbol, name As String) As INamespaceSymbol
            Return New MissingNamespaceSymbol(
                       container.EnsureVbSymbolOrNothing(Of NamespaceSymbol)(NameOf(container)),
                       name)
P
Pilchie 已提交
2651 2652 2653
        End Function

        Protected Overrides Function CommonCreateArrayTypeSymbol(elementType As ITypeSymbol, rank As Integer) As IArrayTypeSymbol
2654
            Return CreateArrayTypeSymbol(elementType.EnsureVbSymbolOrNothing(Of TypeSymbol)(NameOf(elementType)), rank)
P
Pilchie 已提交
2655 2656
        End Function

2657 2658 2659
        Protected Overrides Function CommonCreateTupleTypeSymbol(elementTypes As ImmutableArray(Of ITypeSymbol),
                                                                 elementNames As ImmutableArray(Of String),
                                                                 elementLocations As ImmutableArray(Of Location)) As INamedTypeSymbol
V
VSadov 已提交
2660 2661 2662 2663 2664 2665
            Dim typesBuilder = ArrayBuilder(Of TypeSymbol).GetInstance(elementTypes.Length)
            For i As Integer = 0 To elementTypes.Length - 1
                typesBuilder.Add(elementTypes(i).EnsureVbSymbolOrNothing(Of TypeSymbol)($"{NameOf(elementTypes)}[{i}]"))
            Next

            'no location for the type declaration
2666 2667 2668
            Return TupleTypeSymbol.Create(locationOpt:=Nothing,
                                          elementTypes:=typesBuilder.ToImmutableAndFree(),
                                          elementLocations:=elementLocations,
2669
                                          elementNames:=elementNames, compilation:=Me,
2670
                                          shouldCheckConstraints:=False, errorPositions:=Nothing)
J
Julien 已提交
2671
        End Function
V
VSadov 已提交
2672

2673 2674 2675 2676
        Protected Overrides Function CommonCreateTupleTypeSymbol(
                underlyingType As INamedTypeSymbol,
                elementNames As ImmutableArray(Of String),
                elementLocations As ImmutableArray(Of Location)) As INamedTypeSymbol
V
VSadov 已提交
2677 2678 2679 2680 2681 2682 2683
            Dim csharpUnderlyingTuple = underlyingType.EnsureVbSymbolOrNothing(Of NamedTypeSymbol)(NameOf(underlyingType))

            Dim cardinality As Integer
            If Not csharpUnderlyingTuple.IsTupleCompatible(cardinality) Then
                Throw New ArgumentException(CodeAnalysisResources.TupleUnderlyingTypeMustBeTupleCompatible, NameOf(underlyingType))
            End If

J
Julien 已提交
2684
            elementNames = CheckTupleElementNames(cardinality, elementNames)
2685
            CheckTupleElementLocations(cardinality, elementLocations)
V
VSadov 已提交
2686

2687 2688 2689
            Return TupleTypeSymbol.Create(
                locationOpt:=Nothing,
                tupleCompatibleType:=underlyingType.EnsureVbSymbolOrNothing(Of NamedTypeSymbol)(NameOf(underlyingType)),
2690
                elementLocations:=elementLocations,
2691 2692
                elementNames:=elementNames,
                errorPositions:=Nothing)
2693 2694
        End Function

P
Pilchie 已提交
2695 2696 2697 2698
        Protected Overrides Function CommonCreatePointerTypeSymbol(elementType As ITypeSymbol) As IPointerTypeSymbol
            Throw New NotSupportedException(VBResources.ThereAreNoPointerTypesInVB)
        End Function

2699 2700
        Protected Overrides Function CommonCreateAnonymousTypeSymbol(
                memberTypes As ImmutableArray(Of ITypeSymbol),
2701 2702 2703
                memberNames As ImmutableArray(Of String),
                memberLocations As ImmutableArray(Of Location),
                memberIsReadOnly As ImmutableArray(Of Boolean)) As INamedTypeSymbol
2704

C
CyrusNajmabadi 已提交
2705
            Dim i = 0
2706
            For Each t In memberTypes
C
CyrusNajmabadi 已提交
2707
                t.EnsureVbSymbolOrNothing(Of TypeSymbol)($"{NameOf(memberTypes)}({i})")
2708

C
CyrusNajmabadi 已提交
2709
                i = i + 1
2710 2711
            Next

2712 2713 2714 2715 2716 2717 2718 2719 2720
            Dim fields = ArrayBuilder(Of AnonymousTypeField).GetInstance()

            For i = 0 To memberTypes.Length - 1
                Dim type = memberTypes(i)
                Dim name = memberNames(i)
                Dim loc = If(memberLocations.IsDefault, Location.None, memberLocations(i))
                Dim isReadOnly = memberIsReadOnly.IsDefault OrElse memberIsReadOnly(i)
                fields.Add(New AnonymousTypeField(name, DirectCast(type, TypeSymbol), loc, isReadOnly))
            Next
2721

2722 2723
            Dim descriptor = New AnonymousTypeDescriptor(
                fields.ToImmutableAndFree(), Location.None, isImplicitlyDeclared:=False)
2724 2725 2726
            Return Me.AnonymousTypeManager.ConstructAnonymousTypeSymbol(descriptor)
        End Function

P
Pilchie 已提交
2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742
        Protected Overrides ReadOnly Property CommonDynamicType As ITypeSymbol
            Get
                Throw New NotSupportedException(VBResources.ThereIsNoDynamicTypeInVB)
            End Get
        End Property

        Protected Overrides ReadOnly Property CommonObjectType As INamedTypeSymbol
            Get
                Return Me.ObjectType
            End Get
        End Property

        Protected Overrides Function CommonGetEntryPoint(cancellationToken As CancellationToken) As IMethodSymbol
            Return Me.GetEntryPoint(cancellationToken)
        End Function

H
heejaechang 已提交
2743
        ''' <summary>
C
Cyrus Najmabadi 已提交
2744
        ''' Return true if there is a source declaration symbol name that meets given predicate.
H
heejaechang 已提交
2745 2746 2747
        ''' </summary>
        Public Overrides Function ContainsSymbolsWithName(predicate As Func(Of String, Boolean), Optional filter As SymbolFilter = SymbolFilter.TypeAndMember, Optional cancellationToken As CancellationToken = Nothing) As Boolean
            If predicate Is Nothing Then
2748
                Throw New ArgumentNullException(NameOf(predicate))
H
heejaechang 已提交
2749 2750 2751
            End If

            If filter = SymbolFilter.None Then
2752
                Throw New ArgumentException(VBResources.NoNoneSearchCriteria, NameOf(filter))
H
heejaechang 已提交
2753 2754
            End If

2755
            Return DeclarationTable.ContainsName(MergedRootDeclaration, predicate, filter, cancellationToken)
H
heejaechang 已提交
2756 2757 2758 2759 2760 2761 2762
        End Function

        ''' <summary>
        ''' Return source declaration symbols whose name meets given predicate.
        ''' </summary>
        Public Overrides Function GetSymbolsWithName(predicate As Func(Of String, Boolean), Optional filter As SymbolFilter = SymbolFilter.TypeAndMember, Optional cancellationToken As CancellationToken = Nothing) As IEnumerable(Of ISymbol)
            If predicate Is Nothing Then
2763
                Throw New ArgumentNullException(NameOf(predicate))
H
heejaechang 已提交
2764 2765 2766
            End If

            If filter = SymbolFilter.None Then
2767
                Throw New ArgumentException(VBResources.NoNoneSearchCriteria, NameOf(filter))
H
heejaechang 已提交
2768 2769
            End If

C
Cyrus Najmabadi 已提交
2770 2771 2772
            Return New PredicateSymbolSearcher(Me, filter, predicate, cancellationToken).GetSymbolsWithName()
        End Function

2773
#Disable Warning RS0026 ' Do not add multiple public overloads with optional parameters
C
Cyrus Najmabadi 已提交
2774
        ''' <summary>
C
Cyrus Najmabadi 已提交
2775
        ''' Return true if there is a source declaration symbol name that matches the provided name.
2776 2777 2778
        ''' This may be faster than <see cref="ContainsSymbolsWithName(Func(Of String, Boolean),
        ''' SymbolFilter, CancellationToken)"/> when predicate is just a simple string check.
        ''' <paramref name="name"/> is case insensitive.
C
Cyrus Najmabadi 已提交
2779
        ''' </summary>
2780
        Public Overrides Function ContainsSymbolsWithName(name As String, Optional filter As SymbolFilter = SymbolFilter.TypeAndMember, Optional cancellationToken As CancellationToken = Nothing) As Boolean
2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            If filter = SymbolFilter.None Then
                Throw New ArgumentException(VBResources.NoNoneSearchCriteria, NameOf(filter))
            End If

            Return DeclarationTable.ContainsName(MergedRootDeclaration, name, filter, cancellationToken)
        End Function

2792
        Public Overrides Function GetSymbolsWithName(name As String, Optional filter As SymbolFilter = SymbolFilter.TypeAndMember, Optional cancellationToken As CancellationToken = Nothing) As IEnumerable(Of ISymbol)
C
Cyrus Najmabadi 已提交
2793 2794 2795 2796 2797 2798 2799 2800 2801
            If name Is Nothing Then
                Throw New ArgumentNullException(NameOf(name))
            End If

            If filter = SymbolFilter.None Then
                Throw New ArgumentException(VBResources.NoNoneSearchCriteria, NameOf(filter))
            End If

            Return New NameSymbolSearcher(Me, filter, name, cancellationToken).GetSymbolsWithName()
H
heejaechang 已提交
2802
        End Function
2803
#Enable Warning RS0026 ' Do not add multiple public overloads with optional parameters
2804

2805 2806 2807 2808 2809 2810 2811 2812 2813 2814
        Friend Overrides Function IsUnreferencedAssemblyIdentityDiagnosticCode(code As Integer) As Boolean
            Select Case code
                Case ERRID.ERR_UnreferencedAssemblyEvent3,
                     ERRID.ERR_UnreferencedAssembly3
                    Return True

                Case Else
                    Return False
            End Select
        End Function
2815

P
Pilchie 已提交
2816 2817
#End Region

C
Cyrus Najmabadi 已提交
2818
        Private MustInherit Class AbstractSymbolSearcher
C
Cyrus Najmabadi 已提交
2819
            Private ReadOnly _cache As PooledDictionary(Of Declaration, NamespaceOrTypeSymbol)
2820
            Private ReadOnly _compilation As VisualBasicCompilation
C
Cyrus Najmabadi 已提交
2821 2822 2823 2824
            Private ReadOnly _includeNamespace As Boolean
            Private ReadOnly _includeType As Boolean
            Private ReadOnly _includeMember As Boolean
            Private ReadOnly _cancellationToken As CancellationToken
H
heejaechang 已提交
2825

C
Cyrus Najmabadi 已提交
2826
            Public Sub New(compilation As VisualBasicCompilation, filter As SymbolFilter, cancellationToken As CancellationToken)
C
Cyrus Najmabadi 已提交
2827
                _cache = PooledDictionary(Of Declaration, NamespaceOrTypeSymbol).GetInstance()
C
Cyrus Najmabadi 已提交
2828
                _compilation = compilation
H
heejaechang 已提交
2829

C
Cyrus Najmabadi 已提交
2830 2831 2832 2833 2834
                _includeNamespace = (filter And SymbolFilter.Namespace) = SymbolFilter.Namespace
                _includeType = (filter And SymbolFilter.Type) = SymbolFilter.Type
                _includeMember = (filter And SymbolFilter.Member) = SymbolFilter.Member

                _cancellationToken = cancellationToken
H
heejaechang 已提交
2835 2836
            End Sub

C
Cyrus Najmabadi 已提交
2837 2838 2839 2840
            Protected MustOverride Function Matches(name As String) As Boolean
            Protected MustOverride Function ShouldCheckTypeForMembers(typeDeclaration As MergedTypeDeclaration) As Boolean

            Public Function GetSymbolsWithName() As IEnumerable(Of ISymbol)
H
heejaechang 已提交
2841
                Dim result = New HashSet(Of ISymbol)()
C
Cyrus Najmabadi 已提交
2842
                Dim spine = ArrayBuilder(Of MergedNamespaceOrTypeDeclaration).GetInstance()
H
heejaechang 已提交
2843

C
Cyrus Najmabadi 已提交
2844
                AppendSymbolsWithName(spine, _compilation.MergedRootDeclaration, result)
H
heejaechang 已提交
2845

C
Cyrus Najmabadi 已提交
2846 2847
                spine.Free()
                _cache.Free()
H
heejaechang 已提交
2848 2849 2850 2851 2852

                Return result
            End Function

            Private Sub AppendSymbolsWithName(
C
Cyrus Najmabadi 已提交
2853
                spine As ArrayBuilder(Of MergedNamespaceOrTypeDeclaration), current As MergedNamespaceOrTypeDeclaration, [set] As HashSet(Of ISymbol))
H
heejaechang 已提交
2854 2855

                If current.Kind = DeclarationKind.Namespace Then
C
Cyrus Najmabadi 已提交
2856
                    If _includeNamespace AndAlso Matches(current.Name) Then
H
heejaechang 已提交
2857
                        Dim container = GetSpineSymbol(spine)
2858 2859 2860 2861
                        Dim symbol = GetSymbol(container, current)
                        If symbol IsNot Nothing Then
                            [set].Add(symbol)
                        End If
H
heejaechang 已提交
2862 2863
                    End If
                Else
C
Cyrus Najmabadi 已提交
2864
                    If _includeType AndAlso Matches(current.Name) Then
H
heejaechang 已提交
2865
                        Dim container = GetSpineSymbol(spine)
2866 2867 2868 2869
                        Dim symbol = GetSymbol(container, current)
                        If symbol IsNot Nothing Then
                            [set].Add(symbol)
                        End If
H
heejaechang 已提交
2870 2871
                    End If

C
Cyrus Najmabadi 已提交
2872 2873 2874 2875 2876
                    If _includeMember Then
                        Dim typeDeclaration = DirectCast(current, MergedTypeDeclaration)
                        If ShouldCheckTypeForMembers(typeDeclaration) Then
                            AppendMemberSymbolsWithName(spine, typeDeclaration, [set])
                        End If
H
heejaechang 已提交
2877 2878 2879 2880
                    End If
                End If

                spine.Add(current)
C
Cyrus Najmabadi 已提交
2881 2882 2883 2884 2885 2886
                For Each child In current.Children
                    Dim mergedNamespaceOrType = TryCast(child, MergedNamespaceOrTypeDeclaration)
                    If mergedNamespaceOrType IsNot Nothing Then
                        If _includeMember OrElse _includeType OrElse child.Kind = DeclarationKind.Namespace Then
                            AppendSymbolsWithName(spine, mergedNamespaceOrType, [set])
                        End If
H
heejaechang 已提交
2887 2888 2889 2890 2891 2892 2893
                    End If
                Next

                spine.RemoveAt(spine.Count - 1)
            End Sub

            Private Sub AppendMemberSymbolsWithName(
C
Cyrus Najmabadi 已提交
2894
                spine As ArrayBuilder(Of MergedNamespaceOrTypeDeclaration), mergedType As MergedTypeDeclaration, [set] As HashSet(Of ISymbol))
H
heejaechang 已提交
2895

C
Cyrus Najmabadi 已提交
2896 2897
                _cancellationToken.ThrowIfCancellationRequested()
                spine.Add(mergedType)
H
heejaechang 已提交
2898 2899 2900

                Dim container As NamespaceOrTypeSymbol = Nothing
                For Each name In mergedType.MemberNames
C
Cyrus Najmabadi 已提交
2901
                    If Matches(name) Then
H
heejaechang 已提交
2902
                        container = If(container, GetSpineSymbol(spine))
2903 2904 2905
                        If container IsNot Nothing Then
                            [set].UnionWith(container.GetMembers(name))
                        End If
H
heejaechang 已提交
2906 2907 2908 2909 2910 2911
                    End If
                Next

                spine.RemoveAt(spine.Count - 1)
            End Sub

C
Cyrus Najmabadi 已提交
2912
            Private Function GetSpineSymbol(spine As ArrayBuilder(Of MergedNamespaceOrTypeDeclaration)) As NamespaceOrTypeSymbol
H
heejaechang 已提交
2913 2914 2915 2916 2917 2918 2919 2920 2921
                If spine.Count = 0 Then
                    Return Nothing
                End If

                Dim symbol = GetCachedSymbol(spine(spine.Count - 1))
                If symbol IsNot Nothing Then
                    Return symbol
                End If

2922
                Dim current = TryCast(Me._compilation.GlobalNamespace, NamespaceOrTypeSymbol)
H
heejaechang 已提交
2923 2924 2925 2926 2927 2928 2929 2930 2931
                For i = 1 To spine.Count - 1
                    current = GetSymbol(current, spine(i))
                Next

                Return current
            End Function

            Private Function GetCachedSymbol(declaration As MergedNamespaceOrTypeDeclaration) As NamespaceOrTypeSymbol
                Dim symbol As NamespaceOrTypeSymbol = Nothing
2932
                If Me._cache.TryGetValue(declaration, symbol) Then
H
heejaechang 已提交
2933 2934 2935 2936 2937 2938 2939 2940
                    Return symbol
                End If

                Return Nothing
            End Function

            Private Function GetSymbol(container As NamespaceOrTypeSymbol, declaration As MergedNamespaceOrTypeDeclaration) As NamespaceOrTypeSymbol
                If container Is Nothing Then
2941
                    Return Me._compilation.GlobalNamespace
H
heejaechang 已提交
2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961
                End If

                Dim symbol = GetCachedSymbol(declaration)
                If symbol IsNot Nothing Then
                    Return symbol
                End If

                If declaration.Kind = DeclarationKind.Namespace Then
                    AddCache(container.GetMembers(declaration.Name).OfType(Of NamespaceOrTypeSymbol)())
                Else
                    AddCache(container.GetTypeMembers(declaration.Name))
                End If

                Return GetCachedSymbol(declaration)
            End Function

            Private Sub AddCache(symbols As IEnumerable(Of NamespaceOrTypeSymbol))
                For Each symbol In symbols
                    Dim mergedNamespace = TryCast(symbol, MergedNamespaceSymbol)
                    If mergedNamespace IsNot Nothing Then
2962
                        Me._cache(mergedNamespace.ConstituentNamespaces.OfType(Of SourceNamespaceSymbol).First().MergedDeclaration) = symbol
H
heejaechang 已提交
2963 2964 2965 2966 2967
                        Continue For
                    End If

                    Dim sourceNamespace = TryCast(symbol, SourceNamespaceSymbol)
                    If sourceNamespace IsNot Nothing Then
2968
                        Me._cache(sourceNamespace.MergedDeclaration) = sourceNamespace
H
heejaechang 已提交
2969 2970 2971 2972 2973
                        Continue For
                    End If

                    Dim sourceType = TryCast(symbol, SourceMemberContainerTypeSymbol)
                    If sourceType IsNot Nothing Then
2974
                        Me._cache(sourceType.TypeDeclaration) = sourceType
H
heejaechang 已提交
2975 2976 2977 2978
                    End If
                Next
            End Sub
        End Class
C
Cyrus Najmabadi 已提交
2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014

        Private Class PredicateSymbolSearcher
            Inherits AbstractSymbolSearcher

            Private ReadOnly _predicate As Func(Of String, Boolean)

            Public Sub New(
                compilation As VisualBasicCompilation, filter As SymbolFilter, predicate As Func(Of String, Boolean), cancellationToken As CancellationToken)
                MyBase.New(compilation, filter, cancellationToken)

                _predicate = predicate
            End Sub

            Protected Overrides Function ShouldCheckTypeForMembers(current As MergedTypeDeclaration) As Boolean
                Return True
            End Function

            Protected Overrides Function Matches(name As String) As Boolean
                Return _predicate(name)
            End Function
        End Class

        Private Class NameSymbolSearcher
            Inherits AbstractSymbolSearcher

            Private ReadOnly _name As String

            Public Sub New(
                compilation As VisualBasicCompilation, filter As SymbolFilter, name As String, cancellationToken As CancellationToken)
                MyBase.New(compilation, filter, cancellationToken)

                _name = name
            End Sub

            Protected Overrides Function ShouldCheckTypeForMembers(current As MergedTypeDeclaration) As Boolean
                For Each typeDecl In current.Declarations
3015 3016 3017
                    If typeDecl.MemberNames.Contains(_name) Then
                        Return True
                    End If
C
Cyrus Najmabadi 已提交
3018 3019 3020 3021 3022 3023 3024 3025 3026
                Next

                Return False
            End Function

            Protected Overrides Function Matches(name As String) As Boolean
                Return IdentifierComparison.Equals(_name, name)
            End Function
        End Class
P
Pilchie 已提交
3027
    End Class
3028
End Namespace