提交 7dffad1a 编写于 作者: T Tomas Matousek

Fixes a couple of issues around import scope compilation

上级 c7ab77d0
...@@ -23,7 +23,6 @@ internal struct ProcessedFieldInitializers ...@@ -23,7 +23,6 @@ internal struct ProcessedFieldInitializers
SourceMemberContainerTypeSymbol typeSymbol, SourceMemberContainerTypeSymbol typeSymbol,
MethodSymbol scriptCtor, MethodSymbol scriptCtor,
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> fieldInitializers, ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> fieldInitializers,
bool generateDebugInfo,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
ref ProcessedFieldInitializers processedInitializers) //by ref so that we can store the results of lowering ref ProcessedFieldInitializers processedInitializers) //by ref so that we can store the results of lowering
{ {
...@@ -33,7 +32,7 @@ internal struct ProcessedFieldInitializers ...@@ -33,7 +32,7 @@ internal struct ProcessedFieldInitializers
ImportChain firstImportChain; ImportChain firstImportChain;
processedInitializers.BoundInitializers = BindFieldInitializers(typeSymbol, scriptCtor, fieldInitializers, processedInitializers.BoundInitializers = BindFieldInitializers(typeSymbol, scriptCtor, fieldInitializers,
diagsForInstanceInitializers, generateDebugInfo, out firstImportChain); diagsForInstanceInitializers, out firstImportChain);
processedInitializers.HasErrors = diagsForInstanceInitializers.HasAnyErrors(); processedInitializers.HasErrors = diagsForInstanceInitializers.HasAnyErrors();
processedInitializers.FirstImportChain = firstImportChain; processedInitializers.FirstImportChain = firstImportChain;
...@@ -50,7 +49,6 @@ internal struct ProcessedFieldInitializers ...@@ -50,7 +49,6 @@ internal struct ProcessedFieldInitializers
MethodSymbol scriptCtor, MethodSymbol scriptCtor,
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers, ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
bool generateDebugInfo,
out ImportChain firstImportChain) out ImportChain firstImportChain)
{ {
if (initializers.IsEmpty) if (initializers.IsEmpty)
...@@ -64,11 +62,11 @@ internal struct ProcessedFieldInitializers ...@@ -64,11 +62,11 @@ internal struct ProcessedFieldInitializers
if ((object)scriptCtor == null) if ((object)scriptCtor == null)
{ {
BindRegularCSharpFieldInitializers(compilation, initializers, boundInitializers, diagnostics, generateDebugInfo, out firstImportChain); BindRegularCSharpFieldInitializers(compilation, initializers, boundInitializers, diagnostics, out firstImportChain);
} }
else else
{ {
BindScriptFieldInitializers(compilation, scriptCtor, initializers, boundInitializers, diagnostics, generateDebugInfo, out firstImportChain); BindScriptFieldInitializers(compilation, scriptCtor, initializers, boundInitializers, diagnostics, out firstImportChain);
} }
return boundInitializers.ToImmutableAndFree(); return boundInitializers.ToImmutableAndFree();
...@@ -83,7 +81,6 @@ internal struct ProcessedFieldInitializers ...@@ -83,7 +81,6 @@ internal struct ProcessedFieldInitializers
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers, ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers,
ArrayBuilder<BoundInitializer> boundInitializers, ArrayBuilder<BoundInitializer> boundInitializers,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
bool generateDebugInfo,
out ImportChain firstDebugImports) out ImportChain firstDebugImports)
{ {
firstDebugImports = null; firstDebugImports = null;
...@@ -118,7 +115,7 @@ internal struct ProcessedFieldInitializers ...@@ -118,7 +115,7 @@ internal struct ProcessedFieldInitializers
Debug.Assert(parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType || //should be the binder for the type Debug.Assert(parentBinder.ContainingMemberOrLambda == fieldSymbol.ContainingType || //should be the binder for the type
fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios fieldSymbol.ContainingType.IsImplicitClass); //however, we also allow fields in namespaces to help support script scenarios
if (generateDebugInfo && firstDebugImports == null) if (firstDebugImports == null)
{ {
firstDebugImports = parentBinder.ImportChain; firstDebugImports = parentBinder.ImportChain;
} }
...@@ -138,7 +135,7 @@ internal struct ProcessedFieldInitializers ...@@ -138,7 +135,7 @@ internal struct ProcessedFieldInitializers
/// </summary> /// </summary>
private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor, private static void BindScriptFieldInitializers(CSharpCompilation compilation, MethodSymbol scriptCtor,
ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics, ImmutableArray<ImmutableArray<FieldOrPropertyInitializer>> initializers, ArrayBuilder<BoundInitializer> boundInitializers, DiagnosticBag diagnostics,
bool generateDebugInfo, out ImportChain firstDebugImports) out ImportChain firstDebugImports)
{ {
Debug.Assert((object)scriptCtor != null); Debug.Assert((object)scriptCtor != null);
...@@ -177,7 +174,7 @@ internal struct ProcessedFieldInitializers ...@@ -177,7 +174,7 @@ internal struct ProcessedFieldInitializers
Binder scriptClassBinder = binderFactory.GetBinder(initializerNode); Binder scriptClassBinder = binderFactory.GetBinder(initializerNode);
Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass); Debug.Assert(((ImplicitNamedTypeSymbol)scriptClassBinder.ContainingMemberOrLambda).IsScriptClass);
if (generateDebugInfo && firstDebugImports == null) if (firstDebugImports == null)
{ {
firstDebugImports = scriptClassBinder.ImportChain; firstDebugImports = scriptClassBinder.ImportChain;
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.Emit;
namespace Microsoft.CodeAnalysis.CSharp namespace Microsoft.CodeAnalysis.CSharp
{ {
...@@ -27,17 +22,29 @@ public ImportChain(Imports imports, ImportChain parentOpt) ...@@ -27,17 +22,29 @@ public ImportChain(Imports imports, ImportChain parentOpt)
ParentOpt = parentOpt; ParentOpt = parentOpt;
} }
ImmutableArray<Cci.UsedNamespaceOrType> Cci.IImportScope.GetUsedNamespaces(EmitContext context) ImmutableArray<Cci.UsedNamespaceOrType> Cci.IImportScope.GetUsedNamespaces()
{ {
if (_lazyTranslatedImports.IsDefault) // The imports should have been translated during code gen.
Debug.Assert(!_lazyTranslatedImports.IsDefault);
return _lazyTranslatedImports;
}
public Cci.IImportScope Translate(Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics)
{
for (var scope = this; scope != null; scope = scope.ParentOpt)
{ {
ImmutableInterlocked.InterlockedInitialize(ref _lazyTranslatedImports, TranslateImports(context)); if (!scope._lazyTranslatedImports.IsDefault)
{
break;
} }
return _lazyTranslatedImports; ImmutableInterlocked.InterlockedInitialize(ref scope._lazyTranslatedImports, scope.TranslateImports(moduleBuilder, diagnostics));
}
return this;
} }
private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext context) private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics)
{ {
var usedNamespaces = ArrayBuilder<Cci.UsedNamespaceOrType>.GetInstance(); var usedNamespaces = ArrayBuilder<Cci.UsedNamespaceOrType>.GetInstance();
...@@ -61,12 +68,13 @@ private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext con ...@@ -61,12 +68,13 @@ private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext con
if (namespaceOrType.IsNamespace) if (namespaceOrType.IsNamespace)
{ {
var ns = (NamespaceSymbol)namespaceOrType; var ns = (NamespaceSymbol)namespaceOrType;
var assemblyRef = TryGetAssemblyScope(context, ns); var assemblyRef = TryGetAssemblyScope(ns, moduleBuilder, diagnostics);
usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns, assemblyRef)); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns, assemblyRef));
} }
else else if (!namespaceOrType.ContainingAssembly.IsLinked)
{ {
var typeRef = GetTypeReference(context, (TypeSymbol)namespaceOrType); // We skip alias imports of embedded types to be consistent with imports of aliased embedded types and with VB.
var typeRef = GetTypeReference((TypeSymbol)namespaceOrType, nsOrType.UsingDirective, moduleBuilder, diagnostics);
usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef)); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef));
} }
} }
...@@ -79,18 +87,21 @@ private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext con ...@@ -79,18 +87,21 @@ private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext con
{ {
var alias = pair.Key; var alias = pair.Key;
var symbol = pair.Value.Alias; var symbol = pair.Value.Alias;
var syntax = pair.Value.UsingDirective;
Debug.Assert(!symbol.IsExtern); Debug.Assert(!symbol.IsExtern);
NamespaceOrTypeSymbol target = symbol.Target; NamespaceOrTypeSymbol target = symbol.Target;
if (target.Kind == SymbolKind.Namespace) if (target.Kind == SymbolKind.Namespace)
{ {
var ns = (NamespaceSymbol)target; var ns = (NamespaceSymbol)target;
var assemblyRef = TryGetAssemblyScope(context, ns); var assemblyRef = TryGetAssemblyScope(ns, moduleBuilder, diagnostics);
usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns, assemblyRef, alias)); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateNamespace(ns, assemblyRef, alias));
} }
else else if (!target.ContainingAssembly.IsLinked)
{ {
var typeRef = GetTypeReference(context, (TypeSymbol)target); // We skip alias imports of embedded types to avoid breaking existing code that
// imports types that can't be embedded but doesn't use them anywhere else in the code.
var typeRef = GetTypeReference((TypeSymbol)target, syntax, moduleBuilder, diagnostics);
usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef, alias)); usedNamespaces.Add(Cci.UsedNamespaceOrType.CreateType(typeRef, alias));
} }
} }
...@@ -99,17 +110,17 @@ private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext con ...@@ -99,17 +110,17 @@ private ImmutableArray<Cci.UsedNamespaceOrType> TranslateImports(EmitContext con
return usedNamespaces.ToImmutableAndFree(); return usedNamespaces.ToImmutableAndFree();
} }
private static Cci.ITypeReference GetTypeReference(EmitContext context, TypeSymbol type) private static Cci.ITypeReference GetTypeReference(TypeSymbol type, SyntaxNode syntaxNode, Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics)
{ {
return context.ModuleBuilder.Translate(type, context.SyntaxNodeOpt, context.Diagnostics); return moduleBuilder.Translate(type, syntaxNode, diagnostics);
} }
private Cci.IAssemblyReference TryGetAssemblyScope(EmitContext context, NamespaceSymbol @namespace) private Cci.IAssemblyReference TryGetAssemblyScope(NamespaceSymbol @namespace, Emit.PEModuleBuilder moduleBuilder, DiagnosticBag diagnostics)
{ {
AssemblySymbol containingAssembly = @namespace.ContainingAssembly; AssemblySymbol containingAssembly = @namespace.ContainingAssembly;
if ((object)containingAssembly != null && (object)containingAssembly != context.ModuleBuilder.CommonCompilation.Assembly) if ((object)containingAssembly != null && (object)containingAssembly != moduleBuilder.CommonCompilation.Assembly)
{ {
var referenceManager = ((CSharpCompilation)context.ModuleBuilder.CommonCompilation).GetBoundReferenceManager(); var referenceManager = ((CSharpCompilation)moduleBuilder.CommonCompilation).GetBoundReferenceManager();
foreach (var referencedAssembly in referenceManager.ReferencedAssembliesMap.Values) foreach (var referencedAssembly in referenceManager.ReferencedAssembliesMap.Values)
{ {
...@@ -117,7 +128,7 @@ private Cci.IAssemblyReference TryGetAssemblyScope(EmitContext context, Namespac ...@@ -117,7 +128,7 @@ private Cci.IAssemblyReference TryGetAssemblyScope(EmitContext context, Namespac
{ {
if (!referencedAssembly.DeclarationsAccessibleWithoutAlias()) if (!referencedAssembly.DeclarationsAccessibleWithoutAlias())
{ {
return context.ModuleBuilder.Translate(containingAssembly, context.Diagnostics); return moduleBuilder.Translate(containingAssembly, diagnostics);
} }
} }
} }
......
...@@ -70,7 +70,7 @@ private enum IndirectReturnState : byte ...@@ -70,7 +70,7 @@ private enum IndirectReturnState : byte
PEModuleBuilder moduleBuilder, PEModuleBuilder moduleBuilder,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
OptimizationLevel optimizations, OptimizationLevel optimizations,
bool emittingPdbs) bool emittingPdb)
{ {
Debug.Assert((object)method != null); Debug.Assert((object)method != null);
Debug.Assert(boundBody != null); Debug.Assert(boundBody != null);
...@@ -98,7 +98,7 @@ private enum IndirectReturnState : byte ...@@ -98,7 +98,7 @@ private enum IndirectReturnState : byte
// user code that can be stepped thru, or changed during EnC. // user code that can be stepped thru, or changed during EnC.
// //
// This setting only affects generating PDB sequence points, it shall not affect generated IL in any way. // This setting only affects generating PDB sequence points, it shall not affect generated IL in any way.
_emitPdbSequencePoints = emittingPdbs && method.GenerateDebugInfo; _emitPdbSequencePoints = emittingPdb && method.GenerateDebugInfo;
if (_optimizations == OptimizationLevel.Release) if (_optimizations == OptimizationLevel.Release)
{ {
......
...@@ -2322,7 +2322,7 @@ internal override StrongNameKeys StrongNameKeys ...@@ -2322,7 +2322,7 @@ internal override StrongNameKeys StrongNameKeys
CommonPEModuleBuilder moduleBuilder, CommonPEModuleBuilder moduleBuilder,
Stream win32Resources, Stream win32Resources,
Stream xmlDocStream, Stream xmlDocStream,
bool generateDebugInfo, bool emittingPdb,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
Predicate<ISymbol> filterOpt, Predicate<ISymbol> filterOpt,
CancellationToken cancellationToken) CancellationToken cancellationToken)
...@@ -2354,13 +2354,10 @@ internal override StrongNameKeys StrongNameKeys ...@@ -2354,13 +2354,10 @@ internal override StrongNameKeys StrongNameKeys
} }
else else
{ {
if (generateDebugInfo && moduleBeingBuilt != null) if (emittingPdb && !StartSourceChecksumCalculation(moduleBeingBuilt, diagnostics))
{
if (!StartSourceChecksumCalculation(moduleBeingBuilt, diagnostics))
{ {
return false; return false;
} }
}
// Perform initial bind of method bodies in spite of earlier errors. This is the same // Perform initial bind of method bodies in spite of earlier errors. This is the same
// behavior as when calling GetDiagnostics() // behavior as when calling GetDiagnostics()
...@@ -2371,7 +2368,7 @@ internal override StrongNameKeys StrongNameKeys ...@@ -2371,7 +2368,7 @@ internal override StrongNameKeys StrongNameKeys
MethodCompiler.CompileMethodBodies( MethodCompiler.CompileMethodBodies(
this, this,
moduleBeingBuilt, moduleBeingBuilt,
generateDebugInfo, emittingPdb,
hasDeclarationErrors, hasDeclarationErrors,
diagnostics: methodBodyDiagnosticBag, diagnostics: methodBodyDiagnosticBag,
filterOpt: filterOpt, filterOpt: filterOpt,
......
...@@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.CSharp ...@@ -21,7 +21,7 @@ namespace Microsoft.CodeAnalysis.CSharp
internal sealed class MethodCompiler : CSharpSymbolVisitor<TypeCompilationState, object> internal sealed class MethodCompiler : CSharpSymbolVisitor<TypeCompilationState, object>
{ {
private readonly CSharpCompilation _compilation; private readonly CSharpCompilation _compilation;
private readonly bool _generateDebugInfo; private readonly bool _emittingPdb;
private readonly CancellationToken _cancellationToken; private readonly CancellationToken _cancellationToken;
private readonly DiagnosticBag _diagnostics; private readonly DiagnosticBag _diagnostics;
private readonly bool _hasDeclarationErrors; private readonly bool _hasDeclarationErrors;
...@@ -73,7 +73,7 @@ private void SetGlobalErrorIfTrue(bool arg) ...@@ -73,7 +73,7 @@ private void SetGlobalErrorIfTrue(bool arg)
} }
// Internal for testing only. // Internal for testing only.
internal MethodCompiler(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuiltOpt, bool generateDebugInfo, bool hasDeclarationErrors, internal MethodCompiler(CSharpCompilation compilation, PEModuleBuilder moduleBeingBuiltOpt, bool emittingPdb, bool hasDeclarationErrors,
DiagnosticBag diagnostics, Predicate<Symbol> filterOpt, CancellationToken cancellationToken) DiagnosticBag diagnostics, Predicate<Symbol> filterOpt, CancellationToken cancellationToken)
{ {
Debug.Assert(compilation != null); Debug.Assert(compilation != null);
...@@ -81,7 +81,7 @@ private void SetGlobalErrorIfTrue(bool arg) ...@@ -81,7 +81,7 @@ private void SetGlobalErrorIfTrue(bool arg)
_compilation = compilation; _compilation = compilation;
_moduleBeingBuiltOpt = moduleBeingBuiltOpt; _moduleBeingBuiltOpt = moduleBeingBuiltOpt;
_generateDebugInfo = generateDebugInfo; _emittingPdb = emittingPdb;
_cancellationToken = cancellationToken; _cancellationToken = cancellationToken;
_diagnostics = diagnostics; _diagnostics = diagnostics;
_filterOpt = filterOpt; _filterOpt = filterOpt;
...@@ -89,7 +89,7 @@ private void SetGlobalErrorIfTrue(bool arg) ...@@ -89,7 +89,7 @@ private void SetGlobalErrorIfTrue(bool arg)
_hasDeclarationErrors = hasDeclarationErrors; _hasDeclarationErrors = hasDeclarationErrors;
SetGlobalErrorIfTrue(hasDeclarationErrors); SetGlobalErrorIfTrue(hasDeclarationErrors);
if (generateDebugInfo) if (emittingPdb)
{ {
_debugDocumentProvider = (path, basePath) => moduleBeingBuiltOpt.GetOrAddDebugDocument(path, basePath, CreateDebugDocumentForFile); _debugDocumentProvider = (path, basePath) => moduleBeingBuiltOpt.GetOrAddDebugDocument(path, basePath, CreateDebugDocumentForFile);
} }
...@@ -233,7 +233,7 @@ internal static MethodSymbol DefineScriptEntryPoint(CSharpCompilation compilatio ...@@ -233,7 +233,7 @@ internal static MethodSymbol DefineScriptEntryPoint(CSharpCompilation compilatio
diagnostics: diagnostics, diagnostics: diagnostics,
debugDocumentProvider: null, debugDocumentProvider: null,
importChainOpt: null, importChainOpt: null,
generateDebugInfo: false); emittingPdb: false);
moduleBeingBuilt.SetMethodBody(scriptEntryPoint, emittedBody); moduleBeingBuilt.SetMethodBody(scriptEntryPoint, emittedBody);
moduleBeingBuilt.AddSynthesizedDefinition(compilation.ScriptClass, scriptEntryPoint); moduleBeingBuilt.AddSynthesizedDefinition(compilation.ScriptClass, scriptEntryPoint);
...@@ -376,10 +376,10 @@ private void CompileNamedType(NamedTypeSymbol symbol) ...@@ -376,10 +376,10 @@ private void CompileNamedType(NamedTypeSymbol symbol)
if ((object)sourceTypeSymbol != null) if ((object)sourceTypeSymbol != null)
{ {
_cancellationToken.ThrowIfCancellationRequested(); _cancellationToken.ThrowIfCancellationRequested();
Binder.BindFieldInitializers(sourceTypeSymbol, scriptCtor, sourceTypeSymbol.StaticInitializers, _generateDebugInfo, _diagnostics, ref processedStaticInitializers); Binder.BindFieldInitializers(sourceTypeSymbol, scriptCtor, sourceTypeSymbol.StaticInitializers, _diagnostics, ref processedStaticInitializers);
_cancellationToken.ThrowIfCancellationRequested(); _cancellationToken.ThrowIfCancellationRequested();
Binder.BindFieldInitializers(sourceTypeSymbol, scriptCtor, sourceTypeSymbol.InstanceInitializers, _generateDebugInfo, _diagnostics, ref processedInstanceInitializers); Binder.BindFieldInitializers(sourceTypeSymbol, scriptCtor, sourceTypeSymbol.InstanceInitializers, _diagnostics, ref processedInstanceInitializers);
if (compilationState.Emitting) if (compilationState.Emitting)
{ {
...@@ -625,7 +625,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState) ...@@ -625,7 +625,7 @@ private void CompileSynthesizedMethods(TypeCompilationState compilationState)
diagnosticsThisMethod, diagnosticsThisMethod,
_debugDocumentProvider, _debugDocumentProvider,
methodWithBody.ImportChainOpt, methodWithBody.ImportChainOpt,
generateDebugInfo: _generateDebugInfo && method.GenerateDebugInfo); emittingPdb: _emittingPdb);
} }
_diagnostics.AddRange(diagnosticsThisMethod); _diagnostics.AddRange(diagnosticsThisMethod);
...@@ -719,7 +719,7 @@ private void CompileFieldLikeEventAccessor(SourceEventSymbol eventSymbol, bool i ...@@ -719,7 +719,7 @@ private void CompileFieldLikeEventAccessor(SourceEventSymbol eventSymbol, bool i
diagnostics: diagnosticsThisMethod, diagnostics: diagnosticsThisMethod,
debugDocumentProvider: _debugDocumentProvider, debugDocumentProvider: _debugDocumentProvider,
importChainOpt: null, importChainOpt: null,
generateDebugInfo: false); emittingPdb: false);
_moduleBeingBuiltOpt.SetMethodBody(accessor, emittedBody); _moduleBeingBuiltOpt.SetMethodBody(accessor, emittedBody);
// Definition is already in the symbol table, so don't call moduleBeingBuilt.AddCompilerGeneratedDefinition // Definition is already in the symbol table, so don't call moduleBeingBuilt.AddCompilerGeneratedDefinition
...@@ -841,7 +841,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -841,7 +841,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
includeInitializersInBody = !processedInitializers.BoundInitializers.IsDefaultOrEmpty && includeInitializersInBody = !processedInitializers.BoundInitializers.IsDefaultOrEmpty &&
!HasThisConstructorInitializer(methodSymbol); !HasThisConstructorInitializer(methodSymbol);
body = BindMethodBody(methodSymbol, compilationState, diagsForCurrentMethod, _generateDebugInfo, out importChain); body = BindMethodBody(methodSymbol, compilationState, diagsForCurrentMethod, out importChain);
// lower initializers just once. the lowered tree will be reused when emitting all constructors // lower initializers just once. the lowered tree will be reused when emitting all constructors
// with field initializers. Once lowered, these initializers will be stashed in processedInitializers.LoweredInitializers // with field initializers. Once lowered, these initializers will be stashed in processedInitializers.LoweredInitializers
...@@ -869,12 +869,9 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -869,12 +869,9 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
} }
} }
#if DEBUG #if DEBUG
// If the method is a synthesized static or instance constructor, then debugImports will be null and we will use the value // If the method is a synthesized static or instance constructor, then debugImports will be null and we will use the value
// from the first field initializer. // from the first field initializer.
if (_generateDebugInfo)
{
if ((methodSymbol.MethodKind == MethodKind.Constructor || methodSymbol.MethodKind == MethodKind.StaticConstructor) && if ((methodSymbol.MethodKind == MethodKind.Constructor || methodSymbol.MethodKind == MethodKind.StaticConstructor) &&
methodSymbol.IsImplicitlyDeclared && body == null) methodSymbol.IsImplicitlyDeclared && body == null)
{ {
...@@ -884,7 +881,6 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -884,7 +881,6 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
// Either there were no field initializers or we grabbed debug imports from the first one. // Either there were no field initializers or we grabbed debug imports from the first one.
Debug.Assert(processedInitializers.BoundInitializers.IsDefaultOrEmpty || processedInitializers.FirstImportChain != null); Debug.Assert(processedInitializers.BoundInitializers.IsDefaultOrEmpty || processedInitializers.FirstImportChain != null);
}
#endif #endif
importChain = importChain ?? processedInitializers.FirstImportChain; importChain = importChain ?? processedInitializers.FirstImportChain;
...@@ -1082,7 +1078,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum ...@@ -1082,7 +1078,7 @@ public override object VisitField(FieldSymbol symbol, TypeCompilationState argum
diagsForCurrentMethod, diagsForCurrentMethod,
_debugDocumentProvider, _debugDocumentProvider,
importChain, importChain,
_generateDebugInfo && methodSymbol.GenerateDebugInfo); _emittingPdb);
_moduleBeingBuiltOpt.SetMethodBody(methodSymbol.PartialDefinitionPart ?? methodSymbol, emittedBody); _moduleBeingBuiltOpt.SetMethodBody(methodSymbol.PartialDefinitionPart ?? methodSymbol, emittedBody);
} }
...@@ -1242,7 +1238,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol, ...@@ -1242,7 +1238,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
DebugDocumentProvider debugDocumentProvider, DebugDocumentProvider debugDocumentProvider,
ImportChain importChainOpt, ImportChain importChainOpt,
bool generateDebugInfo) bool emittingPdb)
{ {
// Note: don't call diagnostics.HasAnyErrors() in release; could be expensive if compilation has many warnings. // Note: don't call diagnostics.HasAnyErrors() in release; could be expensive if compilation has many warnings.
Debug.Assert(!diagnostics.HasAnyErrors(), "Running code generator when errors exist might be dangerous; code generator not expecting errors"); Debug.Assert(!diagnostics.HasAnyErrors(), "Running code generator when errors exist might be dangerous; code generator not expecting errors");
...@@ -1257,7 +1253,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol, ...@@ -1257,7 +1253,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
{ {
Cci.AsyncMethodBodyDebugInfo asyncDebugInfo = null; Cci.AsyncMethodBodyDebugInfo asyncDebugInfo = null;
var codeGen = new CodeGen.CodeGenerator(method, block, builder, moduleBuilder, diagnosticsForThisMethod, optimizations, generateDebugInfo); var codeGen = new CodeGen.CodeGenerator(method, block, builder, moduleBuilder, diagnosticsForThisMethod, optimizations, emittingPdb);
// We need to save additional debugging information for MoveNext of an async state machine. // We need to save additional debugging information for MoveNext of an async state machine.
var stateMachineMethod = method as SynthesizedStateMachineMethod; var stateMachineMethod = method as SynthesizedStateMachineMethod;
...@@ -1284,6 +1280,11 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol, ...@@ -1284,6 +1280,11 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
codeGen.Generate(); codeGen.Generate();
} }
// Translate the imports even if we are not writing PDBs. The translation has an impact on generated metadata
// and we don't want to emit different metadata depending on whether or we emit with PDB stream.
// TODO (https://github.com/dotnet/roslyn/issues/2846): This will need to change for member initializers in partial class.
var importScopeOpt = importChainOpt?.Translate(moduleBuilder, diagnosticsForThisMethod);
var localVariables = builder.LocalSlotManager.LocalsInOrder(); var localVariables = builder.LocalSlotManager.LocalsInOrder();
if (localVariables.Length > 0xFFFE) if (localVariables.Length > 0xFFFE)
...@@ -1329,7 +1330,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol, ...@@ -1329,7 +1330,7 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
builder.RealizedExceptionHandlers, builder.RealizedExceptionHandlers,
builder.GetAllScopes(), builder.GetAllScopes(),
builder.HasDynamicLocal, builder.HasDynamicLocal,
importChainOpt, importScopeOpt,
lambdaDebugInfo, lambdaDebugInfo,
closureDebugInfo, closureDebugInfo,
stateMachineTypeOpt?.Name, stateMachineTypeOpt?.Name,
...@@ -1395,11 +1396,11 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol, ...@@ -1395,11 +1396,11 @@ private BoundStatement ChainImplicitStructConstructor(MethodSymbol methodSymbol,
internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics) internal static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics)
{ {
ImportChain unused; ImportChain unused;
return BindMethodBody(method, compilationState, diagnostics, false, out unused); return BindMethodBody(method, compilationState, diagnostics, out unused);
} }
// NOTE: can return null if the method has no body. // NOTE: can return null if the method has no body.
private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, bool generateDebugInfo, out ImportChain importChain) private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationState compilationState, DiagnosticBag diagnostics, out ImportChain importChain)
{ {
importChain = null; importChain = null;
...@@ -1457,10 +1458,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta ...@@ -1457,10 +1458,7 @@ private static BoundBlock BindMethodBody(MethodSymbol method, TypeCompilationSta
Binder binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder); Binder binder = new ExecutableCodeBinder(blockSyntax, sourceMethod, inMethodBinder);
body = binder.BindBlock(blockSyntax, diagnostics); body = binder.BindBlock(blockSyntax, diagnostics);
if (generateDebugInfo)
{
importChain = binder.ImportChain; importChain = binder.ImportChain;
}
if (inMethodBinder.IsDirectlyInIterator) if (inMethodBinder.IsDirectlyInIterator)
{ {
......
...@@ -72,7 +72,7 @@ internal static class EmitHelpers ...@@ -72,7 +72,7 @@ internal static class EmitHelpers
moduleBeingBuilt, moduleBeingBuilt,
win32Resources: null, win32Resources: null,
xmlDocStream: null, xmlDocStream: null,
generateDebugInfo: true, emittingPdb: true,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: changes.RequiresCompilation, filterOpt: changes.RequiresCompilation,
cancellationToken: cancellationToken)) cancellationToken: cancellationToken))
......
...@@ -117,7 +117,7 @@ internal sealed override AssemblySymbol CorLibrary ...@@ -117,7 +117,7 @@ internal sealed override AssemblySymbol CorLibrary
protected sealed override IEnumerable<string> LinkedAssembliesDebugInfo => SpecializedCollections.EmptyEnumerable<string>(); protected sealed override IEnumerable<string> LinkedAssembliesDebugInfo => SpecializedCollections.EmptyEnumerable<string>();
// C# currently doesn't emit compilation level imports (TODO: scripting). // C# currently doesn't emit compilation level imports (TODO: scripting).
protected override ImmutableArray<Cci.UsedNamespaceOrType> GetImports(EmitContext context) => ImmutableArray<Cci.UsedNamespaceOrType>.Empty; protected override ImmutableArray<Cci.UsedNamespaceOrType> GetImports() => ImmutableArray<Cci.UsedNamespaceOrType>.Empty;
// C# doesn't allow to define default namespace for compilation. // C# doesn't allow to define default namespace for compilation.
protected override string DefaultNamespace => null; protected override string DefaultNamespace => null;
......
...@@ -12570,7 +12570,7 @@ static System.Action M() ...@@ -12570,7 +12570,7 @@ static System.Action M()
var methodBodyCompiler = new MethodCompiler( var methodBodyCompiler = new MethodCompiler(
compilation: compilation, compilation: compilation,
moduleBeingBuiltOpt: module, moduleBeingBuiltOpt: module,
generateDebugInfo: false, emittingPdb: false,
hasDeclarationErrors: false, hasDeclarationErrors: false,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: null, filterOpt: null,
......
...@@ -3,9 +3,13 @@ ...@@ -3,9 +3,13 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Text;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.MetadataUtilities;
using Roslyn.Test.Utilities; using Roslyn.Test.Utilities;
using Xunit; using Xunit;
using ProprietaryTestResources = Microsoft.CodeAnalysis.Test.Resources.Proprietary; using ProprietaryTestResources = Microsoft.CodeAnalysis.Test.Resources.Proprietary;
...@@ -2130,5 +2134,208 @@ static void Main() ...@@ -2130,5 +2134,208 @@ static void Main()
Assert.Equal(1, reader.GetTableRowCount(TableIndex.TypeSpec)); Assert.Equal(1, reader.GetTableRowCount(TableIndex.TypeSpec));
}); });
} }
[Fact]
public void EmittingPdbVsNot()
{
string source = @"
using System;
using X = System.IO.FileStream;
class C
{
int x = 1;
static int y = 1;
C()
{
Console.WriteLine();
}
}
";
var c = CreateCompilationWithMscorlib(source, assemblyName: "EmittingPdbVsNot", options: TestOptions.ReleaseDll);
var peStream1 = new MemoryStream();
var peStream2 = new MemoryStream();
var pdbStream = new MemoryStream();
var emitResult1 = c.Emit(peStream: peStream1, pdbStream: pdbStream);
var emitResult2 = c.Emit(peStream: peStream2);
SharedCompilationUtils.VerifyMetadataEqualModuloMvid(peStream1, peStream2);
}
[Fact]
public void ImportedNoPiaTypes()
{
var sourceLib = @"
using System;
using System.Reflection;
using System.Runtime.InteropServices;
[assembly: Guid(""11111111-1111-1111-1111-111111111111"")]
[assembly: ImportedFromTypeLib(""Foo"")]
[assembly: TypeLibVersion(1, 0)]
namespace N
{
public enum E
{
Value1 = 1
}
public struct S1
{
public int A1;
public int A2;
}
public struct S2
{
public const int Value2 = 2;
}
public struct SBad
{
public int A3;
public const int Value3 = 3;
}
[ComImport, Guid(""22222222-2222-2222-2222-222222222222"")]
public interface I
{
void F();
}
public interface IBad
{
void F();
}
}
";
var source = @"
using System;
using static N.E;
using static N.SBad;
using Z1 = N.S1;
using Z2 = N.S2;
using ZBad = N.SBad;
using NI = N.I;
using NIBad = N.IBad;
class C
{
NI i;
void M()
{
Console.WriteLine(Value1);
Console.WriteLine(Z2.Value2);
Console.WriteLine(new Z1());
}
}
";
var libRef = CreateCompilationWithMscorlib(sourceLib, assemblyName: "ImportedNoPiaTypesAssemblyName").EmitToImageReference(embedInteropTypes: true);
var compilation = CreateCompilationWithMscorlib(source, new[] { libRef });
var v = CompileAndVerify(compilation);
v.Diagnostics.Verify(
// (14,8): warning CS0169: The field 'C.i' is never used
// NI i;
Diagnostic(ErrorCode.WRN_UnreferencedField, "i").WithArguments("C.i"),
// (5,1): hidden CS8019: Unnecessary using directive.
// using static N.SBad;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using static N.SBad;"),
// (10,1): hidden CS8019: Unnecessary using directive.
// using NIBad = N.IBad;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using NIBad = N.IBad;"),
// (8,1): hidden CS8019: Unnecessary using directive.
// using ZBad = N.SBad;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using ZBad = N.SBad;"));
// Usings of embedded types are currently ommitted:
v.VerifyPdb("C.M", @"
<symbols>
<methods>
<method containingType=""C"" name=""M"">
<customDebugInfo>
<using>
<namespace usingCount=""1"" />
</using>
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""18"" startColumn=""9"" endLine=""18"" endColumn=""35"" document=""0"" />
<entry offset=""0xb"" startLine=""19"" startColumn=""9"" endLine=""19"" endColumn=""38"" document=""0"" />
<entry offset=""0x11"" startLine=""20"" startColumn=""9"" endLine=""20"" endColumn=""37"" document=""0"" />
<entry offset=""0x24"" startLine=""21"" startColumn=""5"" endLine=""21"" endColumn=""6"" document=""0"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x25"">
<namespace name=""System"" />
</scope>
</method>
</methods>
</symbols>");
}
[Fact]
public void ImportedTypeWithUnknownBase()
{
var sourceLib1 = @"
namespace N
{
public class A { }
}
";
var sourceLib2 = @"
namespace N
{
public class B : A { }
}
";
var source = @"
using System;
using X = N.B;
class C
{
void M()
{
Console.WriteLine();
}
}
";
var libRef1 = CreateCompilationWithMscorlib(sourceLib1).EmitToImageReference();
var libRef2 = CreateCompilationWithMscorlib(sourceLib2, new[] { libRef1 }, assemblyName: "LibRef2").EmitToImageReference();
var compilation = CreateCompilationWithMscorlib(source, new[] { libRef2 });
var v = CompileAndVerify(compilation, emitters: TestEmitters.CCI);
v.Diagnostics.Verify(
// (3,1): hidden CS8019: Unnecessary using directive.
// using X = N.B;
Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using X = N.B;"));
v.VerifyPdb("C.M", @"
<symbols>
<methods>
<method containingType=""C"" name=""M"">
<customDebugInfo>
<using>
<namespace usingCount=""2"" />
</using>
</customDebugInfo>
<sequencePoints>
<entry offset=""0x0"" startLine=""9"" startColumn=""9"" endLine=""9"" endColumn=""29"" document=""0"" />
<entry offset=""0x5"" startLine=""10"" startColumn=""5"" endLine=""10"" endColumn=""6"" document=""0"" />
</sequencePoints>
<scope startOffset=""0x0"" endOffset=""0x6"">
<namespace name=""System"" />
<alias name=""X"" target=""N.B, LibRef2, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"" kind=""type"" />
</scope>
</method>
</methods>
</symbols>");
}
} }
} }
...@@ -293,16 +293,9 @@ private static ImmutableArray<BoundInitializer> BindInitializersWithoutDiagnosti ...@@ -293,16 +293,9 @@ private static ImmutableArray<BoundInitializer> BindInitializersWithoutDiagnosti
scriptCtor: null, scriptCtor: null,
initializers: initializers, initializers: initializers,
diagnostics: diagnostics, diagnostics: diagnostics,
generateDebugInfo: false,
firstImportChain: out unused); firstImportChain: out unused);
var filteredDiag = diagnostics.AsEnumerable(); diagnostics.Verify();
foreach (var diagnostic in filteredDiag)
{
Console.WriteLine(diagnostic);
}
Assert.True(filteredDiag.IsEmpty());
return boundInitializers; return boundInitializers;
} }
......
...@@ -1250,7 +1250,7 @@ internal bool IsRealSigned ...@@ -1250,7 +1250,7 @@ internal bool IsRealSigned
CommonPEModuleBuilder moduleBuilder, CommonPEModuleBuilder moduleBuilder,
Stream win32Resources, Stream win32Resources,
Stream xmlDocStream, Stream xmlDocStream,
bool generateDebugInfo, bool emittingPdb,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
Predicate<ISymbol> filterOpt, Predicate<ISymbol> filterOpt,
CancellationToken cancellationToken); CancellationToken cancellationToken);
...@@ -1259,7 +1259,7 @@ internal bool IsRealSigned ...@@ -1259,7 +1259,7 @@ internal bool IsRealSigned
CommonPEModuleBuilder moduleBuilder, CommonPEModuleBuilder moduleBuilder,
Stream win32Resources, Stream win32Resources,
Stream xmlDocStream, Stream xmlDocStream,
bool generateDebugInfo, bool emittingPdb,
DiagnosticBag diagnostics, DiagnosticBag diagnostics,
Predicate<ISymbol> filterOpt, Predicate<ISymbol> filterOpt,
CancellationToken cancellationToken) CancellationToken cancellationToken)
...@@ -1270,7 +1270,7 @@ internal bool IsRealSigned ...@@ -1270,7 +1270,7 @@ internal bool IsRealSigned
moduleBuilder, moduleBuilder,
win32Resources, win32Resources,
xmlDocStream, xmlDocStream,
generateDebugInfo, emittingPdb,
diagnostics, diagnostics,
filterOpt, filterOpt,
cancellationToken); cancellationToken);
...@@ -1303,7 +1303,7 @@ internal void EnsureAnonymousTypeTemplates(CancellationToken cancellationToken) ...@@ -1303,7 +1303,7 @@ internal void EnsureAnonymousTypeTemplates(CancellationToken cancellationToken)
moduleBeingBuilt, moduleBeingBuilt,
win32Resources: null, win32Resources: null,
xmlDocStream: null, xmlDocStream: null,
generateDebugInfo: false, emittingPdb: false,
diagnostics: discardedDiagnostics, diagnostics: discardedDiagnostics,
filterOpt: null, filterOpt: null,
cancellationToken: cancellationToken); cancellationToken: cancellationToken);
...@@ -1576,7 +1576,7 @@ internal void EnsureAnonymousTypeTemplates(CancellationToken cancellationToken) ...@@ -1576,7 +1576,7 @@ internal void EnsureAnonymousTypeTemplates(CancellationToken cancellationToken)
moduleBeingBuilt, moduleBeingBuilt,
win32Resources, win32Resources,
xmlDocumentationStream, xmlDocumentationStream,
generateDebugInfo: pdbStreamProvider != null, emittingPdb: pdbStreamProvider != null,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: null, filterOpt: null,
cancellationToken: cancellationToken)) cancellationToken: cancellationToken))
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit.NoPia;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Emit namespace Microsoft.CodeAnalysis.Emit
...@@ -24,6 +25,7 @@ internal abstract class CommonPEModuleBuilder ...@@ -24,6 +25,7 @@ internal abstract class CommonPEModuleBuilder
internal abstract CommonModuleCompilationState CommonModuleCompilationState { get; } internal abstract CommonModuleCompilationState CommonModuleCompilationState { get; }
internal abstract void CompilationFinished(); internal abstract void CompilationFinished();
internal abstract ImmutableDictionary<Cci.ITypeDefinition, ImmutableArray<Cci.ITypeDefinitionMember>> GetSynthesizedMembers(); internal abstract ImmutableDictionary<Cci.ITypeDefinition, ImmutableArray<Cci.ITypeDefinitionMember>> GetSynthesizedMembers();
internal abstract CommonEmbeddedTypesManager CommonEmbeddedTypesManagerOpt { get; }
} }
/// <summary> /// <summary>
...@@ -237,54 +239,16 @@ internal sealed override Cci.ITypeReference Translate(ITypeSymbol symbol, Syntax ...@@ -237,54 +239,16 @@ internal sealed override Cci.ITypeReference Translate(ITypeSymbol symbol, Syntax
return Translate((TTypeSymbol)symbol, (TSyntaxNode)syntaxNodeOpt, diagnostics); return Translate((TTypeSymbol)symbol, (TSyntaxNode)syntaxNodeOpt, diagnostics);
} }
internal OutputKind OutputKind internal OutputKind OutputKind => _outputKind;
{ internal TSourceModuleSymbol SourceModule => _sourceModule;
get internal TCompilation Compilation => _compilation;
{
return _outputKind;
}
}
internal TSourceModuleSymbol SourceModule internal sealed override Compilation CommonCompilation => _compilation;
{ internal sealed override CommonModuleCompilationState CommonModuleCompilationState => CompilationState;
get internal sealed override CommonEmbeddedTypesManager CommonEmbeddedTypesManagerOpt => EmbeddedTypesManagerOpt;
{
return _sourceModule;
}
}
internal TCompilation Compilation
{
get
{
return _compilation;
}
}
internal override Compilation CommonCompilation
{
get
{
return _compilation;
}
}
internal override CommonModuleCompilationState CommonModuleCompilationState
{
get
{
return this.CompilationState;
}
}
// General entry point method. May be a PE entry point or a submission entry point. // General entry point method. May be a PE entry point or a submission entry point.
internal sealed override Cci.IMethodReference EntryPoint internal sealed override Cci.IMethodReference EntryPoint => _entryPoint;
{
get
{
return _entryPoint;
}
}
internal void SetEntryPoint(TMethodSymbol value) internal void SetEntryPoint(TMethodSymbol value)
{ {
...@@ -778,8 +742,8 @@ ImmutableArray<Cci.AssemblyReferenceAlias> Cci.IModule.GetAssemblyReferenceAlias ...@@ -778,8 +742,8 @@ ImmutableArray<Cci.AssemblyReferenceAlias> Cci.IModule.GetAssemblyReferenceAlias
IEnumerable<string> Cci.IModule.LinkedAssembliesDebugInfo => LinkedAssembliesDebugInfo; IEnumerable<string> Cci.IModule.LinkedAssembliesDebugInfo => LinkedAssembliesDebugInfo;
protected abstract IEnumerable<string> LinkedAssembliesDebugInfo { get; } protected abstract IEnumerable<string> LinkedAssembliesDebugInfo { get; }
ImmutableArray<Cci.UsedNamespaceOrType> Cci.IModule.GetImports(EmitContext context) => GetImports(context); ImmutableArray<Cci.UsedNamespaceOrType> Cci.IModule.GetImports() => GetImports();
protected abstract ImmutableArray<Cci.UsedNamespaceOrType> GetImports(EmitContext context); protected abstract ImmutableArray<Cci.UsedNamespaceOrType> GetImports();
string Cci.IModule.DefaultNamespace => DefaultNamespace; string Cci.IModule.DefaultNamespace => DefaultNamespace;
protected abstract string DefaultNamespace { get; } protected abstract string DefaultNamespace { get; }
......
...@@ -305,7 +305,7 @@ public void SerializeDebugInfo(IMethodBody methodBody, uint localSignatureToken, ...@@ -305,7 +305,7 @@ public void SerializeDebugInfo(IMethodBody methodBody, uint localSignatureToken,
// NOTE: This is an attempt to match Dev10's apparent behavior. For iterator methods (i.e. the method // NOTE: This is an attempt to match Dev10's apparent behavior. For iterator methods (i.e. the method
// that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal // that appears in source, not the synthesized ones), Dev10 only emits the ForwardIterator and IteratorLocal
// custom debug info (e.g. there will be no information about the usings that were in scope). // custom debug info (e.g. there will be no information about the usings that were in scope).
if (!isIterator) if (!isIterator && methodBody.ImportScope != null)
{ {
IMethodDefinition forwardToMethod; IMethodDefinition forwardToMethod;
if (customDebugInfoWriter.ShouldForwardNamespaceScopes(Context, methodBody, methodToken, out forwardToMethod)) if (customDebugInfoWriter.ShouldForwardNamespaceScopes(Context, methodBody, methodToken, out forwardToMethod))
...@@ -375,7 +375,7 @@ private void DefineNamespaceScopes(IMethodBody methodBody) ...@@ -375,7 +375,7 @@ private void DefineNamespaceScopes(IMethodBody methodBody)
{ {
for (var scope = namespaceScopes; scope != null; scope = scope.Parent) for (var scope = namespaceScopes; scope != null; scope = scope.Parent)
{ {
foreach (var import in scope.GetUsedNamespaces(Context)) foreach (var import in scope.GetUsedNamespaces())
{ {
if (import.TargetNamespaceOpt == null && import.TargetTypeOpt == null) if (import.TargetNamespaceOpt == null && import.TargetTypeOpt == null)
{ {
...@@ -396,7 +396,7 @@ private void DefineNamespaceScopes(IMethodBody methodBody) ...@@ -396,7 +396,7 @@ private void DefineNamespaceScopes(IMethodBody methodBody)
// file and namespace level // file and namespace level
for (IImportScope scope = namespaceScopes; scope != null; scope = scope.Parent) for (IImportScope scope = namespaceScopes; scope != null; scope = scope.Parent)
{ {
foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces(Context)) foreach (UsedNamespaceOrType import in scope.GetUsedNamespaces())
{ {
var importString = TryEncodeImport(import, lazyDeclaredExternAliases, isProjectLevel: false); var importString = TryEncodeImport(import, lazyDeclaredExternAliases, isProjectLevel: false);
if (importString != null) if (importString != null)
...@@ -424,7 +424,7 @@ private void DefineNamespaceScopes(IMethodBody methodBody) ...@@ -424,7 +424,7 @@ private void DefineNamespaceScopes(IMethodBody methodBody)
UsingNamespace("&" + assemblyName, module); UsingNamespace("&" + assemblyName, module);
} }
foreach (UsedNamespaceOrType import in module.GetImports(Context)) foreach (UsedNamespaceOrType import in module.GetImports())
{ {
var importString = TryEncodeImport(import, null, isProjectLevel: true); var importString = TryEncodeImport(import, null, isProjectLevel: true);
if (importString != null) if (importString != null)
......
...@@ -34,7 +34,7 @@ public CustomDebugInfoWriter(PdbWriter pdbWriter) ...@@ -34,7 +34,7 @@ public CustomDebugInfoWriter(PdbWriter pdbWriter)
/// </summary> /// </summary>
public bool ShouldForwardNamespaceScopes(EmitContext context, IMethodBody methodBody, uint methodToken, out IMethodDefinition forwardToMethod) public bool ShouldForwardNamespaceScopes(EmitContext context, IMethodBody methodBody, uint methodToken, out IMethodDefinition forwardToMethod)
{ {
if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody) || methodBody.ImportScope == null) if (ShouldForwardToPreviousMethodWithUsingInfo(context, methodBody))
{ {
// SerializeNamespaceScopeMetadata will do the actual forwarding in case this is a CSharp method. // SerializeNamespaceScopeMetadata will do the actual forwarding in case this is a CSharp method.
// VB on the other hand adds a "@methodtoken" to the scopes instead. // VB on the other hand adds a "@methodtoken" to the scopes instead.
...@@ -351,7 +351,7 @@ private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody me ...@@ -351,7 +351,7 @@ private void SerializeNamespaceScopeMetadata(EmitContext context, IMethodBody me
BinaryWriter cmw = new BinaryWriter(customMetadata); BinaryWriter cmw = new BinaryWriter(customMetadata);
for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent) for (IImportScope scope = methodBody.ImportScope; scope != null; scope = scope.Parent)
{ {
usingCounts.Add((ushort)scope.GetUsedNamespaces(context).Length); usingCounts.Add((ushort)scope.GetUsedNamespaces().Length);
} }
// ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the // ACASEY: This originally wrote (uint)12, (ushort)1, (ushort)0 in the
...@@ -414,7 +414,7 @@ private bool ShouldForwardToPreviousMethodWithUsingInfo(EmitContext context, IMe ...@@ -414,7 +414,7 @@ private bool ShouldForwardToPreviousMethodWithUsingInfo(EmitContext context, IMe
var s2 = previousScopes; var s2 = previousScopes;
while (s1 != null && s2 != null) while (s1 != null && s2 != null)
{ {
if (!s1.GetUsedNamespaces(context).SequenceEqual(s2.GetUsedNamespaces(context))) if (!s1.GetUsedNamespaces().SequenceEqual(s2.GetUsedNamespaces()))
{ {
return false; return false;
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable; using System.Collections.Immutable;
using Microsoft.CodeAnalysis.Emit;
namespace Microsoft.Cci namespace Microsoft.Cci
{ {
...@@ -13,7 +12,7 @@ internal interface IImportScope ...@@ -13,7 +12,7 @@ internal interface IImportScope
/// <summary> /// <summary>
/// Zero or more used namespaces. These correspond to using directives in C# or Imports syntax in VB. /// Zero or more used namespaces. These correspond to using directives in C# or Imports syntax in VB.
/// </summary> /// </summary>
ImmutableArray<UsedNamespaceOrType> GetUsedNamespaces(EmitContext context); ImmutableArray<UsedNamespaceOrType> GetUsedNamespaces();
/// <summary> /// <summary>
/// Parent import scope, or null. /// Parent import scope, or null.
......
...@@ -47,7 +47,7 @@ public override void Visit(IModule module) ...@@ -47,7 +47,7 @@ public override void Visit(IModule module)
this.Visit(module.GetResources(Context)); this.Visit(module.GetResources(Context));
} }
VisitImports(module.GetImports(Context)); VisitImports(module.GetImports());
} }
public void VisitMethodBodyReference(IReference reference) public void VisitMethodBodyReference(IReference reference)
...@@ -101,7 +101,7 @@ protected override void ProcessMethodBody(IMethodDefinition method) ...@@ -101,7 +101,7 @@ protected override void ProcessMethodBody(IMethodDefinition method)
{ {
if (_alreadySeenScopes.Add(scope)) if (_alreadySeenScopes.Add(scope))
{ {
VisitImports(scope.GetUsedNamespaces(Context)); VisitImports(scope.GetUsedNamespaces());
} }
else else
{ {
......
...@@ -414,7 +414,7 @@ ulong SizeOfStackReserve ...@@ -414,7 +414,7 @@ ulong SizeOfStackReserve
/// <summary> /// <summary>
/// Project level imports (VB only, TODO: C# scripts). /// Project level imports (VB only, TODO: C# scripts).
/// </summary> /// </summary>
ImmutableArray<UsedNamespaceOrType> GetImports(EmitContext context); ImmutableArray<UsedNamespaceOrType> GetImports();
/// <summary> /// <summary>
/// Default namespace (VB only). /// Default namespace (VB only).
......
...@@ -47,7 +47,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen ...@@ -47,7 +47,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
moduleBuilder As PEModuleBuilder, moduleBuilder As PEModuleBuilder,
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
optimizations As OptimizationLevel, optimizations As OptimizationLevel,
emittingPdbs As Boolean) emittingPdb As Boolean)
Debug.Assert(method IsNot Nothing) Debug.Assert(method IsNot Nothing)
Debug.Assert(boundBody IsNot Nothing) Debug.Assert(boundBody IsNot Nothing)
...@@ -55,14 +55,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen ...@@ -55,14 +55,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
Debug.Assert(moduleBuilder IsNot Nothing) Debug.Assert(moduleBuilder IsNot Nothing)
Debug.Assert(diagnostics IsNot Nothing) Debug.Assert(diagnostics IsNot Nothing)
Me._method = method _method = method
Me._block = boundBody _block = boundBody
Me._builder = builder _builder = builder
Me._module = moduleBuilder _module = moduleBuilder
Me._diagnostics = diagnostics _diagnostics = diagnostics
' Always optimize synthesized methods that don't contain user code. ' Always optimize synthesized methods that don't contain user code.
Me._optimizations = If(method.GenerateDebugInfo, optimizations, OptimizationLevel.Release) _optimizations = If(method.GenerateDebugInfo, optimizations, OptimizationLevel.Release)
' Emit sequence points unless ' Emit sequence points unless
' - the PDBs are not being generated ' - the PDBs are not being generated
...@@ -70,14 +70,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen ...@@ -70,14 +70,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeGen
' user code that can be stepped thru, or changed during EnC. ' user code that can be stepped thru, or changed during EnC.
' '
' This setting only affects generating PDB sequence points, it shall Not affect generated IL in any way. ' This setting only affects generating PDB sequence points, it shall Not affect generated IL in any way.
Me._emitPdbSequencePoints = emittingPdbs AndAlso method.GenerateDebugInfo _emitPdbSequencePoints = emittingPdb AndAlso method.GenerateDebugInfo
If Me._optimizations = OptimizationLevel.Release Then If _optimizations = OptimizationLevel.Release Then
Me._block = Optimizer.Optimize(method, boundBody, Me._stackLocals) _block = Optimizer.Optimize(method, boundBody, _stackLocals)
End If End If
Me._checkCallsForUnsafeJITOptimization = (Me._method.ImplementationAttributes And MethodSymbol.DisableJITOptimizationFlags) <> MethodSymbol.DisableJITOptimizationFlags _checkCallsForUnsafeJITOptimization = (_method.ImplementationAttributes And MethodSymbol.DisableJITOptimizationFlags) <> MethodSymbol.DisableJITOptimizationFlags
Debug.Assert(Not Me._module.JITOptimizationIsDisabled(Me._method)) Debug.Assert(Not _module.JITOptimizationIsDisabled(_method))
End Sub End Sub
Public Sub Generate() Public Sub Generate()
......
...@@ -20,7 +20,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -20,7 +20,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Private ReadOnly _compilation As VisualBasicCompilation Private ReadOnly _compilation As VisualBasicCompilation
Private ReadOnly _cancellationToken As CancellationToken Private ReadOnly _cancellationToken As CancellationToken
Private ReadOnly _generateDebugInfo As Boolean Private ReadOnly _emittingPdb As Boolean
Private ReadOnly _diagnostics As DiagnosticBag Private ReadOnly _diagnostics As DiagnosticBag
Private ReadOnly _hasDeclarationErrors As Boolean Private ReadOnly _hasDeclarationErrors As Boolean
Private ReadOnly _namespaceScopeBuilder As NamespaceScopeBuilder Private ReadOnly _namespaceScopeBuilder As NamespaceScopeBuilder
...@@ -78,28 +78,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -78,28 +78,28 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
' moduleBeingBuilt can be Nothing in order to just analyze methods for errors. ' moduleBeingBuilt can be Nothing in order to just analyze methods for errors.
Private Sub New(compilation As VisualBasicCompilation, Private Sub New(compilation As VisualBasicCompilation,
moduleBeingBuiltOpt As PEModuleBuilder, moduleBeingBuiltOpt As PEModuleBuilder,
generateDebugInfo As Boolean, emittingPdb As Boolean,
doEmitPhase As Boolean, doEmitPhase As Boolean,
hasDeclarationErrors As Boolean, hasDeclarationErrors As Boolean,
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
filter As Predicate(Of Symbol), filter As Predicate(Of Symbol),
cancellationToken As CancellationToken) cancellationToken As CancellationToken)
Me._compilation = compilation _compilation = compilation
Me._moduleBeingBuiltOpt = moduleBeingBuiltOpt _moduleBeingBuiltOpt = moduleBeingBuiltOpt
Me._diagnostics = diagnostics _diagnostics = diagnostics
Me._hasDeclarationErrors = hasDeclarationErrors _hasDeclarationErrors = hasDeclarationErrors
Me._cancellationToken = cancellationToken _cancellationToken = cancellationToken
Me._doEmitPhase = doEmitPhase _doEmitPhase = doEmitPhase
Me._generateDebugInfo = generateDebugInfo _emittingPdb = emittingPdb
Me._filterOpt = filter _filterOpt = filter
If generateDebugInfo Then If emittingPdb Then
Me._debugDocumentProvider = Function(path As String, basePath As String) moduleBeingBuiltOpt.GetOrAddDebugDocument(path, basePath, AddressOf CreateDebugDocumentForFile) _debugDocumentProvider = Function(path As String, basePath As String) moduleBeingBuiltOpt.GetOrAddDebugDocument(path, basePath, AddressOf CreateDebugDocumentForFile)
End If End If
If compilation.Options.ConcurrentBuild Then If compilation.Options.ConcurrentBuild Then
Me._compilerTasks = New ConcurrentStack(Of Task)() _compilerTasks = New ConcurrentStack(Of Task)()
End If End If
End Sub End Sub
...@@ -155,7 +155,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -155,7 +155,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim compiler = New MethodCompiler(compilation, Dim compiler = New MethodCompiler(compilation,
moduleBeingBuiltOpt:=Nothing, moduleBeingBuiltOpt:=Nothing,
generateDebugInfo:=False, emittingPdb:=False,
doEmitPhase:=doEmitPhase, doEmitPhase:=doEmitPhase,
hasDeclarationErrors:=hasDeclarationErrors, hasDeclarationErrors:=hasDeclarationErrors,
diagnostics:=diagnostics, diagnostics:=diagnostics,
...@@ -187,7 +187,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -187,7 +187,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' </summary> ''' </summary>
Friend Shared Sub CompileMethodBodies(compilation As VisualBasicCompilation, Friend Shared Sub CompileMethodBodies(compilation As VisualBasicCompilation,
moduleBeingBuiltOpt As PEModuleBuilder, moduleBeingBuiltOpt As PEModuleBuilder,
generateDebugInfo As Boolean, emittingPdb As Boolean,
hasDeclarationErrors As Boolean, hasDeclarationErrors As Boolean,
filter As Predicate(Of Symbol), filter As Predicate(Of Symbol),
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
...@@ -209,7 +209,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -209,7 +209,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim compiler = New MethodCompiler(compilation, Dim compiler = New MethodCompiler(compilation,
moduleBeingBuiltOpt, moduleBeingBuiltOpt,
generateDebugInfo, emittingPdb,
doEmitPhase:=True, doEmitPhase:=True,
hasDeclarationErrors:=hasDeclarationErrors, hasDeclarationErrors:=hasDeclarationErrors,
diagnostics:=diagnostics, diagnostics:=diagnostics,
...@@ -305,7 +305,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -305,7 +305,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
variableSlotAllocatorOpt:=Nothing, variableSlotAllocatorOpt:=Nothing,
debugDocumentProvider:=Nothing, debugDocumentProvider:=Nothing,
diagnostics:=diagnostics, diagnostics:=diagnostics,
generateDebugInfo:=False) emittingPdb:=False)
moduleBeingBuilt.SetMethodBody(scriptEntryPoint, emittedBody) moduleBeingBuilt.SetMethodBody(scriptEntryPoint, emittedBody)
moduleBeingBuilt.AddSynthesizedDefinition(compilation.ScriptClass, scriptEntryPoint) moduleBeingBuilt.AddSynthesizedDefinition(compilation.ScriptClass, scriptEntryPoint)
...@@ -855,7 +855,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -855,7 +855,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
variableSlotAllocatorOpt:=Nothing, variableSlotAllocatorOpt:=Nothing,
debugDocumentProvider:=Nothing, debugDocumentProvider:=Nothing,
diagnostics:=diagnosticsThisMethod, diagnostics:=diagnosticsThisMethod,
generateDebugInfo:=False) emittingPdb:=False)
_diagnostics.AddRange(diagnosticsThisMethod) _diagnostics.AddRange(diagnosticsThisMethod)
diagnosticsThisMethod.Free() diagnosticsThisMethod.Free()
...@@ -919,7 +919,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -919,7 +919,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
lazyVariableSlotAllocator, lazyVariableSlotAllocator,
debugDocumentProvider:=Nothing, debugDocumentProvider:=Nothing,
diagnostics:=diagnosticsThisMethod, diagnostics:=diagnosticsThisMethod,
generateDebugInfo:=False) emittingPdb:=False)
End If End If
lambdaDebugInfoBuilder.Free() lambdaDebugInfoBuilder.Free()
...@@ -968,7 +968,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -968,7 +968,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
variableSlotAllocatorOpt:=Nothing, variableSlotAllocatorOpt:=Nothing,
debugDocumentProvider:=_debugDocumentProvider, debugDocumentProvider:=_debugDocumentProvider,
diagnostics:=diagnosticsThisMethod, diagnostics:=diagnosticsThisMethod,
generateDebugInfo:=_generateDebugInfo AndAlso method.GenerateDebugInfo) emittingPdb:=_emittingPdb)
_diagnostics.AddRange(diagnosticsThisMethod) _diagnostics.AddRange(diagnosticsThisMethod)
diagnosticsThisMethod.Free() diagnosticsThisMethod.Free()
...@@ -1451,7 +1451,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1451,7 +1451,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
lazyVariableSlotAllocator, lazyVariableSlotAllocator,
_debugDocumentProvider, _debugDocumentProvider,
diagnostics, diagnostics,
generateDebugInfo:=_generateDebugInfo AndAlso method.GenerateDebugInfo) emittingPdb:=_emittingPdb)
If diagnostics IsNot diagsForCurrentMethod Then If diagnostics IsNot diagsForCurrentMethod Then
DirectCast(method.AssociatedSymbol, SynthesizedMyGroupCollectionPropertySymbol).RelocateDiagnostics(diagnostics, diagsForCurrentMethod) DirectCast(method.AssociatedSymbol, SynthesizedMyGroupCollectionPropertySymbol).RelocateDiagnostics(diagnostics, diagsForCurrentMethod)
...@@ -1474,10 +1474,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1474,10 +1474,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
variableSlotAllocatorOpt As VariableSlotAllocator, variableSlotAllocatorOpt As VariableSlotAllocator,
debugDocumentProvider As DebugDocumentProvider, debugDocumentProvider As DebugDocumentProvider,
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
generateDebugInfo As Boolean) As MethodBody emittingPdb As Boolean) As MethodBody
Dim compilation = moduleBuilder.Compilation Dim compilation = moduleBuilder.Compilation
Dim localSlotManager = New localSlotManager(variableSlotAllocatorOpt) Dim localSlotManager = New LocalSlotManager(variableSlotAllocatorOpt)
Dim optimizations = compilation.Options.OptimizationLevel Dim optimizations = compilation.Options.OptimizationLevel
If method.IsEmbedded Then If method.IsEmbedded Then
...@@ -1490,7 +1490,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1490,7 +1490,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Debug.Assert(Not diagnostics.HasAnyErrors) Debug.Assert(Not diagnostics.HasAnyErrors)
Dim asyncDebugInfo As Cci.AsyncMethodBodyDebugInfo = Nothing Dim asyncDebugInfo As Cci.AsyncMethodBodyDebugInfo = Nothing
Dim codeGen = New codeGen.CodeGenerator(method, block, builder, moduleBuilder, diagnostics, optimizations, generateDebugInfo) Dim codeGen = New CodeGen.CodeGenerator(method, block, builder, moduleBuilder, diagnostics, optimizations, emittingPdb)
' We need to save additional debugging information for MoveNext of an async state machine. ' We need to save additional debugging information for MoveNext of an async state machine.
Dim stateMachineMethod = TryCast(method, SynthesizedStateMachineMethod) Dim stateMachineMethod = TryCast(method, SynthesizedStateMachineMethod)
...@@ -1523,6 +1523,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1523,6 +1523,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
codeGen.Generate() codeGen.Generate()
End If End If
' Translate the imports even if we are not writing PDBs. The translation has an impact on generated metadata
' and we don't want to emit different metadata depending on whether or we emit with PDB stream.
' TODO (https://github.com/dotnet/roslyn/issues/2846): This will need to change for member initializers in partial class.
Dim importScopeOpt = If(method.Syntax IsNot Nothing AndAlso method.Syntax.SyntaxTree IsNot VisualBasicSyntaxTree.DummySyntaxTree.Dummy,
moduleBuilder.SourceModule.GetSourceFile(method.Syntax.SyntaxTree).Translate(moduleBuilder, diagnostics),
Nothing)
If diagnostics.HasAnyErrors() Then If diagnostics.HasAnyErrors() Then
Return Nothing Return Nothing
End If End If
...@@ -1539,29 +1546,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1539,29 +1546,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
GetStateMachineSlotDebugInfo(moduleBuilder.GetSynthesizedFields(stateMachineTypeOpt), stateMachineHoistedLocalSlots, stateMachineAwaiterSlots) GetStateMachineSlotDebugInfo(moduleBuilder.GetSynthesizedFields(stateMachineTypeOpt), stateMachineHoistedLocalSlots, stateMachineAwaiterSlots)
End If End If
Dim namespaceScopes = If(generateDebugInfo, moduleBuilder.SourceModule.GetSourceFile(method.Syntax.SyntaxTree), Nothing)
' edgeInclusive must be true as that is what VB EE expects.
'<PdbUtil.cpp>
'HRESULT()
'PdbUtil::IsScopeInOffset(
' _In_ ISymUnmanagedScope* pScope,
' _In_ DWORD offset,
' _Out_ bool* inOffset)
'{
' VerifyInPtr(pScope);
' VerifyOutPtr(inOffset);
' HRESULT hr;
' ULONG32 start, end;
' IfFailGo( pScope->GetStartOffset(&start) );
' IfFailGo( pScope->GetEndOffset(&end) );
' *inOffset = (end >= offset) && (offset >= start); <==== HERE
'Error:
' return hr;
'}
Dim localScopes = builder.GetAllScopes() Dim localScopes = builder.GetAllScopes()
Return New MethodBody(builder.RealizedIL, Return New MethodBody(builder.RealizedIL,
...@@ -1574,7 +1558,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -1574,7 +1558,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
builder.RealizedExceptionHandlers, builder.RealizedExceptionHandlers,
localScopes, localScopes,
hasDynamicLocalVariables:=False, hasDynamicLocalVariables:=False,
importScopeOpt:=namespaceScopes, importScopeOpt:=importScopeOpt,
lambdaDebugInfo:=lambdaDebugInfo, lambdaDebugInfo:=lambdaDebugInfo,
closureDebugInfo:=closureDebugInfo, closureDebugInfo:=closureDebugInfo,
stateMachineTypeNameOpt:=stateMachineTypeOpt?.Name, ' TODO: remove or update AddedOrChangedMethodInfo stateMachineTypeNameOpt:=stateMachineTypeOpt?.Name, ' TODO: remove or update AddedOrChangedMethodInfo
......
...@@ -11,10 +11,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -11,10 +11,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Sub End Sub
Public Shared Function BuildNamespaceScope( Public Shared Function BuildNamespaceScope(
context As EmitContext, moduleBuilder As Emit.PEModuleBuilder,
xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition), xmlNamespaces As Dictionary(Of String, XmlNamespaceAndImportsClausePosition),
aliasImports As IEnumerable(Of AliasAndImportsClausePosition), aliasImports As IEnumerable(Of AliasAndImportsClausePosition),
memberImports As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition) memberImports As ImmutableArray(Of NamespaceOrTypeAndImportsClausePosition),
diagnostics As DiagnosticBag
) As ImmutableArray(Of Cci.UsedNamespaceOrType) ) As ImmutableArray(Of Cci.UsedNamespaceOrType)
Dim scopeBuilder = ArrayBuilder(Of Cci.UsedNamespaceOrType).GetInstance Dim scopeBuilder = ArrayBuilder(Of Cci.UsedNamespaceOrType).GetInstance
...@@ -31,8 +32,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -31,8 +32,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim target = aliasImport.Alias.Target Dim target = aliasImport.Alias.Target
If target.IsNamespace Then If target.IsNamespace Then
scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateNamespace(DirectCast(target, NamespaceSymbol), aliasOpt:=aliasImport.Alias.Name)) scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateNamespace(DirectCast(target, NamespaceSymbol), aliasOpt:=aliasImport.Alias.Name))
Else ElseIf Not target.ContainingAssembly.IsLinked
Dim typeRef = GetTypeReference(context, DirectCast(target, NamedTypeSymbol)) ' We skip alias imports of embedded types to avoid breaking existing code that
' imports types that can't be embedded but doesn't use them anywhere else in the code.
Dim typeRef = GetTypeReference(DirectCast(target, NamedTypeSymbol), moduleBuilder, diagnostics)
scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateType(typeRef, aliasOpt:=aliasImport.Alias.Name)) scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateType(typeRef, aliasOpt:=aliasImport.Alias.Name))
End If End If
Next Next
...@@ -44,8 +47,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -44,8 +47,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim target = import.NamespaceOrType Dim target = import.NamespaceOrType
If target.IsNamespace Then If target.IsNamespace Then
scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateNamespace(DirectCast(target, NamespaceSymbol))) scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateNamespace(DirectCast(target, NamespaceSymbol)))
Else ElseIf Not target.ContainingAssembly.IsLinked
Dim typeRef = GetTypeReference(context, DirectCast(target, NamedTypeSymbol)) ' We skip imports of embedded types to avoid breaking existing code that
' imports types that can't be embedded but doesn't use them anywhere else in the code.
Dim typeRef = GetTypeReference(DirectCast(target, NamedTypeSymbol), moduleBuilder, diagnostics)
scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateType(typeRef)) scopeBuilder.Add(Cci.UsedNamespaceOrType.CreateType(typeRef))
End If End If
Next Next
...@@ -54,8 +59,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -54,8 +59,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return scopeBuilder.ToImmutableAndFree() Return scopeBuilder.ToImmutableAndFree()
End Function End Function
Private Shared Function GetTypeReference(context As EmitContext, type As TypeSymbol) As Cci.ITypeReference Private Shared Function GetTypeReference(type As TypeSymbol, moduleBuilder As CommonPEModuleBuilder, diagnostics As DiagnosticBag) As Cci.ITypeReference
Return context.ModuleBuilder.Translate(type, context.SyntaxNodeOpt, context.Diagnostics) Return moduleBuilder.Translate(type, Nothing, diagnostics)
End Function End Function
End Class End Class
End Namespace End Namespace
...@@ -2207,7 +2207,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2207,7 +2207,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
moduleBuilder As CommonPEModuleBuilder, moduleBuilder As CommonPEModuleBuilder,
win32Resources As Stream, win32Resources As Stream,
xmlDocStream As Stream, xmlDocStream As Stream,
generateDebugInfo As Boolean, emittingPdb As Boolean,
diagnostics As DiagnosticBag, diagnostics As DiagnosticBag,
filterOpt As Predicate(Of ISymbol), filterOpt As Predicate(Of ISymbol),
cancellationToken As CancellationToken) As Boolean cancellationToken As CancellationToken) As Boolean
...@@ -2220,6 +2220,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2220,6 +2220,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Me.EmbeddedSymbolManager.MarkAllDeferredSymbolsAsReferenced(Me) Me.EmbeddedSymbolManager.MarkAllDeferredSymbolsAsReferenced(Me)
moduleBeingBuilt.TranslateImports(diagnostics)
If moduleBeingBuilt.EmitOptions.EmitMetadataOnly Then If moduleBeingBuilt.EmitOptions.EmitMetadataOnly Then
If hasDeclarationErrors Then If hasDeclarationErrors Then
Return False Return False
...@@ -2233,13 +2235,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2233,13 +2235,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
SynthesizedMetadataCompiler.ProcessSynthesizedMembers(Me, moduleBeingBuilt, cancellationToken) SynthesizedMetadataCompiler.ProcessSynthesizedMembers(Me, moduleBeingBuilt, cancellationToken)
Else Else
' start generating PDB checksums if we need to emit PDBs ' start generating PDB checksums if we need to emit PDBs
If generateDebugInfo AndAlso moduleBeingBuilt IsNot Nothing Then If emittingPdb AndAlso Not StartSourceChecksumCalculation(moduleBeingBuilt, diagnostics) Then
If Not StartSourceChecksumCalculation(moduleBeingBuilt, diagnostics) Then
Return False Return False
End If End If
End If
' Perform initial bind of method bodies in spite of earlier errors. This is the same ' Perform initial bind of method bodies in spite of earlier errors. This is the same
' behavior as when calling GetDiagnostics() ' behavior as when calling GetDiagnostics()
...@@ -2250,13 +2249,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ...@@ -2250,13 +2249,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
MethodCompiler.CompileMethodBodies( MethodCompiler.CompileMethodBodies(
Me, Me,
moduleBeingBuilt, moduleBeingBuilt,
generateDebugInfo, emittingPdb,
hasDeclarationErrors, hasDeclarationErrors,
filterOpt, filterOpt,
methodBodyDiagnosticBag, methodBodyDiagnosticBag,
cancellationToken) cancellationToken)
Dim assemblyName = FileNameUtilities.ChangeExtension(moduleBeingBuilt.EmitOptions.OutputNameOverride, extension:=Nothing) Dim assemblyName = FileNameUtilities.ChangeExtension(moduleBeingBuilt.EmitOptions.OutputNameOverride, extension:=Nothing)
DocumentationCommentCompiler.WriteDocumentationCommentXml(Me, assemblyName, xmlDocStream, methodBodyDiagnosticBag, cancellationToken) DocumentationCommentCompiler.WriteDocumentationCommentXml(Me, assemblyName, xmlDocStream, methodBodyDiagnosticBag, cancellationToken)
......
...@@ -63,7 +63,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ...@@ -63,7 +63,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
If compilation.Compile(moduleBeingBuilt, If compilation.Compile(moduleBeingBuilt,
win32Resources:=Nothing, win32Resources:=Nothing,
xmlDocStream:=Nothing, xmlDocStream:=Nothing,
generateDebugInfo:=True, emittingPdb:=True,
diagnostics:=diagnostics, diagnostics:=diagnostics,
filterOpt:=AddressOf changes.RequiresCompilation, filterOpt:=AddressOf changes.RequiresCompilation,
cancellationToken:=cancellationToken) Then cancellationToken:=cancellationToken) Then
......
...@@ -22,7 +22,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ...@@ -22,7 +22,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
Private ReadOnly _metadataName As String Private ReadOnly _metadataName As String
Private _lazyExportedTypes As ImmutableArray(Of TypeExport(Of NamedTypeSymbol)) Private _lazyExportedTypes As ImmutableArray(Of TypeExport(Of NamedTypeSymbol))
Private _lazyImports As ImmutableArray(Of Cci.UsedNamespaceOrType) Private _lazyTranslatedImports As ImmutableArray(Of Cci.UsedNamespaceOrType)
Private _lazyDefaultNamespace As String Private _lazyDefaultNamespace As String
' These fields will only be set when running tests. They allow realized IL for a given method to be looked up by method display name. ' These fields will only be set when running tests. They allow realized IL for a given method to be looked up by method display name.
...@@ -99,15 +99,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit ...@@ -99,15 +99,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Emit
End Get End Get
End Property End Property
Protected NotOverridable Overrides Function GetImports(context As EmitContext) As ImmutableArray(Of Cci.UsedNamespaceOrType) Protected NotOverridable Overrides Function GetImports() As ImmutableArray(Of Cci.UsedNamespaceOrType)
If _lazyImports.IsDefault Then ' Imports should have been translated in code gen phase.
Debug.Assert(Not _lazyTranslatedImports.IsDefault)
Return _lazyTranslatedImports
End Function
Public Sub TranslateImports(diagnostics As DiagnosticBag)
If _lazyTranslatedImports.IsDefault Then
ImmutableInterlocked.InterlockedInitialize( ImmutableInterlocked.InterlockedInitialize(
_lazyImports, _lazyTranslatedImports,
NamespaceScopeBuilder.BuildNamespaceScope(context, SourceModule.XmlNamespaces, SourceModule.AliasImports, SourceModule.MemberImports)) NamespaceScopeBuilder.BuildNamespaceScope(Me, SourceModule.XmlNamespaces, SourceModule.AliasImports, SourceModule.MemberImports, diagnostics))
End If End If
End Sub
Return _lazyImports
End Function
Protected NotOverridable Overrides ReadOnly Property DefaultNamespace As String Protected NotOverridable Overrides ReadOnly Property DefaultNamespace As String
Get Get
......
...@@ -430,19 +430,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols ...@@ -430,19 +430,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
End Get End Get
End Property End Property
Public Function GetUsedNamespaces(context As EmitContext) As ImmutableArray(Of Cci.UsedNamespaceOrType) Implements Cci.IImportScope.GetUsedNamespaces Public Function Translate(moduleBuilder As Emit.PEModuleBuilder, diagnostics As DiagnosticBag) As Cci.IImportScope
If _lazyTranslatedImports.IsDefault Then If _lazyTranslatedImports.IsDefault Then
ImmutableInterlocked.InterlockedInitialize(_lazyTranslatedImports, TranslateImports(context)) ImmutableInterlocked.InterlockedInitialize(_lazyTranslatedImports, TranslateImports(moduleBuilder, diagnostics))
End If End If
Return Me
End Function
Public Function GetUsedNamespaces() As ImmutableArray(Of Cci.UsedNamespaceOrType) Implements Cci.IImportScope.GetUsedNamespaces
' The imports should have been translated during code gen.
Debug.Assert(Not _lazyTranslatedImports.IsDefault)
Return _lazyTranslatedImports Return _lazyTranslatedImports
End Function End Function
Private Function TranslateImports(context As EmitContext) As ImmutableArray(Of Cci.UsedNamespaceOrType) Private Function TranslateImports(moduleBuilder As Emit.PEModuleBuilder, diagnostics As DiagnosticBag) As ImmutableArray(Of Cci.UsedNamespaceOrType)
Return NamespaceScopeBuilder.BuildNamespaceScope(context, Return NamespaceScopeBuilder.BuildNamespaceScope(moduleBuilder,
XmlNamespaces, XmlNamespaces,
If(AliasImports IsNot Nothing, AliasImports.Values, Nothing), If(AliasImports IsNot Nothing, AliasImports.Values, Nothing),
MemberImports) MemberImports,
diagnostics)
End Function End Function
End Class End Class
End Namespace End Namespace
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. ' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.IO
Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.PDB Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.PDB
...@@ -354,6 +355,207 @@ End Namespace ...@@ -354,6 +355,207 @@ End Namespace
</symbols>) </symbols>)
End Sub End Sub
<Fact>
Public Sub EmittingPdbVsNot()
Dim source =
<compilation name="EmittingPdbVsNot">
<file>
Imports System
Imports X = System.IO.FileStream
Class C
Dim x As Integer = 1
Shared y As Integer = 1
Sub New()
Console.WriteLine()
End Sub
End Class
</file>
</compilation>
Dim c = CreateCompilationWithMscorlib(source, options:=TestOptions.ReleaseDll)
Dim peStream1 = New MemoryStream()
Dim peStream2 = New MemoryStream()
Dim pdbStream = New MemoryStream()
Dim emitResult1 = c.Emit(peStream:=peStream1, pdbStream:=pdbStream)
Dim emitResult2 = c.Emit(peStream:=peStream2)
SharedCompilationUtils.VerifyMetadataEqualModuloMvid(peStream1, peStream2)
End Sub
<Fact>
Public Sub ImportedNoPiaTypes()
Dim sourceLib =
<compilation name="ImportedNoPiaTypesAssemblyName">
<file><![CDATA[
Imports System
Imports System.Reflection
Imports System.Runtime.InteropServices
<Assembly:Guid("11111111-1111-1111-1111-111111111111")>
<Assembly:ImportedFromTypeLib("Foo")>
<Assembly:TypeLibVersion(1, 0)>
Namespace N
Public Enum E
Value1 = 1
End Enum
Public Structure S1
Public A1 As Integer
Public A2 As Integer
End Structure
Public Structure S2
Public Const Value2 As Integer = 2
End Structure
Public Structure SBad
Public A3 As Integer
Public Const Value3 As Integer = 3
End Structure
<ComImport, Guid("22222222-2222-2222-2222-222222222222")>
Public Interface I
Sub F()
End Interface
Public Interface IBad
Sub F()
End Interface
End Namespace
]]>
</file>
</compilation>
Dim source =
<compilation>
<file>
Imports System
Imports N.E
Imports N.SBad
Imports Z1 = N.S1
Imports Z2 = N.S2
Imports ZBad = N.SBad
Imports NI = N.I
Imports NIBad = N.IBad
Class C
Dim i As NI
Sub M
Console.WriteLine(Value1)
Console.WriteLine(Z2.Value2)
Console.WriteLine(New Z1())
End Sub
End Class
</file>
</compilation>
Dim globalImports = GlobalImport.Parse(
"GlobalNIBad = N.IBad",
"GlobalZ1 = N.S1",
"GlobalZ2 = N.S2",
"GlobalZBad = N.SBad",
"GlobalNI = N.I")
Dim libRef = CreateCompilationWithMscorlib(sourceLib).EmitToImageReference(embedInteropTypes:=True)
Dim compilation = CreateCompilationWithMscorlibAndReferences(source, {libRef}, options:=TestOptions.DebugDll.WithGlobalImports(globalImports))
Dim v = CompileAndVerify(compilation)
v.Diagnostics.Verify(
Diagnostic(ERRID.HDN_UnusedImportStatement, "Imports N.SBad"),
Diagnostic(ERRID.HDN_UnusedImportStatement, "Imports ZBad = N.SBad"),
Diagnostic(ERRID.HDN_UnusedImportStatement, "Imports NIBad = N.IBad"))
' Imports of embedded types are currently ommitted:
v.VerifyPdb("C.M",
<symbols>
<methods>
<method containingType="C" name="M">
<sequencePoints>
<entry offset="0x0" startLine="13" startColumn="5" endLine="13" endColumn="10" document="0"/>
<entry offset="0x1" startLine="14" startColumn="9" endLine="14" endColumn="34" document="0"/>
<entry offset="0x8" startLine="15" startColumn="9" endLine="15" endColumn="37" document="0"/>
<entry offset="0xf" startLine="16" startColumn="9" endLine="16" endColumn="36" document="0"/>
<entry offset="0x23" startLine="17" startColumn="5" endLine="17" endColumn="12" document="0"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x24">
<namespace name="System" importlevel="file"/>
<defunct name="&amp;ImportedNoPiaTypesAssemblyName"/>
<currentnamespace name=""/>
</scope>
</method>
</methods>
</symbols>)
End Sub
<Fact>
Public Sub ImportedTypeWithUnknownBase()
Dim sourceLib1 =
<compilation>
<file>
Namespace N
Public Class A
End Class
End Namespace
</file>
</compilation>
Dim sourceLib2 =
<compilation name="LibRef2">
<file>
Namespace N
Public Class B
Inherits A
End Class
End Namespace
</file>
</compilation>
Dim source =
<compilation>
<file>
Imports System
Imports X = N.B
Class C
Sub M()
Console.WriteLine()
End Sub
End Class
</file>
</compilation>
Dim libRef1 = CreateCompilationWithMscorlib(sourceLib1).EmitToImageReference()
Dim libRef2 = CreateCompilationWithMscorlibAndReferences(sourceLib2, {libRef1}).EmitToImageReference()
Dim compilation = CreateCompilationWithMscorlibAndReferences(source, {libRef2})
Dim v = CompileAndVerify(compilation, emitters:=TestEmitters.CCI)
v.Diagnostics.Verify(
Diagnostic(ERRID.HDN_UnusedImportStatement, "Imports X = N.B"))
v.VerifyPdb("C.M",
<symbols>
<methods>
<method containingType="C" name="M">
<sequencePoints>
<entry offset="0x0" startLine="6" startColumn="9" endLine="6" endColumn="28" document="0"/>
<entry offset="0x5" startLine="7" startColumn="5" endLine="7" endColumn="12" document="0"/>
</sequencePoints>
<scope startOffset="0x0" endOffset="0x6">
<alias name="X" target="N.B" kind="namespace" importlevel="file"/>
<namespace name="System" importlevel="file"/>
<currentnamespace name=""/>
</scope>
</method>
</methods>
</symbols>)
End Sub
End Class End Class
End Namespace End Namespace
......
...@@ -157,7 +157,7 @@ internal sealed class CompilationContext ...@@ -157,7 +157,7 @@ internal sealed class CompilationContext
module, module,
win32Resources: null, win32Resources: null,
xmlDocStream: null, xmlDocStream: null,
generateDebugInfo: false, emittingPdb: false,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: null, filterOpt: null,
cancellationToken: CancellationToken.None); cancellationToken: CancellationToken.None);
...@@ -220,7 +220,7 @@ internal sealed class CompilationContext ...@@ -220,7 +220,7 @@ internal sealed class CompilationContext
module, module,
win32Resources: null, win32Resources: null,
xmlDocStream: null, xmlDocStream: null,
generateDebugInfo: false, emittingPdb: false,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: null, filterOpt: null,
cancellationToken: CancellationToken.None); cancellationToken: CancellationToken.None);
...@@ -405,7 +405,7 @@ private static string GetNextMethodName(ArrayBuilder<MethodSymbol> builder) ...@@ -405,7 +405,7 @@ private static string GetNextMethodName(ArrayBuilder<MethodSymbol> builder)
module, module,
win32Resources: null, win32Resources: null,
xmlDocStream: null, xmlDocStream: null,
generateDebugInfo: false, emittingPdb: false,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: null, filterOpt: null,
cancellationToken: CancellationToken.None); cancellationToken: CancellationToken.None);
......
...@@ -154,7 +154,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator ...@@ -154,7 +154,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
moduleBuilder, moduleBuilder,
win32Resources:=Nothing, win32Resources:=Nothing,
xmlDocStream:=Nothing, xmlDocStream:=Nothing,
generateDebugInfo:=False, emittingPdb:=False,
diagnostics:=diagnostics, diagnostics:=diagnostics,
filterOpt:=Nothing, filterOpt:=Nothing,
cancellationToken:=CancellationToken.None) cancellationToken:=CancellationToken.None)
...@@ -327,7 +327,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator ...@@ -327,7 +327,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
moduleBuilder, moduleBuilder,
win32Resources:=Nothing, win32Resources:=Nothing,
xmlDocStream:=Nothing, xmlDocStream:=Nothing,
generateDebugInfo:=False, emittingPdb:=False,
diagnostics:=diagnostics, diagnostics:=diagnostics,
filterOpt:=Nothing, filterOpt:=Nothing,
cancellationToken:=CancellationToken.None) cancellationToken:=CancellationToken.None)
......
...@@ -84,7 +84,7 @@ internal static class CommonCompilationExtensions ...@@ -84,7 +84,7 @@ internal static class CommonCompilationExtensions
moduleBeingBuilt, moduleBeingBuilt,
win32Resources: null, win32Resources: null,
xmlDocStream: null, xmlDocStream: null,
generateDebugInfo: false, emittingPdb: false,
diagnostics: diagnostics, diagnostics: diagnostics,
filterOpt: null, filterOpt: null,
cancellationToken: cancellationToken)) cancellationToken: cancellationToken))
......
...@@ -381,6 +381,7 @@ public static void ThrowsArgumentException(string parameterName, Action del) ...@@ -381,6 +381,7 @@ public static void ThrowsArgumentException(string parameterName, Action del)
throw new Exception("No exception was thrown."); throw new Exception("No exception was thrown.");
} }
// compares against a baseline
public static void AssertEqualToleratingWhitespaceDifferences( public static void AssertEqualToleratingWhitespaceDifferences(
string expected, string expected,
string actual, string actual,
...@@ -397,6 +398,32 @@ public static void ThrowsArgumentException(string parameterName, Action del) ...@@ -397,6 +398,32 @@ public static void ThrowsArgumentException(string parameterName, Action del)
} }
} }
// compares two results (no baseline)
public static void AssertResultsEqual(string result1, string result2)
{
if (result1 != result2)
{
string message;
if (DiffToolAvailable)
{
string file1 = Path.GetTempFileName();
File.WriteAllText(file1, result1);
string file2 = Path.GetTempFileName();
File.WriteAllText(file2, result2);
message = MakeDiffToolLink(file1, file2);
}
else
{
message = GetAssertMessage(result1, result2);
}
Assert.True(false, message);
}
}
public static void AssertContainsToleratingWhitespaceDifferences(string expectedSubString, string actualString) public static void AssertContainsToleratingWhitespaceDifferences(string expectedSubString, string actualString)
{ {
expectedSubString = NormalizeWhitespace(expectedSubString); expectedSubString = NormalizeWhitespace(expectedSubString);
...@@ -481,7 +508,7 @@ public static string GetAssertMessage<T>(IEnumerable<T> expected, IEnumerable<T> ...@@ -481,7 +508,7 @@ public static string GetAssertMessage<T>(IEnumerable<T> expected, IEnumerable<T>
message.AppendLine(DiffUtil.DiffReport(expected, actual, comparer, itemInspector, itemSeparator)); message.AppendLine(DiffUtil.DiffReport(expected, actual, comparer, itemInspector, itemSeparator));
string link; string link;
if (TryGenerateExpectedSourceFielAndGetDiffLink(actualString, expected.Count(), expectedValueSourcePath, expectedValueSourceLine, out link)) if (TryGenerateExpectedSourceFileAndGetDiffLink(actualString, expected.Count(), expectedValueSourcePath, expectedValueSourceLine, out link))
{ {
message.AppendLine(link); message.AppendLine(link);
} }
...@@ -489,10 +516,10 @@ public static string GetAssertMessage<T>(IEnumerable<T> expected, IEnumerable<T> ...@@ -489,10 +516,10 @@ public static string GetAssertMessage<T>(IEnumerable<T> expected, IEnumerable<T>
return message.ToString(); return message.ToString();
} }
internal static bool TryGenerateExpectedSourceFielAndGetDiffLink(string actualString, int expectedLineCount, string expectedValueSourcePath, int expectedValueSourceLine, out string link) internal static bool TryGenerateExpectedSourceFileAndGetDiffLink(string actualString, int expectedLineCount, string expectedValueSourcePath, int expectedValueSourceLine, out string link)
{ {
// add a link to a .cmd file that opens a diff tool: // add a link to a .cmd file that opens a diff tool:
if (!string.IsNullOrEmpty(s_diffToolPath) && expectedValueSourcePath != null && expectedValueSourceLine != 0) if (DiffToolAvailable && expectedValueSourcePath != null && expectedValueSourceLine != 0)
{ {
var actualFile = Path.GetTempFileName(); var actualFile = Path.GetTempFileName();
var testFileLines = File.ReadAllLines(expectedValueSourcePath); var testFileLines = File.ReadAllLines(expectedValueSourcePath);
...@@ -501,10 +528,7 @@ internal static bool TryGenerateExpectedSourceFielAndGetDiffLink(string actualSt ...@@ -501,10 +528,7 @@ internal static bool TryGenerateExpectedSourceFielAndGetDiffLink(string actualSt
File.AppendAllText(actualFile, actualString); File.AppendAllText(actualFile, actualString);
File.AppendAllLines(actualFile, testFileLines.Skip(expectedValueSourceLine + expectedLineCount)); File.AppendAllLines(actualFile, testFileLines.Skip(expectedValueSourceLine + expectedLineCount));
var compareCmd = Path.GetTempFileName() + ".cmd"; link = MakeDiffToolLink(actualFile, expectedValueSourcePath);
File.WriteAllText(compareCmd, string.Format("\"{0}\" \"{1}\" \"{2}\"", s_diffToolPath, actualFile, expectedValueSourcePath));
link = "file://" + compareCmd;
s_diffLinks.Value.Add(Tuple.Create(expectedValueSourcePath, expectedValueSourceLine, link)); s_diffLinks.Value.Add(Tuple.Create(expectedValueSourcePath, expectedValueSourceLine, link));
return true; return true;
...@@ -514,6 +538,16 @@ internal static bool TryGenerateExpectedSourceFielAndGetDiffLink(string actualSt ...@@ -514,6 +538,16 @@ internal static bool TryGenerateExpectedSourceFielAndGetDiffLink(string actualSt
return false; return false;
} }
internal static bool DiffToolAvailable => !string.IsNullOrEmpty(s_diffToolPath);
internal static string MakeDiffToolLink(string actualFilePath, string expectedFilePath)
{
var compareCmd = Path.GetTempFileName() + ".cmd";
File.WriteAllText(compareCmd, string.Format("\"{0}\" \"{1}\" \"{2}\"", s_diffToolPath, actualFilePath, expectedFilePath));
return "file://" + compareCmd;
}
private static readonly Lazy<List<Tuple<string, int, string>>> s_diffLinks = new Lazy<List<Tuple<string, int, string>>>(() => private static readonly Lazy<List<Tuple<string, int, string>>> s_diffLinks = new Lazy<List<Tuple<string, int, string>>>(() =>
{ {
AppDomain.CurrentDomain.DomainUnload += (_, __) => AppDomain.CurrentDomain.DomainUnload += (_, __) =>
......
...@@ -84,7 +84,7 @@ private static string GetXmlString(XElement node, bool expectedIsXmlLiteral) ...@@ -84,7 +84,7 @@ private static string GetXmlString(XElement node, bool expectedIsXmlLiteral)
string expectedString = expectedIsXmlLiteral ? expected.Replace(" />\r\n", "/>\r\n") : string.Format("@\"{0}\"", expected.Replace("\"", "\"\"")); string expectedString = expectedIsXmlLiteral ? expected.Replace(" />\r\n", "/>\r\n") : string.Format("@\"{0}\"", expected.Replace("\"", "\"\""));
string link; string link;
if (AssertEx.TryGenerateExpectedSourceFielAndGetDiffLink(actualString, expectedString.Count(c => c == '\n') + 1, expectedValueSourcePath, expectedValueSourceLine, out link)) if (AssertEx.TryGenerateExpectedSourceFileAndGetDiffLink(actualString, expectedString.Count(c => c == '\n') + 1, expectedValueSourcePath, expectedValueSourceLine, out link))
{ {
assertText.AppendLine(link); assertText.AppendLine(link);
} }
......
...@@ -38,7 +38,7 @@ public static class CompilationExtensions ...@@ -38,7 +38,7 @@ public static class CompilationExtensions
getHostDiagnostics: null, getHostDiagnostics: null,
cancellationToken: default(CancellationToken)); cancellationToken: default(CancellationToken));
Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n, ", emitResult.Diagnostics.Select(d => d.ToString()))); Assert.True(emitResult.Success, "Diagnostics:\r\n" + string.Join("\r\n", emitResult.Diagnostics.Select(d => d.ToString())));
if (expectedWarnings != null) if (expectedWarnings != null)
{ {
......
...@@ -8,12 +8,14 @@ ...@@ -8,12 +8,14 @@
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable; using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Text; using System.Text;
using System.Xml.Linq; using System.Xml.Linq;
using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Emit;
using PDB::Roslyn.Test.MetadataUtilities;
using PDB::Roslyn.Test.PdbUtilities; using PDB::Roslyn.Test.PdbUtilities;
using Roslyn.Test.Utilities; using Roslyn.Test.Utilities;
using Xunit; using Xunit;
...@@ -194,6 +196,39 @@ public static void ValidateDebugDirectory(Stream peStream, string pdbPath) ...@@ -194,6 +196,39 @@ public static void ValidateDebugDirectory(Stream peStream, string pdbPath)
Assert.Equal(0, reader.ReadByte()); Assert.Equal(0, reader.ReadByte());
} }
public static void VerifyMetadataEqualModuloMvid(Stream peStream1, Stream peStream2)
{
peStream1.Position = 0;
peStream2.Position = 0;
var peReader1 = new PEReader(peStream1);
var peReader2 = new PEReader(peStream2);
var md1 = peReader1.GetMetadata().GetContent();
var md2 = peReader2.GetMetadata().GetContent();
var mdReader1 = peReader1.GetMetadataReader();
var mdReader2 = peReader2.GetMetadataReader();
var mvidIndex1 = mdReader1.GetModuleDefinition().Mvid;
var mvidIndex2 = mdReader2.GetModuleDefinition().Mvid;
var mvidOffset1 = mdReader1.GetHeapMetadataOffset(HeapIndex.Guid) + 16 * (MetadataTokens.GetHeapOffset(mvidIndex1) - 1);
var mvidOffset2 = mdReader2.GetHeapMetadataOffset(HeapIndex.Guid) + 16 * (MetadataTokens.GetHeapOffset(mvidIndex2) - 1);
if (!md1.RemoveRange(mvidOffset1, 16).SequenceEqual(md1.RemoveRange(mvidOffset2, 16)))
{
var mdw1 = new StringWriter();
var mdw2 = new StringWriter();
new MetadataVisualizer(mdReader1, mdw1).Visualize();
new MetadataVisualizer(mdReader2, mdw2).Visualize();
mdw1.Flush();
mdw2.Flush();
AssertEx.AssertResultsEqual(mdw1.ToString(), mdw2.ToString());
}
}
internal static string GetMethodIL(this CompilationTestData.MethodData method) internal static string GetMethodIL(this CompilationTestData.MethodData method)
{ {
return ILBuilderVisualizer.ILBuilderToString(method.ILBuilder); return ILBuilderVisualizer.ILBuilderToString(method.ILBuilder);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册