|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.ExpressionEvaluator;
namespace Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator
{
internal sealed class EETypeNameDecoder : TypeNameDecoder<PEModuleSymbol, TypeSymbol>
{
private readonly CSharpCompilation _compilation;
internal EETypeNameDecoder(CSharpCompilation compilation, PEModuleSymbol moduleSymbol) :
base(SymbolFactory.Instance, moduleSymbol)
{
_compilation = compilation;
}
protected override int GetIndexOfReferencedAssembly(AssemblyIdentity identity)
{
// Find assembly matching identity.
int index = Module.GetReferencedAssemblies().IndexOf(identity);
if (index >= 0)
{
return index;
}
if (identity.IsWindowsComponent())
{
// Find placeholder Windows.winmd assembly (created
// in MetadataUtilities.MakeAssemblyReferences).
var assemblies = Module.GetReferencedAssemblySymbols();
index = assemblies.IndexOf((assembly, unused) => assembly.Identity.IsWindowsRuntime(), arg: (object?)null);
if (index >= 0)
{
// Find module in Windows.winmd matching identity.
var modules = assemblies[index].Modules;
var moduleIndex = modules.IndexOf((m, id) => id.Equals(GetComponentAssemblyIdentity(m)), identity);
if (moduleIndex >= 0)
{
return index;
}
}
}
return -1;
}
protected override bool IsContainingAssembly(AssemblyIdentity identity)
{
return false;
}
protected override TypeSymbol LookupNestedTypeDefSymbol(TypeSymbol container, ref MetadataTypeName emittedName)
{
return container.LookupMetadataType(ref emittedName) ??
new MissingMetadataTypeSymbol.Nested((NamedTypeSymbol)container, ref emittedName);
}
protected override TypeSymbol LookupTopLevelTypeDefSymbol(int referencedAssemblyIndex, ref MetadataTypeName emittedName)
{
var assembly = Module.GetReferencedAssemblySymbol(referencedAssemblyIndex);
// GetReferencedAssemblySymbol should not return null since referencedAssemblyIndex
// was obtained from GetIndexOfReferencedAssembly above.
return assembly.LookupDeclaredOrForwardedTopLevelMetadataType(ref emittedName, visitedAssemblies: null);
}
protected override TypeSymbol LookupTopLevelTypeDefSymbol(ref MetadataTypeName emittedName, out bool isNoPiaLocalType)
{
return moduleSymbol.LookupTopLevelMetadataTypeWithNoPiaLocalTypeUnification(ref emittedName, out isNoPiaLocalType);
}
private static AssemblyIdentity GetComponentAssemblyIdentity(ModuleSymbol module)
{
return ((PEModuleSymbol)module).Module.ReadAssemblyIdentityOrThrow();
}
private ModuleSymbol Module => _compilation.Assembly.Modules.Single();
}
}
|