When finding a type def from a type ref, search all assemblies (#1919)
This commit is contained in:
Родитель
8c02061909
Коммит
19ceee6047
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче