Browse Source

Merge pull request #1324 from icsharpcode/navigateTo-Fix

Possible fix for primitive types resolving to MinimalCorlib types in …
pull/1347/head
Siegfried Pammer 7 years ago
committed by GitHub
parent
commit
11ec0e22e6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 48
      ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs
  2. 9
      ICSharpCode.Decompiler/SRMExtensions.cs
  3. 48
      ILSpy/MainWindow.xaml.cs

48
ICSharpCode.Decompiler/Documentation/GetPotentiallyNestedClassTypeReference.cs

@ -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
/// 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
// 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
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)

48
ILSpy/MainWindow.xaml.cs

@ -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,12 +288,25 @@ 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;
ICompilation compilation = typeHandle.Kind == HandleKind.ExportedType
? new DecompilerTypeSystem(module, module.GetAssemblyResolver())
: new SimpleCompilation(module, MinimalCorlib.Instance);
mr = memberRef == null
? typeRef.Resolve(new SimpleTypeResolveContext(compilation)) as ITypeDefinition
: (IEntity)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.
@ -320,6 +334,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