提交 d4f39a0d 编写于 作者: C Charles Stoner

Report no AssemblyReferences from corlib in EE

上级 12717c54
......@@ -125,9 +125,14 @@ protected override TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, re
int referencedAssemblyIndex,
ref MetadataTypeName emittedName)
{
var assembly = moduleSymbol.GetReferencedAssemblySymbol(referencedAssemblyIndex);
if ((object)assembly == null)
{
return new UnsupportedMetadataTypeSymbol();
}
try
{
AssemblySymbol assembly = moduleSymbol.GetReferencedAssemblySymbols()[referencedAssemblyIndex];
return assembly.LookupTopLevelMetadataType(ref emittedName, digThroughForwardedTypes: true);
}
catch (Exception e) when (FatalError.Report(e)) // Trying to get more useful Watson dumps.
......
......@@ -651,38 +651,39 @@ internal NamedTypeSymbol LookupTopLevelMetadataType(ref MetadataTypeName emitted
/// </remarks>
internal AssemblySymbol GetAssemblyForForwardedType(ref MetadataTypeName fullName)
{
try
{
string matchedName;
AssemblyReferenceHandle assemblyRef = Module.GetAssemblyForForwardedType(fullName.FullName, ignoreCase: false, matchedName: out matchedName);
return assemblyRef.IsNil ? null : this.GetReferencedAssemblySymbols()[Module.GetAssemblyReferenceIndexOrThrow(assemblyRef)];
}
catch (BadImageFormatException)
{
return null;
}
string matchedName;
AssemblyReferenceHandle assemblyRef = Module.GetAssemblyForForwardedType(fullName.FullName, ignoreCase: false, matchedName: out matchedName);
return assemblyRef.IsNil ? null : this.GetReferencedAssemblySymbol(assemblyRef);
}
internal IEnumerable<NamedTypeSymbol> GetForwardedTypes()
{
foreach (KeyValuePair<string, AssemblyReferenceHandle> forwarder in Module.GetForwardedTypes())
{
var name = MetadataTypeName.FromFullName(forwarder.Key);
AssemblySymbol assemblySymbol;
try
{
assemblySymbol = this.GetReferencedAssemblySymbols()[Module.GetAssemblyReferenceIndexOrThrow(forwarder.Value)];
}
catch (BadImageFormatException)
var assemblySymbol = this.GetReferencedAssemblySymbol(forwarder.Value);
if ((object)assemblySymbol == null)
{
continue;
}
var name = MetadataTypeName.FromFullName(forwarder.Key);
yield return assemblySymbol.LookupTopLevelMetadataType(ref name, digThroughForwardedTypes: true);
}
}
private AssemblySymbol GetReferencedAssemblySymbol(AssemblyReferenceHandle assemblyRef)
{
int referencedAssemblyIndex;
try
{
referencedAssemblyIndex = Module.GetAssemblyReferenceIndexOrThrow(assemblyRef);
}
catch (BadImageFormatException)
{
return null;
}
return this.GetReferencedAssemblySymbol(referencedAssemblyIndex);
}
public override ModuleMetadata GetMetadata() => _module.GetNonDisposableMetadata();
}
}
......@@ -4,12 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
......
......@@ -245,6 +245,25 @@ public ImmutableArray<AssemblySymbol> ReferencedAssemblySymbols
/// </summary>
internal abstract ImmutableArray<AssemblySymbol> GetReferencedAssemblySymbols(); // TODO: Remove this method and make ReferencedAssemblySymbols property abstract instead.
internal AssemblySymbol GetReferencedAssemblySymbol(int referencedAssemblyIndex)
{
var referencedAssemblies = GetReferencedAssemblySymbols();
if (referencedAssemblyIndex < referencedAssemblies.Length)
{
return referencedAssemblies[referencedAssemblyIndex];
}
// This module must be a corlib where the original metadata contains assembly
// references (see https://github.com/dotnet/roslyn/issues/13275).
var assembly = ContainingAssembly;
if ((object)assembly != assembly.CorLibrary)
{
throw new ArgumentOutOfRangeException(nameof(referencedAssemblyIndex));
}
return null;
}
/// <summary>
/// A helper method for ReferenceManager to set assembly identities for assemblies
/// referenced by this module and corresponding AssemblySymbols.
......
......@@ -10,11 +10,10 @@
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Threading;
using Roslyn.Utilities;
using System.Security.Cryptography;
namespace Microsoft.CodeAnalysis
{
......@@ -84,7 +83,10 @@ internal sealed class PEModule : IDisposable
private static readonly AttributeValueExtractor<ObsoleteAttributeData> s_attributeObsoleteDataExtractor = CrackObsoleteAttributeData;
private static readonly AttributeValueExtractor<ObsoleteAttributeData> s_attributeDeprecatedDataExtractor = CrackDeprecatedAttributeData;
internal PEModule(ModuleMetadata owner, PEReader peReader, IntPtr metadataOpt, int metadataSizeOpt, bool includeEmbeddedInteropTypes = false)
// 'ignoreAssemblyRefs' is used by the EE only, when debugging
// .NET Native, where the corlib may have assembly references
// (see https://github.com/dotnet/roslyn/issues/13275).
internal PEModule(ModuleMetadata owner, PEReader peReader, IntPtr metadataOpt, int metadataSizeOpt, bool includeEmbeddedInteropTypes, bool ignoreAssemblyRefs)
{
// shall not throw
......@@ -99,6 +101,11 @@ internal PEModule(ModuleMetadata owner, PEReader peReader, IntPtr metadataOpt, i
_lazyNamespaceNameCollection = new Lazy<IdentifierCollection>(ComputeNamespaceNameCollection);
_hashesOpt = (peReader != null) ? new PEHashProvider(peReader) : null;
_lazyContainsNoPiaLocalTypes = includeEmbeddedInteropTypes ? ThreeState.False : ThreeState.Unknown;
if (ignoreAssemblyRefs)
{
_lazyAssemblyReferences = ImmutableArray<AssemblyIdentity>.Empty;
}
}
private sealed class PEHashProvider : CryptographicHashProvider
......
......@@ -24,13 +24,13 @@ public sealed partial class ModuleMetadata : Metadata
private ModuleMetadata(PEReader peReader)
: base(isImageOwner: true, id: MetadataId.CreateNewId())
{
_module = new PEModule(this, peReader: peReader, metadataOpt: IntPtr.Zero, metadataSizeOpt: 0);
_module = new PEModule(this, peReader: peReader, metadataOpt: IntPtr.Zero, metadataSizeOpt: 0, includeEmbeddedInteropTypes: false, ignoreAssemblyRefs: false);
}
private ModuleMetadata(IntPtr metadata, int size, bool includeEmbeddedInteropTypes)
private ModuleMetadata(IntPtr metadata, int size, bool includeEmbeddedInteropTypes, bool ignoreAssemblyRefs)
: base(isImageOwner: true, id: MetadataId.CreateNewId())
{
_module = new PEModule(this, peReader: null, metadataOpt: metadata, metadataSizeOpt: size, includeEmbeddedInteropTypes: includeEmbeddedInteropTypes);
_module = new PEModule(this, peReader: null, metadataOpt: metadata, metadataSizeOpt: size, includeEmbeddedInteropTypes: includeEmbeddedInteropTypes, ignoreAssemblyRefs: ignoreAssemblyRefs);
}
// creates a copy
......@@ -60,14 +60,14 @@ public static ModuleMetadata CreateFromMetadata(IntPtr metadata, int size)
throw new ArgumentOutOfRangeException(CodeAnalysisResources.SizeHasToBePositive, nameof(size));
}
return new ModuleMetadata(metadata, size, includeEmbeddedInteropTypes: false);
return new ModuleMetadata(metadata, size, includeEmbeddedInteropTypes: false, ignoreAssemblyRefs: false);
}
internal static ModuleMetadata CreateFromMetadata(IntPtr metadata, int size, bool includeEmbeddedInteropTypes)
internal static ModuleMetadata CreateFromMetadata(IntPtr metadata, int size, bool includeEmbeddedInteropTypes, bool ignoreAssemblyRefs = false)
{
Debug.Assert(metadata != IntPtr.Zero);
Debug.Assert(size > 0);
return new ModuleMetadata(metadata, size, includeEmbeddedInteropTypes);
return new ModuleMetadata(metadata, size, includeEmbeddedInteropTypes, ignoreAssemblyRefs);
}
/// <summary>
......
......@@ -124,9 +124,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
referencedAssemblyIndex As Integer,
ByRef emittedName As MetadataTypeName
) As TypeSymbol
Try
Dim assembly As AssemblySymbol = moduleSymbol.GetReferencedAssemblySymbols()(referencedAssemblyIndex)
Dim assembly As AssemblySymbol = ModuleSymbol.GetReferencedAssemblySymbol(referencedAssemblyIndex)
If assembly Is Nothing Then
Return New UnsupportedMetadataTypeSymbol()
End If
Try
Return assembly.LookupTopLevelMetadataType(emittedName, digThroughForwardedTypes:=True)
Catch e As Exception When FatalError.Report(e) ' Trying to get more useful Watson dumps.
Throw ExceptionUtilities.Unreachable
......
......@@ -435,28 +435,31 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
''' </remarks>
Friend Function GetAssemblyForForwardedType(ByRef fullName As MetadataTypeName, ignoreCase As Boolean, <Out> ByRef matchedName As String) As AssemblySymbol
Dim assemblyRef As AssemblyReferenceHandle = Me.Module.GetAssemblyForForwardedType(fullName.FullName, ignoreCase, matchedName)
Try
Return If(assemblyRef.IsNil, Nothing, Me.GetReferencedAssemblySymbols()(Me.Module.GetAssemblyReferenceIndexOrThrow(assemblyRef)))
Catch mrEx As BadImageFormatException
Return Nothing
End Try
Return If(assemblyRef.IsNil, Nothing, GetReferencedAssemblySymbol(assemblyRef))
End Function
Friend Iterator Function GetForwardedTypes() As IEnumerable(Of NamedTypeSymbol)
For Each forwarder As KeyValuePair(Of String, AssemblyReferenceHandle) In Me.Module.GetForwardedTypes()
Dim assembly As AssemblySymbol
Try
assembly = Me.GetReferencedAssemblySymbols()(Me.Module.GetAssemblyReferenceIndexOrThrow(forwarder.Value))
Catch ex As BadImageFormatException
Dim assembly As AssemblySymbol = GetReferencedAssemblySymbol(forwarder.Value)
If assembly Is Nothing Then
Continue For
End Try
End If
Dim name = MetadataTypeName.FromFullName(forwarder.Key)
Yield assembly.LookupTopLevelMetadataType(name, digThroughForwardedTypes:=True)
Next
End Function
Private Overloads Function GetReferencedAssemblySymbol(assemblyRef As AssemblyReferenceHandle) As AssemblySymbol
Dim referencedAssemblyIndex As Integer
Try
referencedAssemblyIndex = Me.Module.GetAssemblyReferenceIndexOrThrow(assemblyRef)
Catch ex As BadImageFormatException
Return Nothing
End Try
Return GetReferencedAssemblySymbol(referencedAssemblyIndex)
End Function
Public Overrides Function GetMetadata() As ModuleMetadata
Return _module.GetNonDisposableMetadata()
End Function
......
......@@ -161,6 +161,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Symbols
''' </summary>
Friend MustOverride Function GetReferencedAssemblySymbols() As ImmutableArray(Of AssemblySymbol) ' TODO: Remove this method and make ReferencedAssemblySymbols property abstract instead.
Friend Function GetReferencedAssemblySymbol(referencedAssemblyIndex As Integer) As AssemblySymbol
Dim referencedAssemblies = GetReferencedAssemblySymbols()
If referencedAssemblyIndex < referencedAssemblies.Length Then
Return referencedAssemblies(referencedAssemblyIndex)
End If
' This module must be a corlib where the original metadata contains assembly
' references (see https://github.com/dotnet/roslyn/issues/13275).
Dim assembly = ContainingAssembly
If assembly IsNot assembly.CorLibrary Then
Throw New ArgumentOutOfRangeException(NameOf(referencedAssemblyIndex))
End If
Return Nothing
End Function
''' <summary>
''' A helper method for ReferenceManager to set assembly identities for assemblies
''' referenced by this module and corresponding AssemblySymbols.
......
......@@ -88,7 +88,12 @@ public override void DecodeLocalConstant(ref BlobReader reader, out TypeSymbol t
public override IAssemblySymbol GetReferencedAssembly(AssemblyReferenceHandle handle)
{
int index = _metadataDecoder.Module.GetAssemblyReferenceIndexOrThrow(handle);
return _metadataDecoder.ModuleSymbol.GetReferencedAssemblySymbols()[index];
var assembly = _metadataDecoder.ModuleSymbol.GetReferencedAssemblySymbol(index);
if (assembly == null)
{
throw new BadImageFormatException();
}
return assembly;
}
/// <exception cref="UnsupportedSignatureContent"></exception>
......
......@@ -58,7 +58,9 @@ protected override TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, re
protected override TypeSymbol LookupTopLevelTypeDefSymbol(int referencedAssemblyIndex, ref MetadataTypeName emittedName)
{
var assembly = this.Module.GetReferencedAssemblySymbols()[referencedAssemblyIndex];
var assembly = this.Module.GetReferencedAssemblySymbol(referencedAssemblyIndex);
// GetReferencedAssemblySymbol should not return null since referencedAssemblyIndex
// was obtained from GetIndexOfReferencedAssembly above.
return assembly.LookupTopLevelMetadataType(ref emittedName, digThroughForwardedTypes: true);
}
......
......@@ -8,7 +8,6 @@
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.VisualStudio.Debugger.Evaluation;
using Roslyn.Test.Utilities;
using Xunit;
......@@ -459,7 +458,6 @@ private MethodSymbol GetConstructedMethod(string source, string methodName, stri
Assert.NotEmpty(serializedTypeArgumentNames);
var typeParameters = instructionDecoder.GetAllTypeParameters(method);
Assert.NotEmpty(typeParameters);
var typeNameDecoder = new EETypeNameDecoder(compilation, (PEModuleSymbol)method.ContainingModule);
// Use the same helper method as the FrameDecoder to get the TypeSymbols for the
// generic type arguments (rather than using EETypeNameDecoder directly).
var typeArguments = instructionDecoder.GetTypeSymbols(compilation, method, serializedTypeArgumentNames);
......
// 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.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection.PortableExecutable;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.CSharp.UnitTests;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
using Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests;
......@@ -705,6 +711,250 @@ .maxstack 2
}");
}
private const string CorLibAssemblyName = "System.Private.CoreLib";
// An assembly with the expected corlib name and with System.Object should
// be considered the corlib, even with references to external assemblies.
[WorkItem(13275, "https://github.com/dotnet/roslyn/issues/13275")]
[Fact]
public void CorLibWithAssemblyReferences()
{
string sourceLib =
@"public class Private1
{
}
public class Private2
{
}";
var compLib = CreateCompilationWithMscorlib(sourceLib, assemblyName: "System.Private.Library");
compLib.VerifyDiagnostics();
var refLib = compLib.EmitToImageReference();
string sourceCorLib =
@"using System.Runtime.CompilerServices;
[assembly: TypeForwardedTo(typeof(Private2))]
namespace System
{
public class Object
{
public Private1 F() => null;
}
#pragma warning disable 0436
public class Void : Object { }
#pragma warning restore 0436
}";
// Create a custom corlib with a reference to compilation
// above and a reference to the actual mscorlib.
var compCorLib = CreateCompilation(sourceCorLib, assemblyName: CorLibAssemblyName, references: new[] { MscorlibRef, refLib });
compCorLib.VerifyDiagnostics();
var objectType = compCorLib.SourceAssembly.GlobalNamespace.GetMember<NamedTypeSymbol>("System.Object");
Assert.NotNull(objectType.BaseType);
ImmutableArray<byte> peBytes;
ImmutableArray<byte> pdbBytes;
ExpressionCompilerTestHelpers.EmitCorLibWithAssemblyReferences(
compCorLib,
null,
moduleBuilder => new PEAssemblyBuilderWithAdditionalReferences(moduleBuilder, objectType),
out peBytes,
out pdbBytes);
using (var reader = new PEReader(peBytes))
{
var metadata = reader.GetMetadata();
var module = metadata.ToModuleMetadata(ignoreAssemblyRefs: true);
var metadataReader = metadata.ToMetadataReader();
var moduleInstance = ModuleInstance.Create(metadata, metadataReader.GetModuleVersionIdOrThrow());
// Verify the module declares System.Object.
Assert.True(metadataReader.DeclaresTheObjectClass());
// Verify the PEModule has no assembly references.
Assert.Equal(0, module.Module.ReferencedAssemblies.Length);
// Verify the underlying metadata has the expected assembly references.
var actualReferences = metadataReader.AssemblyReferences.Select(r => metadataReader.GetString(metadataReader.GetAssemblyReference(r).Name)).ToImmutableArray();
AssertEx.Equal(new[] { "mscorlib", "System.Private.Library" }, actualReferences);
var source =
@"class C
{
static void M()
{
}
}";
var comp = CreateCompilation(source, options: TestOptions.DebugDll, references: new[] { refLib, AssemblyMetadata.Create(module).GetReference() });
comp.VerifyDiagnostics();
using (var runtime = RuntimeInstance.Create(new[] { comp.ToModuleInstance(), moduleInstance }))
{
string error;
var context = CreateMethodContext(runtime, "C.M");
// Valid expression.
var testData = new CompilationTestData();
context.CompileExpression(
"new object()",
out error,
testData);
Assert.Null(error);
testData.GetMethodData("<>x.<>m0").VerifyIL(
@"{
// Code size 6 (0x6)
.maxstack 1
IL_0000: newobj ""object..ctor()""
IL_0005: ret
}");
// Invalid expression: System.Int32 is not defined in corlib above.
testData = new CompilationTestData();
context.CompileExpression(
"1",
out error,
testData);
Assert.Equal("error CS0518: Predefined type 'System.Int32' is not defined or imported", error);
// Invalid expression: type in method signature from missing referenced assembly.
testData = new CompilationTestData();
context.CompileExpression(
"(new object()).F()",
out error,
testData);
Assert.Equal("error CS0570: 'object.F()' is not supported by the language", error);
// Invalid expression: type forwarded to missing referenced assembly.
testData = new CompilationTestData();
context.CompileExpression(
"new Private2()",
out error,
testData);
Assert.Equal("error CS0246: The type or namespace name 'Private2' could not be found (are you missing a using directive or an assembly reference?)", error);
}
}
}
// References to missing assembly from PDB custom debug info.
[WorkItem(13275, "https://github.com/dotnet/roslyn/issues/13275")]
[Fact]
public void CorLibWithAssemblyReferences_Pdb()
{
string sourceLib =
@"namespace Namespace
{
public class Private { }
}";
var compLib = CreateCompilationWithMscorlib(sourceLib, assemblyName: "System.Private.Library");
compLib.VerifyDiagnostics();
var refLib = compLib.EmitToImageReference(aliases: ImmutableArray.Create("A"));
string sourceCorLib =
@"extern alias A;
#pragma warning disable 8019
using N = A::Namespace;
namespace System
{
public class Object
{
public void F()
{
}
}
#pragma warning disable 0436
public class Void : Object { }
#pragma warning restore 0436
}";
// Create a custom corlib with a reference to compilation
// above and a reference to the actual mscorlib.
var compCorLib = CreateCompilation(sourceCorLib, assemblyName: CorLibAssemblyName, references: new[] { MscorlibRef, refLib });
compCorLib.VerifyDiagnostics();
var objectType = compCorLib.SourceAssembly.GlobalNamespace.GetMember<NamedTypeSymbol>("System.Object");
Assert.NotNull(objectType.BaseType);
var pdbPath = Temp.CreateDirectory().Path;
ImmutableArray<byte> peBytes;
ImmutableArray<byte> pdbBytes;
ExpressionCompilerTestHelpers.EmitCorLibWithAssemblyReferences(
compCorLib,
pdbPath,
moduleBuilder => new PEAssemblyBuilderWithAdditionalReferences(moduleBuilder, objectType),
out peBytes,
out pdbBytes);
var symReader = SymReaderFactory.CreateReader(pdbBytes);
using (var reader = new PEReader(peBytes))
{
var metadata = reader.GetMetadata();
var module = metadata.ToModuleMetadata(ignoreAssemblyRefs: true);
var metadataReader = metadata.ToMetadataReader();
var moduleInstance = ModuleInstance.Create(metadata, metadataReader.GetModuleVersionIdOrThrow(), symReader);
// Verify the module declares System.Object.
Assert.True(metadataReader.DeclaresTheObjectClass());
// Verify the PEModule has no assembly references.
Assert.Equal(0, module.Module.ReferencedAssemblies.Length);
// Verify the underlying metadata has the expected assembly references.
var actualReferences = metadataReader.AssemblyReferences.Select(r => metadataReader.GetString(metadataReader.GetAssemblyReference(r).Name)).ToImmutableArray();
AssertEx.Equal(new[] { "mscorlib", "System.Private.Library" }, actualReferences);
using (var runtime = RuntimeInstance.Create(new[] { moduleInstance }))
{
string error;
var context = CreateMethodContext(runtime, "System.Object.F");
var testData = new CompilationTestData();
// Invalid import: "using N = A::Namespace;".
context.CompileExpression(
"new N.Private()",
out error,
testData);
Assert.Equal("error CS0246: The type or namespace name 'N' could not be found (are you missing a using directive or an assembly reference?)", error);
}
}
}
// An assembly with the expected corlib name but without
// System.Object should not be considered the corlib.
[Fact]
public void CorLibWithAssemblyReferencesNoSystemObject()
{
// Assembly with expected corlib name but without System.Object declared.
string sourceLib =
@"class Private
{
}";
var compLib = CreateCompilationWithMscorlib(sourceLib, assemblyName: CorLibAssemblyName);
compLib.VerifyDiagnostics();
var refLib = compLib.EmitToImageReference();
var source =
@"class C
{
static void M()
{
}
}";
var comp = CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll);
comp.VerifyDiagnostics();
using (var runtime = RuntimeInstance.Create(new[] { comp.ToModuleInstance(), refLib.ToModuleInstance(), MscorlibRef.ToModuleInstance() }))
{
string error;
var context = CreateMethodContext(runtime, "C.M");
var testData = new CompilationTestData();
context.CompileExpression(
"1.GetType()",
out error,
testData);
Assert.Null(error);
testData.GetMethodData("<>x.<>m0").VerifyIL(
@"{
// Code size 12 (0xc)
.maxstack 1
IL_0000: ldc.i4.1
IL_0001: box ""int""
IL_0006: call ""System.Type object.GetType()""
IL_000b: ret
}");
}
}
private static ExpressionCompiler.CreateContextDelegate CreateTypeContextFactory(
Guid moduleVersionId,
int typeToken)
......@@ -738,5 +988,40 @@ .maxstack 2
{
return useReferencedModulesOnly ? blocks.ToCompilationReferencedModulesOnly(moduleVersionId) : blocks.ToCompilation();
}
private sealed class PEAssemblyBuilderWithAdditionalReferences : PEModuleBuilder, IAssemblyReference
{
private readonly CommonPEModuleBuilder _builder;
private readonly NamespaceTypeDefinitionNoBase _objectType;
internal PEAssemblyBuilderWithAdditionalReferences(CommonPEModuleBuilder builder, INamespaceTypeDefinition objectType) :
base((SourceModuleSymbol)builder.CommonSourceModule, builder.EmitOptions, builder.OutputKind, builder.SerializationProperties, builder.ManifestResources)
{
_builder = builder;
_objectType = new NamespaceTypeDefinitionNoBase(objectType);
}
internal override IEnumerable<INamespaceTypeDefinition> GetTopLevelTypesCore(EmitContext context)
{
foreach (var type in base.GetTopLevelTypesCore(context))
{
yield return (type == _objectType.UnderlyingType) ? _objectType : type;
}
}
public override int CurrentGenerationOrdinal => _builder.CurrentGenerationOrdinal;
public override ISourceAssemblySymbolInternal SourceAssemblyOpt => _builder.SourceAssemblyOpt;
public override IEnumerable<IFileReference> GetFiles(EmitContext context) => _builder.GetFiles(context);
protected override void AddEmbeddedResourcesFromAddedModules(ArrayBuilder<ManagedResource> builder, DiagnosticBag diagnostics)
{
}
AssemblyIdentity IAssemblyReference.Identity => ((IAssemblyReference)_builder).Identity;
Version IAssemblyReference.AssemblyVersionPattern => ((IAssemblyReference)_builder).AssemblyVersionPattern;
}
}
}
......@@ -8,7 +8,6 @@
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.DiaSymReader;
using Roslyn.Utilities;
......@@ -42,11 +41,35 @@ internal static class MetadataUtilities
// Windows.*.winmd into a single fake Windows.winmd at runtime.
// All other (application) winmds are left as is.
var runtimeWinMdBuilder = ArrayBuilder<ModuleMetadata>.GetInstance();
AssemblyIdentity corLibrary = null;
foreach (var block in metadataBlocks)
{
var metadata = ModuleMetadata.CreateFromMetadata(block.Pointer, block.Size, includeEmbeddedInteropTypes: true);
try
{
var reader = metadata.MetadataReader;
if (corLibrary == null)
{
bool hasNoAssemblyRefs = reader.AssemblyReferences.Count == 0;
// .NET Native uses a corlib with references
// (see https://github.com/dotnet/roslyn/issues/13275).
if (hasNoAssemblyRefs || metadata.Name.Equals("System.Private.CoreLib.dll", StringComparison.OrdinalIgnoreCase))
{
// If this assembly declares System.Object, assume it is the corlib.
// (Note, it is order dependent which assembly we treat as corlib
// if there are multiple assemblies that meet these requirements.
// That should be acceptable for evaluating expressions in the EE though.)
if (reader.DeclaresTheObjectClass())
{
corLibrary = reader.ReadAssemblyIdentityOrThrow();
// Compiler layer requires corlib to have no AssemblyRefs.
if (!hasNoAssemblyRefs)
{
metadata = ModuleMetadata.CreateFromMetadata(block.Pointer, block.Size, includeEmbeddedInteropTypes: true, ignoreAssemblyRefs: true);
}
}
}
}
if (IsWindowsComponent(metadata.MetadataReader, metadata.Name))
{
runtimeWinMdBuilder.Add(metadata);
......@@ -86,7 +109,6 @@ internal static class MetadataUtilities
// Build assembly references from modules in primary module manifests.
var referencesBuilder = ArrayBuilder<MetadataReference>.GetInstance();
var identitiesBuilder = (identityComparer == null) ? null : ArrayBuilder<AssemblyIdentity>.GetInstance();
AssemblyIdentity corLibrary = null;
AssemblyIdentity intrinsicsAssembly = null;
foreach (var metadata in metadataBuilder)
......@@ -100,15 +122,7 @@ internal static class MetadataUtilities
var reader = metadata.MetadataReader;
var identity = reader.ReadAssemblyIdentityOrThrow();
identitiesBuilder.Add(identity);
// If this assembly has no references, and declares
// System.Object, assume it is the COR library.
if ((corLibrary == null) &&
(reader.AssemblyReferences.Count == 0) &&
reader.DeclaresTheObjectClass())
{
corLibrary = identity;
}
else if ((intrinsicsAssembly == null) &&
if ((intrinsicsAssembly == null) &&
reader.DeclaresType((r, t) => r.IsPublicNonInterfaceType(t, ExpressionCompilerConstants.IntrinsicAssemblyNamespace, ExpressionCompilerConstants.IntrinsicAssemblyTypeName)))
{
intrinsicsAssembly = identity;
......
......@@ -6,7 +6,6 @@
using System.Reflection.Metadata.Ecma335;
using System.Text;
using Microsoft.CodeAnalysis.Debugging;
using Microsoft.CodeAnalysis.Collections;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator
{
......@@ -165,16 +164,9 @@ internal partial class MethodDebugInfo<TTypeSymbol, TLocalSymbol>
var importGroupsBuilder = ArrayBuilder<ImmutableArray<ImportRecord>>.GetInstance();
var externAliasesBuilder = ArrayBuilder<ExternAliasRecord>.GetInstance();
try
{
if (!innerMostImportScope.IsNil)
{
PopulateImports(reader, innerMostImportScope, symbolProvider, isVisualBasicMethod, importGroupsBuilder, externAliasesBuilder);
}
}
catch (Exception e) when (e is UnsupportedSignatureContent || e is BadImageFormatException)
if (!innerMostImportScope.IsNil)
{
// ignore invalid imports
PopulateImports(reader, innerMostImportScope, symbolProvider, isVisualBasicMethod, importGroupsBuilder, externAliasesBuilder);
}
importGroups = importGroupsBuilder.ToImmutableAndFree();
......@@ -206,7 +198,6 @@ private static string ReadUtf8String(ref BlobReader reader)
return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
}
/// <exception cref="BadImageFormatException">Invalid data format.</exception>
private static void PopulateImports(
MetadataReader reader,
ImportScopeHandle handle,
......@@ -221,70 +212,13 @@ private static string ReadUtf8String(ref BlobReader reader)
{
var importScope = reader.GetImportScope(handle);
foreach (ImportDefinition import in importScope.GetImports())
try
{
switch (import.Kind)
{
case ImportDefinitionKind.ImportNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
targetString: ReadUtf8String(reader, import.TargetNamespace)));
break;
case ImportDefinitionKind.ImportAssemblyNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
targetString: ReadUtf8String(reader, import.TargetNamespace),
targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly)));
break;
case ImportDefinitionKind.ImportType:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Type,
targetType: symbolProvider.GetType(import.TargetType)));
break;
case ImportDefinitionKind.ImportXmlNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.XmlNamespace,
alias: ReadUtf8String(reader, import.Alias),
targetString: ReadUtf8String(reader, import.TargetNamespace)));
break;
case ImportDefinitionKind.ImportAssemblyReferenceAlias:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Assembly,
alias: ReadUtf8String(reader, import.Alias)));
break;
case ImportDefinitionKind.AliasAssemblyReference:
externAliasesBuilder.Add(new ExternAliasRecord(
alias: ReadUtf8String(reader, import.Alias),
targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly)));
break;
case ImportDefinitionKind.AliasNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
alias: ReadUtf8String(reader, import.Alias),
targetString: ReadUtf8String(reader, import.TargetNamespace)));
break;
case ImportDefinitionKind.AliasAssemblyNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
alias: ReadUtf8String(reader, import.Alias),
targetString: ReadUtf8String(reader, import.TargetNamespace),
targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly)));
break;
case ImportDefinitionKind.AliasType:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Type,
alias: ReadUtf8String(reader, import.Alias),
targetType: symbolProvider.GetType(import.TargetType)));
break;
}
PopulateImports(reader, importScope, symbolProvider, importGroupBuilder, externAliasesBuilder);
}
catch (BadImageFormatException)
{
// ignore invalid imports
}
// VB always expects two import groups (even if they are empty).
......@@ -301,6 +235,81 @@ private static string ReadUtf8String(ref BlobReader reader)
importGroupBuilder.Free();
}
/// <exception cref="BadImageFormatException">Invalid data format.</exception>
private static void PopulateImports(
MetadataReader reader,
ImportScope importScope,
EESymbolProvider<TTypeSymbol, TLocalSymbol> symbolProvider,
ArrayBuilder<ImportRecord> importGroupBuilder,
ArrayBuilder<ExternAliasRecord> externAliasesBuilder)
{
foreach (ImportDefinition import in importScope.GetImports())
{
switch (import.Kind)
{
case ImportDefinitionKind.ImportNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
targetString: ReadUtf8String(reader, import.TargetNamespace)));
break;
case ImportDefinitionKind.ImportAssemblyNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
targetString: ReadUtf8String(reader, import.TargetNamespace),
targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly)));
break;
case ImportDefinitionKind.ImportType:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Type,
targetType: symbolProvider.GetType(import.TargetType)));
break;
case ImportDefinitionKind.ImportXmlNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.XmlNamespace,
alias: ReadUtf8String(reader, import.Alias),
targetString: ReadUtf8String(reader, import.TargetNamespace)));
break;
case ImportDefinitionKind.ImportAssemblyReferenceAlias:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Assembly,
alias: ReadUtf8String(reader, import.Alias)));
break;
case ImportDefinitionKind.AliasAssemblyReference:
externAliasesBuilder.Add(new ExternAliasRecord(
alias: ReadUtf8String(reader, import.Alias),
targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly)));
break;
case ImportDefinitionKind.AliasNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
alias: ReadUtf8String(reader, import.Alias),
targetString: ReadUtf8String(reader, import.TargetNamespace)));
break;
case ImportDefinitionKind.AliasAssemblyNamespace:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Namespace,
alias: ReadUtf8String(reader, import.Alias),
targetString: ReadUtf8String(reader, import.TargetNamespace),
targetAssembly: symbolProvider.GetReferencedAssembly(import.TargetAssembly)));
break;
case ImportDefinitionKind.AliasType:
importGroupBuilder.Add(new ImportRecord(
ImportTargetKind.Type,
alias: ReadUtf8String(reader, import.Alias),
targetType: symbolProvider.GetType(import.TargetType)));
break;
}
}
}
/// <exception cref="BadImageFormatException">Invalid data format.</exception>
private static void ReadMethodCustomDebugInformation(
MetadataReader reader,
......
......@@ -15,6 +15,8 @@
using System.Reflection.PortableExecutable;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using System.Threading;
using Microsoft.Cci;
using Microsoft.CodeAnalysis.CodeGen;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.Emit;
......@@ -733,5 +735,71 @@ internal static string GetMethodOrTypeSignatureParts(string signature, out strin
parameters.Split(',');
return methodName;
}
internal unsafe static ModuleMetadata ToModuleMetadata(this PEMemoryBlock metadata, bool ignoreAssemblyRefs)
{
return ModuleMetadata.CreateFromMetadata(
(IntPtr)metadata.Pointer,
metadata.Length,
includeEmbeddedInteropTypes: false,
ignoreAssemblyRefs: ignoreAssemblyRefs);
}
internal unsafe static MetadataReader ToMetadataReader(this PEMemoryBlock metadata)
{
return new MetadataReader(metadata.Pointer, metadata.Length, MetadataReaderOptions.None);
}
internal static void EmitCorLibWithAssemblyReferences(
Compilation comp,
string pdbPath,
Func<CommonPEModuleBuilder, CommonPEModuleBuilder> getModuleBuilder,
out ImmutableArray<byte> peBytes,
out ImmutableArray<byte> pdbBytes)
{
var diagnostics = DiagnosticBag.GetInstance();
var emitOptions = EmitOptions.Default.WithRuntimeMetadataVersion("0.0.0.0").WithDebugInformationFormat(DebugInformationFormat.PortablePdb);
var moduleBuilder = comp.CheckOptionsAndCreateModuleBuilder(
diagnostics,
null,
emitOptions,
null,
null,
null,
null,
default(CancellationToken));
// Wrap the module builder in a module builder that
// reports the "System.Object" type as having no base type.
moduleBuilder = getModuleBuilder(moduleBuilder);
bool result = comp.Compile(
moduleBuilder,
emittingPdb: pdbPath != null,
diagnostics: diagnostics,
filterOpt: null,
cancellationToken: default(CancellationToken));
using (var peStream = new MemoryStream())
{
using (var pdbStream = new MemoryStream())
{
PeWriter.WritePeToStream(
new EmitContext(moduleBuilder, null, diagnostics),
comp.MessageProvider,
() => peStream,
() => pdbStream,
null, null,
allowMissingMethodBodies: true,
isDeterministic: false,
cancellationToken: default(CancellationToken));
peBytes = peStream.ToImmutable();
pdbBytes = pdbStream.ToImmutable();
}
}
diagnostics.Verify();
diagnostics.Free();
}
}
}
......@@ -54,6 +54,7 @@
<Compile Include="ExpressionCompilerTestHelpers.cs" />
<Compile Include="MethodDebugInfoBytes.cs" />
<Compile Include="MethodDebugInfoValidation.cs" />
<Compile Include="NamespaceTypeDefinitionNoBase.cs" />
<Compile Include="NotImplementedSymUnmanaged.cs" />
<Compile Include="ModuleInstance.cs" />
<Compile Include="MockSymUnmanaged.cs" />
......@@ -83,4 +84,4 @@
</ItemGroup>
<ItemGroup />
<Import Project="..\..\..\..\..\build\Targets\Imports.targets" />
</Project>
</Project>
\ No newline at end of file
......@@ -2,12 +2,9 @@
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices;
using Microsoft.DiaSymReader;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
......@@ -40,24 +37,36 @@ internal sealed class ModuleInstance : IDisposable
_includeLocalSignatures = includeLocalSignatures;
}
public static ModuleInstance Create(IntPtr metadataAddress, int metadataLength, Guid moduleVersionId)
public unsafe static ModuleInstance Create(
PEMemoryBlock metadata,
Guid moduleVersionId,
ISymUnmanagedReader symReader = null)
{
return Create((IntPtr)metadata.Pointer, metadata.Length, moduleVersionId, symReader);
}
public static ModuleInstance Create(
IntPtr metadataAddress,
int metadataLength,
Guid moduleVersionId,
ISymUnmanagedReader symReader = null)
{
return new ModuleInstance(
metadata: null,
moduleVersionId: moduleVersionId,
metadataLength: metadataLength,
metadataAddress: metadataAddress,
symReader: null,
symReader: symReader,
includeLocalSignatures: false);
}
public unsafe static ModuleInstance Create(PortableExecutableReference reference)
public static ModuleInstance Create(PortableExecutableReference reference)
{
// make a copy of the metadata, so that we don't dispose the metadata of a reference that are shared accross tests:
return Create(reference.GetMetadata(), symReader: null, includeLocalSignatures: false);
}
public unsafe static ModuleInstance Create(ImmutableArray<byte> assemblyImage, ISymUnmanagedReader symReader, bool includeLocalSignatures = true)
public static ModuleInstance Create(ImmutableArray<byte> assemblyImage, ISymUnmanagedReader symReader, bool includeLocalSignatures = true)
{
// create a new instance of metadata, the resulting object takes an ownership:
return Create(AssemblyMetadata.CreateFromImage(assemblyImage), symReader, includeLocalSignatures);
......
// 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 Microsoft.Cci;
using Microsoft.CodeAnalysis.Emit;
using System.Collections.Generic;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
namespace Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
{
internal sealed class NamespaceTypeDefinitionNoBase : INamespaceTypeDefinition
{
internal readonly INamespaceTypeDefinition UnderlyingType;
internal NamespaceTypeDefinitionNoBase(INamespaceTypeDefinition underlyingType)
{
UnderlyingType = underlyingType;
}
ushort ITypeDefinition.Alignment => UnderlyingType.Alignment;
IGenericMethodParameterReference ITypeReference.AsGenericMethodParameterReference => UnderlyingType.AsGenericMethodParameterReference;
IGenericTypeInstanceReference ITypeReference.AsGenericTypeInstanceReference => UnderlyingType.AsGenericTypeInstanceReference;
IGenericTypeParameterReference ITypeReference.AsGenericTypeParameterReference => UnderlyingType.AsGenericTypeParameterReference;
INamespaceTypeReference ITypeReference.AsNamespaceTypeReference => UnderlyingType.AsNamespaceTypeReference;
INestedTypeReference ITypeReference.AsNestedTypeReference => UnderlyingType.AsNestedTypeReference;
ISpecializedNestedTypeReference ITypeReference.AsSpecializedNestedTypeReference => UnderlyingType.AsSpecializedNestedTypeReference;
IEnumerable<IEventDefinition> ITypeDefinition.Events => UnderlyingType.Events;
ushort INamedTypeReference.GenericParameterCount => 0;
ushort ITypeDefinition.GenericParameterCount => 0;
IEnumerable<IGenericTypeParameter> ITypeDefinition.GenericParameters => UnderlyingType.GenericParameters;
bool ITypeDefinition.HasDeclarativeSecurity => UnderlyingType.HasDeclarativeSecurity;
bool ITypeDefinition.IsAbstract => UnderlyingType.IsAbstract;
bool ITypeDefinition.IsBeforeFieldInit => UnderlyingType.IsBeforeFieldInit;
bool ITypeDefinition.IsComObject => UnderlyingType.IsComObject;
bool ITypeReference.IsEnum => UnderlyingType.IsEnum;
bool ITypeDefinition.IsGeneric => UnderlyingType.IsGeneric;
bool ITypeDefinition.IsInterface => UnderlyingType.IsInterface;
bool INamespaceTypeDefinition.IsPublic => UnderlyingType.IsPublic;
bool ITypeDefinition.IsRuntimeSpecial => UnderlyingType.IsRuntimeSpecial;
bool ITypeDefinition.IsSealed => UnderlyingType.IsSealed;
bool ITypeDefinition.IsSerializable => UnderlyingType.IsSerializable;
bool ITypeDefinition.IsSpecialName => UnderlyingType.IsSpecialName;
bool ITypeReference.IsValueType => UnderlyingType.IsValueType;
bool ITypeDefinition.IsWindowsRuntimeImport => UnderlyingType.IsWindowsRuntimeImport;
LayoutKind ITypeDefinition.Layout => UnderlyingType.Layout;
bool INamedTypeReference.MangleName => UnderlyingType.MangleName;
string INamedEntity.Name => UnderlyingType.Name;
string INamespaceTypeReference.NamespaceName => UnderlyingType.NamespaceName;
IEnumerable<SecurityAttribute> ITypeDefinition.SecurityAttributes => UnderlyingType.SecurityAttributes;
uint ITypeDefinition.SizeOf => UnderlyingType.SizeOf;
CharSet ITypeDefinition.StringFormat => UnderlyingType.StringFormat;
TypeDefinitionHandle ITypeReference.TypeDef => UnderlyingType.TypeDef;
IDefinition IReference.AsDefinition(EmitContext context) => UnderlyingType.AsDefinition(context);
INamespaceTypeDefinition ITypeReference.AsNamespaceTypeDefinition(EmitContext context) => UnderlyingType.AsNamespaceTypeDefinition(context);
INestedTypeDefinition ITypeReference.AsNestedTypeDefinition(EmitContext context) => UnderlyingType.AsNestedTypeDefinition(context);
ITypeDefinition ITypeReference.AsTypeDefinition(EmitContext context) => UnderlyingType.AsTypeDefinition(context);
void IReference.Dispatch(MetadataVisitor visitor) => UnderlyingType.Dispatch(visitor);
IEnumerable<ICustomAttribute> IReference.GetAttributes(EmitContext context) => UnderlyingType.GetAttributes(context);
ITypeReference ITypeDefinition.GetBaseClass(EmitContext context) => null;
IEnumerable<Cci.MethodImplementation> ITypeDefinition.GetExplicitImplementationOverrides(EmitContext context) => UnderlyingType.GetExplicitImplementationOverrides(context);
IEnumerable<IFieldDefinition> ITypeDefinition.GetFields(EmitContext context) => UnderlyingType.GetFields(context);
IEnumerable<IMethodDefinition> ITypeDefinition.GetMethods(EmitContext context) => UnderlyingType.GetMethods(context);
IEnumerable<INestedTypeDefinition> ITypeDefinition.GetNestedTypes(EmitContext context) => UnderlyingType.GetNestedTypes(context);
IEnumerable<IPropertyDefinition> ITypeDefinition.GetProperties(EmitContext context) => UnderlyingType.GetProperties(context);
ITypeDefinition ITypeReference.GetResolvedType(EmitContext context) => UnderlyingType.GetResolvedType(context);
IUnitReference INamespaceTypeReference.GetUnit(EmitContext context) => UnderlyingType.GetUnit(context);
IEnumerable<TypeReferenceWithAttributes> ITypeDefinition.Interfaces(EmitContext context) => UnderlyingType.Interfaces(context);
Cci.PrimitiveTypeCode ITypeReference.TypeCode(EmitContext context) => UnderlyingType.TypeCode(context);
}
}
......@@ -50,7 +50,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
End Function
Protected Overrides Function LookupTopLevelTypeDefSymbol(referencedAssemblyIndex As Integer, ByRef emittedName As MetadataTypeName) As TypeSymbol
Dim assembly = Me.Module.GetReferencedAssemblySymbols()(referencedAssemblyIndex)
Dim assembly As AssemblySymbol = Me.Module.GetReferencedAssemblySymbol(referencedAssemblyIndex)
' GetReferencedAssemblySymbol should not return Nothing since referencedAssemblyIndex
' was obtained from GetIndexOfReferencedAssembly above.
Return assembly.LookupTopLevelMetadataType(emittedName, digThroughForwardedTypes:=True)
End Function
......
......@@ -2,7 +2,6 @@
Imports System
Imports System.Collections.Immutable
Imports System.Diagnostics
Imports System.Reflection.Metadata
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
......@@ -66,7 +65,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
''' <exception cref="BadImageFormatException"></exception>
Public Overrides Function GetReferencedAssembly(handle As AssemblyReferenceHandle) As IAssemblySymbol
Dim index As Integer = _metadataDecoder.Module.GetAssemblyReferenceIndexOrThrow(handle)
Return _metadataDecoder.ModuleSymbol.GetReferencedAssemblySymbols()(index)
Dim assembly = _metadataDecoder.ModuleSymbol.GetReferencedAssemblySymbol(index)
' GetReferencedAssemblySymbol should not return Nothing since this method is
' only used for import aliases in the PDB which are not supported from VB.
Return assembly
End Function
''' <exception cref="UnsupportedSignatureContent"></exception>
......
......@@ -519,7 +519,6 @@ End Class"
Assert.NotEmpty(serializedTypeArgumentNames)
Dim typeParameters = instructionDecoder.GetAllTypeParameters(method)
Assert.NotEmpty(typeParameters)
Dim typeNameDecoder = New EETypeNameDecoder(compilation, DirectCast(method.ContainingModule, PEModuleSymbol))
' Use the same helper method as the FrameDecoder to get the TypeSymbols for the
' generic type arguments (rather than using EETypeNameDecoder directly).
Dim typeArgumentSymbols = instructionDecoder.GetTypeSymbols(compilation, method, serializedTypeArgumentNames)
......
' 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.Collections.Immutable
Imports System.Reflection.Metadata
Imports System.Reflection.PortableExecutable
Imports Microsoft.Cci
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols.Metadata.PE
Imports Microsoft.CodeAnalysis.VisualBasic.UnitTests
Imports Microsoft.DiaSymReader
Imports Roslyn.Test.PdbUtilities
......@@ -27,7 +34,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator.UnitTests
"Public Class A
End Class"
Const sourceB =
"Public Class B
"Public Class B
Public F As New A()
End Class"
Const sourceC =
......@@ -436,6 +443,118 @@ End Class"
End Sub)
End Sub
Private Const CorLibAssemblyName = "System.Private.CoreLib"
' An assembly with the expected corlib name and with System.Object should
' be considered the corlib, even with references to external assemblies.
<WorkItem(13275, "https://github.com/dotnet/roslyn/issues/13275")>
<Fact>
Public Sub CorLibWithAssemblyReferences()
Const sourceLib =
"Public Class Private1
End Class
Public Class Private2
End Class"
Dim compLib = CreateCompilationWithMscorlib(
{sourceLib},
options:=TestOptions.ReleaseDll,
assemblyName:="System.Private.Library")
compLib.VerifyDiagnostics()
Dim refLib = compLib.EmitToImageReference()
Const sourceCorLib =
"Imports System.Runtime.CompilerServices
<Assembly: TypeForwardedTo(GetType(Private2))>
Namespace System
Public Class [Object]
Public Function F() As Private1
Return Nothing
End Function
End Class
Public Class Void
Inherits [Object]
End Class
End Namespace"
' Create a custom corlib with a reference to compilation
' above and a reference to the actual mscorlib.
Dim compCorLib = CreateCompilation(
{Parse(sourceCorLib)},
options:=TestOptions.ReleaseDll,
references:={MscorlibRef, refLib},
assemblyName:=CorLibAssemblyName)
compCorLib.VerifyDiagnostics()
Dim objectType = compCorLib.SourceAssembly.GlobalNamespace.GetMember(Of NamedTypeSymbol)("System.Object")
Assert.NotNull(objectType.BaseType)
Dim peBytes As ImmutableArray(Of Byte) = Nothing
Dim pdbBytes As ImmutableArray(Of Byte) = Nothing
ExpressionCompilerTestHelpers.EmitCorLibWithAssemblyReferences(
compCorLib,
Nothing,
Function(moduleBuilder) New PEAssemblyBuilderWithAdditionalReferences(moduleBuilder, objectType),
peBytes,
pdbBytes)
Using reader As New PEReader(peBytes)
Dim metadata = reader.GetMetadata()
Dim [module] = metadata.ToModuleMetadata(ignoreAssemblyRefs:=True)
Dim metadataReader = metadata.ToMetadataReader()
Dim moduleInstance = Microsoft.CodeAnalysis.ExpressionEvaluator.UnitTests.ModuleInstance.Create(metadata, metadataReader.GetModuleVersionIdOrThrow())
' Verify the module declares System.Object.
Assert.True(metadataReader.DeclaresTheObjectClass())
' Verify the PEModule has no assembly references.
Assert.Equal(0, [module].Module.ReferencedAssemblies.Length)
' Verify the underlying metadata has the expected assembly references.
Dim actualReferences = metadataReader.AssemblyReferences.Select(Function(r) metadataReader.GetString(metadataReader.GetAssemblyReference(r).Name)).ToImmutableArray()
AssertEx.Equal({"mscorlib", "System.Private.Library"}, actualReferences)
Const source =
"Class C
Shared Sub M()
End Sub
End Class"
Dim comp = CreateCompilation(
{Parse(source)},
options:=TestOptions.ReleaseDll,
references:={refLib, AssemblyMetadata.Create([module]).GetReference()})
comp.VerifyDiagnostics()
Using runtime = RuntimeInstance.Create({comp.ToModuleInstance(), moduleInstance})
Dim errorMessage As String = Nothing
Dim context = CreateMethodContext(runtime, "C.M")
' Valid expression.
Dim testData = New CompilationTestData()
context.CompileExpression("New Object()", errorMessage, testData)
Assert.Null(errorMessage)
Dim methodData = testData.GetMethodData("<>x.<>m0")
methodData.VerifyIL(
"{
// Code size 6 (0x6)
.maxstack 1
IL_0000: newobj ""Sub Object..ctor()""
IL_0005: ret
}")
' Invalid expression: System.Int32 is not defined in corlib above.
testData = New CompilationTestData()
context.CompileExpression("1", errorMessage, testData)
Assert.Equal("error BC30002: Type 'System.Int32' is not defined.", errorMessage)
' Invalid expression: type in method signature from missing referenced assembly.
testData = New CompilationTestData()
context.CompileExpression("(New Object()).F()", errorMessage, testData)
Assert.Equal("error BC30657: 'F' has a return type that is not supported or parameter types that are not supported.", errorMessage)
' Invalid expression: type forwarded to missing referenced assembly.
testData = New CompilationTestData()
context.CompileExpression("New Private2()", errorMessage, testData)
Assert.Equal("error BC30002: Type 'Private2' is not defined.", errorMessage)
End Using
End Using
End Sub
Private Shared Function CreateTypeContextFactory(
moduleVersionId As Guid,
typeToken As Integer) As ExpressionCompiler.CreateContextDelegate
......@@ -469,6 +588,64 @@ End Class"
End Function
End Function
Private NotInheritable Class PEAssemblyBuilderWithAdditionalReferences
Inherits PEModuleBuilder
Implements IAssemblyReference
Private ReadOnly _builder As CommonPEModuleBuilder
Private ReadOnly _objectType As NamespaceTypeDefinitionNoBase
Friend Sub New(builder As CommonPEModuleBuilder, objectType As INamespaceTypeDefinition)
MyBase.New(DirectCast(builder.CommonSourceModule, SourceModuleSymbol), builder.EmitOptions, builder.OutputKind, builder.SerializationProperties, builder.ManifestResources)
_builder = builder
_objectType = New NamespaceTypeDefinitionNoBase(objectType)
End Sub
Friend Overrides Iterator Function GetTopLevelTypesCore(context As EmitContext) As IEnumerable(Of INamespaceTypeDefinition)
For Each t In MyBase.GetTopLevelTypesCore(context)
Yield If(t Is _objectType.UnderlyingType, _objectType, t)
Next
End Function
Public Overrides ReadOnly Property CurrentGenerationOrdinal As Integer
Get
Return _builder.CurrentGenerationOrdinal
End Get
End Property
Public Overrides ReadOnly Property SourceAssemblyOpt As ISourceAssemblySymbolInternal
Get
Return _builder.SourceAssemblyOpt
End Get
End Property
Public Overrides Function GetFiles(context As EmitContext) As IEnumerable(Of IFileReference)
Return _builder.GetFiles(context)
End Function
Protected Overrides Sub AddEmbeddedResourcesFromAddedModules(builder As ArrayBuilder(Of Cci.ManagedResource), diagnostics As DiagnosticBag)
End Sub
Friend Overrides ReadOnly Property AllowOmissionOfConditionalCalls As Boolean
Get
Return True
End Get
End Property
Private ReadOnly Property Identity As AssemblyIdentity Implements IAssemblyReference.Identity
Get
Return DirectCast(_builder, IAssemblyReference).Identity
End Get
End Property
Private ReadOnly Property AssemblyVersionPattern As Version Implements IAssemblyReference.AssemblyVersionPattern
Get
Return DirectCast(_builder, IAssemblyReference).AssemblyVersionPattern
End Get
End Property
End Class
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册