diff --git a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EETypeNameDecoder.cs b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EETypeNameDecoder.cs index e05907375ebeebe00fa63ce4af7fb8c4cfaaa75a..541d5c11f22d32c403e2f7175b4a442f07ce55a5 100644 --- a/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EETypeNameDecoder.cs +++ b/src/ExpressionEvaluator/CSharp/Source/ExpressionCompiler/EETypeNameDecoder.cs @@ -20,9 +20,8 @@ internal sealed class EETypeNameDecoder : TypeNameDecoder id.Equals(assembly.Identity), identity); + int index = this.Module.GetReferencedAssemblies().IndexOf(identity); if (index >= 0) { return index; @@ -31,6 +30,7 @@ protected override int GetIndexOfReferencedAssembly(AssemblyIdentity identity) { // Find placeholder Windows.winmd assembly (created // in MetadataUtilities.MakeAssemblyReferences). + var assemblies = this.Module.GetReferencedAssemblySymbols(); index = assemblies.IndexOf((assembly, unused) => assembly.Identity.IsWindowsRuntime(), (object)null); if (index >= 0) { @@ -58,7 +58,7 @@ protected override TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, re protected override TypeSymbol LookupTopLevelTypeDefSymbol(int referencedAssemblyIndex, ref MetadataTypeName emittedName) { - var assembly = this.GetAssemblies()[referencedAssemblyIndex]; + var assembly = this.Module.GetReferencedAssemblySymbols()[referencedAssemblyIndex]; return assembly.LookupTopLevelMetadataType(ref emittedName, digThroughForwardedTypes: true); } @@ -67,14 +67,11 @@ protected override TypeSymbol LookupTopLevelTypeDefSymbol(ref MetadataTypeName e return this.moduleSymbol.LookupTopLevelMetadataType(ref emittedName, out isNoPiaLocalType); } - private ImmutableArray GetAssemblies() - { - return _compilation.Assembly.Modules.Single().GetReferencedAssemblySymbols(); - } - private static AssemblyIdentity GetComponentAssemblyIdentity(ModuleSymbol module) { return ((PEModuleSymbol)module).Module.ReadAssemblyIdentityOrThrow(); } + + private ModuleSymbol Module => _compilation.Assembly.Modules.Single(); } } diff --git a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/UsingDebugInfoTests.cs b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/UsingDebugInfoTests.cs index 29fde3fb77410096a69021da62b303004079750e..b358c4b136235c13f3df46acc559e911aa9dff39 100644 --- a/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/UsingDebugInfoTests.cs +++ b/src/ExpressionEvaluator/CSharp/Test/ExpressionCompiler/UsingDebugInfoTests.cs @@ -8,8 +8,11 @@ using System.Reflection.Metadata; using System.Reflection.Metadata.Ecma335; using System.Reflection.PortableExecutable; +using Microsoft.CodeAnalysis.CodeGen; using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.ExpressionEvaluator; +using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.VisualStudio.Debugger.Evaluation.ClrCompilation; using Microsoft.DiaSymReader; using Roslyn.Test.PdbUtilities; @@ -1051,6 +1054,67 @@ class B includeSymbols: false); Assert.Null(error); } + + [WorkItem(2441, "https://github.com/dotnet/roslyn/issues/2441")] + [Fact] + public void AssemblyQualifiedNameResolutionWithUnification() + { + var source1 = @" +using SI = System.Int32; + +public class C1 +{ + void M() + { + } +} +"; + + var source2 = @" +public class C2 : C1 +{ +} +"; + ImmutableArray unused; + + var comp1 = CreateCompilation(source1, new[] { MscorlibRef_v20}, TestOptions.DebugDll, assemblyName: "A"); + byte[] dllBytes1; + byte[] pdbBytes1; + comp1.EmitAndGetReferences(out dllBytes1, out pdbBytes1, out unused); + var ref1 = AssemblyMetadata.CreateFromImage(dllBytes1).GetReference(display: "A"); + + var comp2 = CreateCompilation(source2, new[] { MscorlibRef_v4_0_30316_17626, ref1 }, TestOptions.DebugDll, assemblyName: "B"); + byte[] dllBytes2; + byte[] pdbBytes2; + comp2.EmitAndGetReferences(out dllBytes2, out pdbBytes2, out unused); + var ref2 = AssemblyMetadata.CreateFromImage(dllBytes2).GetReference(display: "B"); + + var modulesBuilder = ArrayBuilder.GetInstance(); + modulesBuilder.Add(ref1.ToModuleInstance(dllBytes1, new SymReader(pdbBytes1, dllBytes1))); + modulesBuilder.Add(ref2.ToModuleInstance(dllBytes2, new SymReader(pdbBytes2, dllBytes2))); + modulesBuilder.Add(MscorlibRef_v4_0_30316_17626.ToModuleInstance(fullImage: null, symReader: null)); + modulesBuilder.Add(ExpressionCompilerTestHelpers.IntrinsicAssemblyReference.ToModuleInstance(fullImage: null, symReader: null)); + + using (var runtime = new RuntimeInstance(modulesBuilder.ToImmutableAndFree())) + { + var context = CreateMethodContext(runtime, "C1.M"); + + string error; + var testData = new CompilationTestData(); + context.CompileExpression("typeof(SI)", out error, testData); + Assert.Null(error); + + testData.GetMethodData("<>x.<>m0").VerifyIL(@" +{ + // Code size 11 (0xb) + .maxstack 1 + IL_0000: ldtoken ""int"" + IL_0005: call ""System.Type System.Type.GetTypeFromHandle(System.RuntimeTypeHandle)"" + IL_000a: ret +} +"); + } + } } internal static class ImportChainExtensions diff --git a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EETypeNameDecoder.vb b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EETypeNameDecoder.vb index 16d23d1dc7fb8dfff17eabce2d6aa95d438739c7..38cca7558914557357b426d37c14a9d32326263c 100644 --- a/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EETypeNameDecoder.vb +++ b/src/ExpressionEvaluator/VisualBasic/Source/ExpressionCompiler/EETypeNameDecoder.vb @@ -18,15 +18,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Sub Protected Overrides Function GetIndexOfReferencedAssembly(identity As AssemblyIdentity) As Integer - Dim assemblies = GetAssemblies() + Dim assemblyIdentities = Me.Module.GetReferencedAssemblies() ' Find assembly matching identity. - Dim index = assemblies.IndexOf(Function(assembly, id) id.Equals(assembly.Identity), identity) + Dim index = assemblyIdentities.IndexOf(identity) If index >= 0 Then Return index End If If identity.IsWindowsComponent() Then ' Find placeholder Windows.winmd assembly (created ' in MetadataUtilities.MakeAssemblyReferences). + Dim assemblies = Me.Module.GetReferencedAssemblySymbols() index = assemblies.IndexOf(Function(assembly, unused) assembly.Identity.IsWindowsRuntime(), DirectCast(Nothing, Object)) If index >= 0 Then ' Find module in Windows.winmd matching identity. @@ -49,7 +50,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator End Function Protected Overrides Function LookupTopLevelTypeDefSymbol(referencedAssemblyIndex As Integer, ByRef emittedName As MetadataTypeName) As TypeSymbol - Dim assembly = GetAssemblies()(referencedAssemblyIndex) + Dim assembly = Me.Module.GetReferencedAssemblySymbols()(referencedAssemblyIndex) Return assembly.LookupTopLevelMetadataType(emittedName, digThroughForwardedTypes:=True) End Function @@ -57,14 +58,16 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator Return moduleSymbol.LookupTopLevelMetadataType(emittedName, isNoPiaLocalType) End Function - Private Function GetAssemblies() As ImmutableArray(Of AssemblySymbol) - Return _compilation.Assembly.Modules.Single().GetReferencedAssemblySymbols() - End Function - Private Shared Function GetComponentAssemblyIdentity([module] As ModuleSymbol) As AssemblyIdentity Return DirectCast([module], PEModuleSymbol).Module.ReadAssemblyIdentityOrThrow() End Function + Private ReadOnly Property [Module] As ModuleSymbol + Get + Return _compilation.Assembly.Modules.Single() + End Get + End Property + End Class End Namespace diff --git a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ImportDebugInfoTests.vb b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ImportDebugInfoTests.vb index 30ada8987c2e3385bc8545b361fbb0e42a460631..57f37cdac986ee447f124b4ba2cd880f49361169 100644 --- a/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ImportDebugInfoTests.vb +++ b/src/ExpressionEvaluator/VisualBasic/Test/ExpressionCompiler/ImportDebugInfoTests.vb @@ -7,7 +7,9 @@ Imports System.Reflection.Metadata Imports System.Reflection.Metadata.Ecma335 Imports System.Reflection.PortableExecutable Imports System.Runtime.InteropServices +Imports Microsoft.CodeAnalysis.CodeGen Imports Microsoft.CodeAnalysis.ExpressionEvaluator +Imports Microsoft.CodeAnalysis.Test.Utilities Imports Microsoft.CodeAnalysis.VisualBasic.ExpressionEvaluator Imports Microsoft.CodeAnalysis.VisualBasic.Symbols Imports Microsoft.CodeAnalysis.VisualBasic.Syntax @@ -468,6 +470,61 @@ End Namespace Assert.Equal("http://xml1", xmlNamespaces("C").XmlNamespace) End Sub + + + Public Sub AssemblyQualifiedNameResolutionWithUnification() + Const source1 = " +Imports SI = System.Int32 + +Public Class C1 + Sub M() + End Sub +End Class +" + + Const source2 = " +Public Class C2 : Inherits C1 +End Class +" + + Dim comp1 = CreateCompilationWithReferences(VisualBasicSyntaxTree.ParseText(source1), {MscorlibRef_v20}, TestOptions.DebugDll, assemblyName:="A") + Dim dllBytes1 As Byte() = Nothing + Dim pdbBytes1 As Byte() = Nothing + comp1.EmitAndGetReferences(dllBytes1, pdbBytes1, Nothing) + Dim ref1 = AssemblyMetadata.CreateFromImage(dllBytes1).GetReference(display:="A") + + Dim comp2 = CreateCompilationWithReferences(VisualBasicSyntaxTree.ParseText(source2), {MscorlibRef_v4_0_30316_17626, ref1}, TestOptions.DebugDll, assemblyName:="B") + Dim dllBytes2 As Byte() = Nothing + Dim pdbBytes2 As Byte() = Nothing + comp2.EmitAndGetReferences(dllBytes2, pdbBytes2, Nothing) + Dim ref2 = AssemblyMetadata.CreateFromImage(dllBytes2).GetReference(display:="B") + + Dim modulesBuilder = ArrayBuilder(Of ModuleInstance).GetInstance() + modulesBuilder.Add(ref1.ToModuleInstance(dllBytes1, New SymReader(pdbBytes1, dllBytes1))) + modulesBuilder.Add(ref2.ToModuleInstance(dllBytes2, New SymReader(pdbBytes2, dllBytes2))) + modulesBuilder.Add(MscorlibRef_v4_0_30316_17626.ToModuleInstance(fullImage:=Nothing, symReader:=Nothing)) + modulesBuilder.Add(ExpressionCompilerTestHelpers.IntrinsicAssemblyReference.ToModuleInstance(fullImage:=Nothing, symReader:=Nothing)) + + Using runtime As New RuntimeInstance(modulesBuilder.ToImmutableAndFree()) + Dim context = CreateMethodContext(runtime, "C1.M") + + Dim errorMessage As String = Nothing + Dim testData As New CompilationTestData() + context.CompileExpression("GetType(SI)", errorMessage, testData) + Assert.Null(errorMessage) + + testData.GetMethodData("<>x.<>m0").VerifyIL(" +{ + // Code size 11 (0xb) + .maxstack 1 + IL_0000: ldtoken ""Integer"" + IL_0005: call ""Function System.Type.GetTypeFromHandle(System.RuntimeTypeHandle) As System.Type"" + IL_000a: ret +} +") + End Using + End Sub + Private Shared Function GetExpressionStatement(compilation As Compilation) As ExpressionStatementSyntax Return DirectCast(compilation.SyntaxTrees.Single().GetRoot().DescendantNodes().OfType(Of InvocationExpressionSyntax).Single().Parent, ExpressionStatementSyntax) End Function @@ -511,7 +568,7 @@ End Namespace aliases = Nothing xmlNamespaces = Nothing - Const bindingFlags As BindingFlags = bindingFlags.NonPublic Or bindingFlags.Instance + Const bindingFlags As BindingFlags = BindingFlags.NonPublic Or BindingFlags.Instance Dim typesAndNamespacesField = GetType(ImportedTypesAndNamespacesMembersBinder).GetField("_importedSymbols", bindingFlags) Assert.NotNull(typesAndNamespacesField) Dim aliasesField = GetType(ImportAliasesBinder).GetField("_importedAliases", bindingFlags)