When finding a type def from a type ref, search all assemblies (#1919)

This commit is contained in:
Daniel Paoliello 2024-06-04 11:34:15 -07:00 коммит произвёл GitHub
Родитель 8c02061909
Коммит 19ceee6047
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
4 изменённых файлов: 77 добавлений и 44 удалений

Просмотреть файл

@ -544,44 +544,43 @@ namespace ClangSharpSourceToWinmd
interfaceWalker.Visit(tree.GetRoot());
}
foreach (var r in this.compilation.References)
var allWinmds = this.compilation.References.Where(r => !r.Display.EndsWith("netstandard.dll")).Select(r => MetadataUtils.WinmdUtils.LoadFromFile(r.Display)).ToList();
foreach (var winmd in allWinmds)
{
if (r.Display.EndsWith("netstandard.dll"))
foreach (var typeInfo in winmd.GetTypes(allWinmds))
{
continue;
}
using (var winmd = MetadataUtils.WinmdUtils.LoadFromFile(r.Display))
{
foreach (var typeInfo in winmd.GetTypes())
if (typeInfo is MetadataUtils.InterfaceInfo interfaceInfo)
{
if (typeInfo is MetadataUtils.InterfaceInfo interfaceInfo)
{
this.CacheInterfaceInfo(interfaceInfo);
}
else if (typeInfo is MetadataUtils.StructInfo)
{
var fullName = $"{typeInfo.Namespace}.{typeInfo.Name}";
var typeSymbol = this.compilation.GetTypeByMetadataName(fullName);
this.CacheInterfaceInfo(interfaceInfo);
}
else if (typeInfo is MetadataUtils.StructInfo)
{
var fullName = $"{typeInfo.Namespace}.{typeInfo.Name}";
var typeSymbol = this.compilation.GetTypeByMetadataName(fullName);
if (typeSymbol != null)
{
this.nameToSymbols[typeInfo.Name] = typeSymbol;
}
}
else if (typeInfo is MetadataUtils.DelegateTypeInfo)
if (typeSymbol != null)
{
var fullName = $"{typeInfo.Namespace}.{typeInfo.Name}";
var typeSymbol = this.compilation.GetTypeByMetadataName(fullName);
this.nameToSymbols[typeInfo.Name] = typeSymbol;
}
}
else if (typeInfo is MetadataUtils.DelegateTypeInfo)
{
var fullName = $"{typeInfo.Namespace}.{typeInfo.Name}";
var typeSymbol = this.compilation.GetTypeByMetadataName(fullName);
if (typeSymbol != null)
{
this.nameToSymbols[typeInfo.Name] = typeSymbol;
}
if (typeSymbol != null)
{
this.nameToSymbols[typeInfo.Name] = typeSymbol;
}
}
}
}
foreach (var winmd in allWinmds)
{
winmd.Dispose();
}
}
}

Просмотреть файл

@ -131,7 +131,7 @@ namespace MetadataUtils
}
}
public IEnumerable<TypeInfo> GetTypes()
public IEnumerable<TypeInfo> GetTypes(List<WinmdUtils> allWinmds)
{
foreach (var typeDefHandle in this.metadataReader.TypeDefinitions)
{
@ -185,7 +185,7 @@ namespace MetadataUtils
}
else if (typeDef.Attributes.HasFlag(TypeAttributes.Interface))
{
var implementedMethodCount = this.InternalGetImplementedMethodCount(typeDef);
var implementedMethodCount = this.InternalGetImplementedMethodCount(typeDef, allWinmds);
var methodInfos = this.GetMethodInfos(typeDef.GetMethods());
yield return new InterfaceInfo(ns, name, methodInfos, implementedMethodCount);
}
@ -207,7 +207,7 @@ namespace MetadataUtils
}
}
private int InternalGetImplementedMethodCount(TypeDefinition typeDef)
private int InternalGetImplementedMethodCount(TypeDefinition typeDef, List<WinmdUtils> allWinmds)
{
int methodCount = typeDef.GetMethods().Count;
var interfaceImplHandles = typeDef.GetInterfaceImplementations();
@ -220,12 +220,7 @@ namespace MetadataUtils
{
case HandleKind.TypeReference:
{
var interfaceTypeRefHandle = this.metadataReader.GetTypeReference((TypeReferenceHandle)interfaceImpl.Interface);
interfaceTypeDef = this.metadataReader.TypeDefinitions
.Select(h => this.metadataReader.GetTypeDefinition(h))
.First(iterType =>
this.metadataReader.GetString(iterType.Name) == this.metadataReader.GetString(interfaceTypeRefHandle.Name) &&
this.metadataReader.GetString(iterType.Namespace) == this.metadataReader.GetString(interfaceTypeRefHandle.Namespace));
interfaceTypeDef = this.GetDefinitionFromReference(this.metadataReader.GetTypeReference((TypeReferenceHandle)interfaceImpl.Interface), allWinmds);
break;
}
@ -243,6 +238,27 @@ namespace MetadataUtils
return methodCount;
}
public TypeDefinition GetDefinitionFromReference(TypeReference typeReference, List<WinmdUtils> allWinmds)
{
var name = this.metadataReader.GetString(typeReference.Name);
var @namespace = this.metadataReader.GetString(typeReference.Namespace);
foreach (var winmd in allWinmds)
{
foreach (var typeDefinitionHandle in winmd.metadataReader.TypeDefinitions)
{
var typeDefinition = winmd.metadataReader.GetTypeDefinition(typeDefinitionHandle);
if (winmd.metadataReader.GetString(typeDefinition.Name) == name &&
winmd.metadataReader.GetString(typeDefinition.Namespace) == @namespace)
{
return typeDefinition;
}
}
}
throw new InvalidOperationException($"Could not find definition for '{@namespace}.{name}'");
}
}
public class TypeInfo

