Browse Source

Possible fix for primitive types resolving to MinimalCorlib types in navigateTo handling.

pull/1324/head
Siegfried Pammer 7 years ago
parent
commit
188bac4e55
  1. 48
      ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs
  2. 9
      ICSharpCode.Decompiler/SRMExtensions.cs
  3. 60
      ILSpy/MainWindow.xaml.cs

48
ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs

@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
using System;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
@ -30,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation @@ -30,7 +32,7 @@ namespace ICSharpCode.Decompiler.Documentation
/// The type parameter count only applies to the innermost type, all outer types must be non-generic.
/// </summary>
[Serializable]
class GetPotentiallyNestedClassTypeReference : ITypeReference
public class GetPotentiallyNestedClassTypeReference : ITypeReference
{
readonly string typeName;
readonly int typeParameterCount;
@ -67,5 +69,49 @@ namespace ICSharpCode.Decompiler.Documentation @@ -67,5 +69,49 @@ namespace ICSharpCode.Decompiler.Documentation
// give back a guessed namespace/type name
return new UnknownType(typeName.Substring(0, idx), typeName.Substring(idx + 1), typeParameterCount);
}
/// <summary>
/// Resolves the type reference within the context of the given PE file.
/// </summary>
/// <returns>Either TypeDefinitionHandle, if the type is defined in the module or ExportedTypeHandle,
/// if the module contains a type forwarder. Returns a nil handle, if the type was not found.</returns>
public EntityHandle ResolveInPEFile(PEFile module)
{
string[] parts = typeName.Split('.');
for (int i = parts.Length - 1; i >= 0; i--) {
string ns = string.Join(".", parts, 0, i);
string name = parts[i];
int topLevelTPC = (i == parts.Length - 1 ? typeParameterCount : 0);
var topLevelName = new TopLevelTypeName(ns, name, topLevelTPC);
var typeHandle = module.GetTypeDefinition(topLevelName);
for (int j = i + 1; j < parts.Length && !typeHandle.IsNil; j++) {
int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
var typeDef = module.Metadata.GetTypeDefinition(typeHandle);
string lookupName = parts[j] + (tpc > 0 ? "`" + tpc : "");
typeHandle = typeDef.GetNestedTypes().FirstOrDefault(n => IsEqualShortName(n, module.Metadata, lookupName));
}
if (!typeHandle.IsNil)
return typeHandle;
FullTypeName typeName = topLevelName;
for (int j = i + 1; j < parts.Length; j++) {
int tpc = (j == parts.Length - 1 ? typeParameterCount : 0);
typeName = typeName.NestedType(parts[j], tpc);
}
var exportedType = module.GetTypeForwarder(typeName);
if (!exportedType.IsNil)
return exportedType;
}
return default;
bool IsEqualShortName(TypeDefinitionHandle h, MetadataReader metadata, string name)
{
var nestedType = metadata.GetTypeDefinition(h);
return metadata.StringComparer.Equals(nestedType.Name, name);
}
}
}
}

9
ICSharpCode.Decompiler/SRMExtensions.cs

@ -241,9 +241,14 @@ namespace ICSharpCode.Decompiler @@ -241,9 +241,14 @@ namespace ICSharpCode.Decompiler
public static FullTypeName GetFullTypeName(this ExportedType type, MetadataReader metadata)
{
string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace);
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(metadata.GetString(type.Name), out int typeParameterCount);
return new TopLevelTypeName(ns, name, typeParameterCount);
if (type.Implementation.Kind == HandleKind.ExportedType) {
var outerType = metadata.GetExportedType((ExportedTypeHandle)type.Implementation);
return outerType.GetFullTypeName(metadata).NestedType(name, typeParameterCount);
} else {
string ns = type.Namespace.IsNil ? "" : metadata.GetString(type.Namespace);
return new TopLevelTypeName(ns, name, typeParameterCount);
}
}
public static bool IsAnonymousType(this TypeDefinition type, MetadataReader metadata)

60
ILSpy/MainWindow.xaml.cs

@ -23,6 +23,7 @@ using System.ComponentModel; @@ -23,6 +23,7 @@ using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
@ -287,15 +288,36 @@ namespace ICSharpCode.ILSpy @@ -287,15 +288,36 @@ namespace ICSharpCode.ILSpy
}
}
} else {
ITypeReference typeRef = null;
IMemberReference memberRef = null;
if (args.NavigateTo.StartsWith("T:", StringComparison.Ordinal)) {
typeRef = IdStringProvider.ParseTypeName(args.NavigateTo);
} else {
memberRef = IdStringProvider.ParseMemberIdString(args.NavigateTo);
typeRef = memberRef.DeclaringTypeReference;
}
foreach (LoadedAssembly asm in commandLineLoadedAssemblies) {
var def = asm.GetPEFileOrNull();
if (def != null) {
var compilation = new SimpleCompilation(def, MinimalCorlib.Instance);
var mr = IdStringProvider.FindEntity(args.NavigateTo, new SimpleTypeResolveContext(compilation));
if (mr != null) {
var module = asm.GetPEFileOrNull();
if (CanResolveTypeInPEFile(module, typeRef, out var typeHandle)) {
IEntity mr = null;
if (typeHandle.Kind == HandleKind.ExportedType) {
var decompilerTypeSystem = new DecompilerTypeSystem(module, module.GetAssemblyResolver());
if (memberRef == null) {
mr = typeRef.Resolve(new SimpleTypeResolveContext(decompilerTypeSystem)) as ITypeDefinition;
} else {
mr = memberRef.Resolve(new SimpleTypeResolveContext(decompilerTypeSystem));
}
} else {
var compilation = new SimpleCompilation(module, MinimalCorlib.Instance);
if (memberRef == null) {
mr = ((MetadataModule)compilation.MainModule).GetDefinition((TypeDefinitionHandle)typeHandle);
} else {
mr = memberRef.Resolve(new SimpleTypeResolveContext(compilation));
}
}
if (mr != null && mr.ParentModule.PEFile != null) {
found = true;
// Defer JumpToReference call to allow an assembly that was loaded while
// resolving a type-forwarder in FindMemberByKey to appear in the assembly list.
Dispatcher.BeginInvoke(new Action(() => JumpToReference(mr)), DispatcherPriority.Loaded);
break;
}
@ -320,6 +342,30 @@ namespace ICSharpCode.ILSpy @@ -320,6 +342,30 @@ namespace ICSharpCode.ILSpy
commandLineLoadedAssemblies.Clear(); // clear references once we don't need them anymore
}
private bool CanResolveTypeInPEFile(PEFile module, ITypeReference typeRef, out EntityHandle typeHandle)
{
switch (typeRef) {
case GetPotentiallyNestedClassTypeReference topLevelType:
typeHandle = topLevelType.ResolveInPEFile(module);
return !typeHandle.IsNil;
case NestedTypeReference nestedType:
if (!CanResolveTypeInPEFile(module, nestedType.DeclaringTypeReference, out typeHandle))
return false;
if (typeHandle.Kind == HandleKind.ExportedType)
return true;
var typeDef = module.Metadata.GetTypeDefinition((TypeDefinitionHandle)typeHandle);
typeHandle = typeDef.GetNestedTypes().FirstOrDefault(t => {
var td = module.Metadata.GetTypeDefinition(t);
var typeName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(module.Metadata.GetString(td.Name), out int typeParameterCount);
return nestedType.AdditionalTypeParameterCount == typeParameterCount && nestedType.Name == typeName;
});
return !typeHandle.IsNil;
default:
typeHandle = default;
return false;
}
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
ILSpySettings spySettings = this.spySettings;

Loading…
Cancel
Save