EmitHelpers.vb 6.3 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.
2 3 4

Imports System.Collections.Immutable
Imports System.IO
5
Imports System.Reflection.Metadata
6
Imports System.Threading
7
Imports Microsoft.CodeAnalysis
8 9 10 11 12
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Emit

Namespace Microsoft.CodeAnalysis.VisualBasic.Emit

13
    Friend Module EmitHelpers
14 15

        Friend Function EmitDifference(
A
angocke 已提交
16
            compilation As VisualBasicCompilation,
17 18
            baseline As EmitBaseline,
            edits As IEnumerable(Of SemanticEdit),
19
            isAddedSymbol As Func(Of ISymbol, Boolean),
20 21 22
            metadataStream As Stream,
            ilStream As Stream,
            pdbStream As Stream,
A
angocke 已提交
23
            updatedMethods As ICollection(Of MethodDefinitionHandle),
24 25 26 27 28 29 30 31 32 33 34
            testData As CompilationTestData,
            cancellationToken As CancellationToken) As EmitDifferenceResult

            Dim moduleVersionId As Guid
            Try
                moduleVersionId = baseline.OriginalMetadata.GetModuleVersionId()
            Catch ex As BadImageFormatException
                ' Return MakeEmitResult(success:=False, diagnostics:= ..., baseline:=Nothing)
                Throw
            End Try

35
            Dim pdbName = FileNameUtilities.ChangeExtension(compilation.SourceModule.Name, "pdb")
36
            Dim diagnostics = DiagnosticBag.GetInstance()
37 38

            Dim emitOpts = EmitOptions.Default
39
            Dim runtimeMDVersion = compilation.GetRuntimeMetadataVersion()
40
            Dim serializationProperties = compilation.ConstructModuleSerializationProperties(emitOpts, runtimeMDVersion, moduleVersionId)
41 42
            Dim manifestResources = SpecializedCollections.EmptyEnumerable(Of ResourceDescription)()

43
            Dim moduleBeingBuilt = New PEDeltaAssemblyBuilder(
44
                    compilation.SourceAssembly,
45
                    emitOptions:=emitOpts,
46 47 48 49
                    outputKind:=compilation.Options.OutputKind,
                    serializationProperties:=serializationProperties,
                    manifestResources:=manifestResources,
                    previousGeneration:=baseline,
50 51
                    edits:=edits,
                    isAddedSymbol:=isAddedSymbol)
52

53 54 55 56
            If testData IsNot Nothing Then
                moduleBeingBuilt.SetMethodTestData(testData.Methods)
                testData.Module = moduleBeingBuilt
            End If
57

58 59
            Dim definitionMap = moduleBeingBuilt.PreviousDefinitions
            Dim changes = moduleBeingBuilt.Changes
60

61 62
            Dim newBaseline As EmitBaseline = Nothing

63 64 65
            If compilation.Compile(moduleBeingBuilt,
                                   win32Resources:=Nothing,
                                   xmlDocStream:=Nothing,
66
                                   emittingPdb:=True,
67
                                   diagnostics:=diagnostics,
68 69
                                   filterOpt:=AddressOf changes.RequiresCompilation,
                                   cancellationToken:=cancellationToken) Then
70

71 72 73
                ' Map the definitions from the previous compilation to the current compilation.
                ' This must be done after compiling above since synthesized definitions
                ' (generated when compiling method bodies) may be required.
74 75 76 77 78 79 80 81 82 83 84 85 86 87
                Dim mappedBaseline = MapToCompilation(compilation, moduleBeingBuilt)

                newBaseline = compilation.SerializeToDeltaStreams(
                    moduleBeingBuilt,
                    mappedBaseline,
                    definitionMap,
                    changes,
                    metadataStream,
                    ilStream,
                    pdbStream,
                    updatedMethods,
                    diagnostics,
                    testData?.SymWriterFactory,
                    cancellationToken)
88 89
            End If

90 91 92 93
            Return New EmitDifferenceResult(
                success:=newBaseline IsNot Nothing,
                diagnostics:=diagnostics.ToReadOnlyAndFree(),
                baseline:=newBaseline)
94 95 96
        End Function

        Friend Function MapToCompilation(
A
angocke 已提交
97
            compilation As VisualBasicCompilation,
98 99 100 101 102 103 104 105 106 107 108 109
            moduleBeingBuilt As PEDeltaAssemblyBuilder) As EmitBaseline

            Dim previousGeneration = moduleBeingBuilt.PreviousGeneration
            Debug.Assert(previousGeneration.Compilation IsNot compilation)

            If previousGeneration.Ordinal = 0 Then
                ' Initial generation, nothing to map. (Since the initial generation
                ' is always loaded from metadata in the context of the current
                ' compilation, there's no separate mapping step.)
                Return previousGeneration
            End If

110 111 112
            Dim currentSynthesizedMembers = moduleBeingBuilt.GetSynthesizedMembers()

            ' Mapping from previous compilation to the current.
113 114 115 116 117
            Dim anonymousTypeMap = moduleBeingBuilt.GetAnonymousTypeMap()
            Dim sourceAssembly = DirectCast(previousGeneration.Compilation, VisualBasicCompilation).SourceAssembly
            Dim sourceContext = New EmitContext(DirectCast(previousGeneration.PEModuleBuilder, PEModuleBuilder), Nothing, New DiagnosticBag())
            Dim otherContext = New EmitContext(moduleBeingBuilt, Nothing, New DiagnosticBag())

118
            Dim matcher = New VisualBasicSymbolMatcher(
119 120 121 122 123 124 125 126 127
                anonymousTypeMap,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                currentSynthesizedMembers)

            Dim mappedSynthesizedMembers = matcher.MapSynthesizedMembers(previousGeneration.SynthesizedMembers, currentSynthesizedMembers)

C
Charles Stoner 已提交
128
            ' TODO can we reuse some data from the previous matcher?
129 130 131 132 133 134 135 136 137
            Dim matcherWithAllSynthesizedMembers = New VisualBasicSymbolMatcher(
                anonymousTypeMap,
                sourceAssembly,
                sourceContext,
                compilation.SourceAssembly,
                otherContext,
                mappedSynthesizedMembers)

            Return matcherWithAllSynthesizedMembers.MapBaselineToCompilation(
138
                previousGeneration,
139 140
                compilation,
                moduleBeingBuilt,
141
                mappedSynthesizedMembers)
142 143
        End Function
    End Module
144
End Namespace