Просмотреть файл

@ -417,13 +417,14 @@ namespace WinmdUtilsProgram
public static int ShowPointersToDelegates(FileInfo winmd, string[] allowItem, IConsole console)
{
List<WinmdUtils> allWinmds = new List<WinmdUtils>();
HashSet<string> allowTable = new HashSet<string>(allowItem);
using WinmdUtils w1 = WinmdUtils.LoadFromFile(winmd.FullName);
bool pointersFound = false;
HashSet<string> delegateNames = new HashSet<string>(w1.GetTypes().Where(t => t is DelegateTypeInfo).Select(d => $"{d.Namespace}.{d.Name}"));
HashSet<string> delegateNames = new HashSet<string>(w1.GetTypes(allWinmds).Where(t => t is DelegateTypeInfo).Select(d => $"{d.Namespace}.{d.Name}"));
foreach (var type in w1.GetTypes())
foreach (var type in w1.GetTypes(allWinmds))
{
foreach (var pointerInUse in PointerToOneOfNamesInUse(delegateNames, type))
{
@ -690,10 +691,11 @@ namespace WinmdUtilsProgram
public static int ShowEmptyDelegates(FileInfo winmd, string[] allowItem, IConsole console)
{
List<WinmdUtils> allWinmds = new List<WinmdUtils>();
HashSet<string> allowTable = new HashSet<string>(allowItem);
using WinmdUtils w1 = WinmdUtils.LoadFromFile(winmd.FullName);
bool emptyFound = false;
foreach (DelegateTypeInfo type in w1.GetTypes().Where(t => t is DelegateTypeInfo))
foreach (DelegateTypeInfo type in w1.GetTypes(allWinmds).Where(t => t is DelegateTypeInfo))
{
if (!type.Parameters.Any())
{

Просмотреть файл

@ -1,4 +1,5 @@
using System.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Xunit;
@ -8,6 +9,7 @@ namespace MetadataUtils.Tests
public interface IFoo { void B(); }
public interface IBar : IBase { void C(); }
public interface IQux : IFoo, IBar { void D(); }
public interface IInheritsFromOther : IRegexConstHelper { }
public class WinmdUtilsTests
{
@ -18,7 +20,7 @@ namespace MetadataUtils.Tests
// Act
using var metadata = WinmdUtils.LoadFromFile(Assembly.GetExecutingAssembly().Location);
var typeInfo = metadata.GetTypes().First(t => t.Name == "IQux") as InterfaceInfo;
var typeInfo = metadata.GetTypes(new List<WinmdUtils> { metadata }).First(t => t.Name == "IQux") as InterfaceInfo;
// Assert
Assert.Equal(4, typeInfo.ImplementedMethodCount);
@ -31,7 +33,7 @@ namespace MetadataUtils.Tests
// Act
using var metadata = WinmdUtils.LoadFromFile(Assembly.GetExecutingAssembly().Location);
var typeInfo = metadata.GetTypes().First(t => t.Name == "IFoo") as InterfaceInfo;
var typeInfo = metadata.GetTypes(new List<WinmdUtils> { metadata }).First(t => t.Name == "IFoo") as InterfaceInfo;
// Assert
Assert.Equal(1, typeInfo.ImplementedMethodCount);
@ -44,10 +46,24 @@ namespace MetadataUtils.Tests
// Act
using var metadata = WinmdUtils.LoadFromFile(Assembly.GetExecutingAssembly().Location);
var typeInfo = metadata.GetTypes().First(t => t.Name == "IBar") as InterfaceInfo;
var typeInfo = metadata.GetTypes(new List<WinmdUtils> { metadata }).First(t => t.Name == "IBar") as InterfaceInfo;
// Assert
Assert.Equal(2, typeInfo.ImplementedMethodCount);
}
[Fact]
public void GetTypes_InterfaceHeirarchyPresent_InheritFromOtherAssembly()
{
// Arrange
// Act
using var otherMetadata = WinmdUtils.LoadFromFile(typeof(IRegexConstHelper).Assembly.Location);
using var metadata = WinmdUtils.LoadFromFile(Assembly.GetExecutingAssembly().Location);
var typeInfo = metadata.GetTypes(new List<WinmdUtils> { metadata, otherMetadata }).First(t => t.Name == "IInheritsFromOther") as InterfaceInfo;
// Assert
Assert.Equal(typeof(IRegexConstHelper).GetMethods().Length, typeInfo.ImplementedMethodCount);
}
}
}