mirror of https://github.com/icsharpcode/ILSpy.git
114 lines
3.9 KiB
114 lines
3.9 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.Collections.Immutable; |
|
using System.Reflection; |
|
using System.Reflection.Metadata; |
|
using System.Text; |
|
using System.Text.RegularExpressions; |
|
using ICSharpCode.Decompiler.Metadata; |
|
using ICSharpCode.Decompiler.Util; |
|
|
|
namespace ICSharpCode.Decompiler.IL.Transforms |
|
{ |
|
class LocalFunctionDecompiler : IILTransform |
|
{ |
|
public void Run(ILFunction function, ILTransformContext context) |
|
{ |
|
throw new NotImplementedException(); |
|
} |
|
|
|
public static bool IsLocalFunctionMethod(PEFile module, MethodDefinitionHandle methodHandle) |
|
{ |
|
var metadata = module.Metadata; |
|
var method = metadata.GetMethodDefinition(methodHandle); |
|
var declaringType = method.GetDeclaringType(); |
|
|
|
if ((method.Attributes & MethodAttributes.Assembly) == 0 || !(method.IsCompilerGenerated(metadata) || declaringType.IsCompilerGenerated(metadata))) |
|
return false; |
|
|
|
if (!ParseLocalFunctionName(metadata.GetString(method.Name), out _, out _)) |
|
return false; |
|
|
|
return true; |
|
} |
|
|
|
public static bool IsLocalFunctionDisplayClass(PEFile module, TypeDefinitionHandle typeHandle) |
|
{ |
|
var metadata = module.Metadata; |
|
var type = metadata.GetTypeDefinition(typeHandle); |
|
|
|
if ((type.Attributes & TypeAttributes.NestedPrivate) == 0) |
|
return false; |
|
if (!type.HasGeneratedName(metadata)) |
|
return false; |
|
|
|
var declaringTypeHandle = type.GetDeclaringType(); |
|
var declaringType = metadata.GetTypeDefinition(declaringTypeHandle); |
|
|
|
foreach (var method in declaringType.GetMethods()) { |
|
if (!IsLocalFunctionMethod(module, method)) |
|
continue; |
|
var md = metadata.GetMethodDefinition(method); |
|
if (md.DecodeSignature(new FindTypeDecoder(typeHandle), default).ParameterTypes.Any()) |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
/// <summary> |
|
/// Newer Roslyn versions use the format "<callerName>g__functionName|x_y" |
|
/// Older versions use "<callerName>g__functionNamex_y" |
|
/// </summary> |
|
static readonly Regex functionNameRegex = new Regex(@"^<(.*)>g__(.*)\|{0,1}\d+(_\d+)?$", RegexOptions.Compiled); |
|
|
|
static bool ParseLocalFunctionName(string name, out string callerName, out string functionName) |
|
{ |
|
callerName = null; |
|
functionName = null; |
|
if (string.IsNullOrWhiteSpace(name)) |
|
return false; |
|
var match = functionNameRegex.Match(name); |
|
callerName = match.Groups[1].Value; |
|
functionName = match.Groups[2].Value; |
|
return match.Success; |
|
} |
|
|
|
struct FindTypeDecoder : ISignatureTypeProvider<bool, Unit> |
|
{ |
|
TypeDefinitionHandle handle; |
|
|
|
public FindTypeDecoder(TypeDefinitionHandle handle) |
|
{ |
|
this.handle = handle; |
|
} |
|
|
|
public bool GetArrayType(bool elementType, ArrayShape shape) => elementType; |
|
public bool GetByReferenceType(bool elementType) => elementType; |
|
public bool GetFunctionPointerType(MethodSignature<bool> signature) => false; |
|
public bool GetGenericInstantiation(bool genericType, ImmutableArray<bool> typeArguments) => genericType; |
|
public bool GetGenericMethodParameter(Unit genericContext, int index) => false; |
|
public bool GetGenericTypeParameter(Unit genericContext, int index) => false; |
|
public bool GetModifiedType(bool modifier, bool unmodifiedType, bool isRequired) => unmodifiedType; |
|
public bool GetPinnedType(bool elementType) => elementType; |
|
public bool GetPointerType(bool elementType) => elementType; |
|
public bool GetPrimitiveType(PrimitiveTypeCode typeCode) => false; |
|
public bool GetSZArrayType(bool elementType) => false; |
|
|
|
public bool GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) |
|
{ |
|
return this.handle == handle; |
|
} |
|
|
|
public bool GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) |
|
{ |
|
return false; |
|
} |
|
|
|
public bool GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind) |
|
{ |
|
return reader.GetTypeSpecification(handle).DecodeSignature(this, genericContext); |
|
} |
|
} |
|
} |
|
}
|
|
|