mirror of https://github.com/icsharpcode/ILSpy.git
7 changed files with 229 additions and 2 deletions
@ -0,0 +1,76 @@
@@ -0,0 +1,76 @@
|
||||
using System; |
||||
using System.Collections.Generic; |
||||
using System.Linq; |
||||
using System.Text; |
||||
using System.Threading.Tasks; |
||||
|
||||
namespace LocalFunctions |
||||
{ |
||||
class LocalFunctions |
||||
{ |
||||
int field; |
||||
|
||||
public static void Main(string[] args) |
||||
{ |
||||
StaticContextNoCapture(10); |
||||
StaticContextSimpleCapture(10); |
||||
StaticContextCaptureInForLoop(10); |
||||
var inst = new LocalFunctions() { field = 10 }; |
||||
inst.ContextNoCapture(); |
||||
inst.ContextSimpleCapture(); |
||||
inst.ContextCaptureInForLoop(); |
||||
} |
||||
|
||||
public static void StaticContextNoCapture(int length) |
||||
{ |
||||
for (int i = 0; i < length; i++) { |
||||
LocalWrite("Hello " + i); |
||||
} |
||||
|
||||
void LocalWrite(string s) => Console.WriteLine(s); |
||||
} |
||||
|
||||
public static void StaticContextSimpleCapture(int length) |
||||
{ |
||||
for (int i = 0; i < length; i++) { |
||||
LocalWrite(); |
||||
} |
||||
|
||||
void LocalWrite() => Console.WriteLine("Hello " + length); |
||||
} |
||||
|
||||
public static void StaticContextCaptureInForLoop(int length) |
||||
{ |
||||
for (int i = 0; i < length; i++) { |
||||
void LocalWrite() => Console.WriteLine("Hello " + i + "/" + length); |
||||
LocalWrite(); |
||||
} |
||||
} |
||||
|
||||
public void ContextNoCapture() |
||||
{ |
||||
for (int i = 0; i < field; i++) { |
||||
LocalWrite("Hello " + i); |
||||
} |
||||
|
||||
void LocalWrite(string s) => Console.WriteLine(s); |
||||
} |
||||
|
||||
public void ContextSimpleCapture() |
||||
{ |
||||
for (int i = 0; i < field; i++) { |
||||
LocalWrite(); |
||||
} |
||||
|
||||
void LocalWrite() => Console.WriteLine("Hello " + field); |
||||
} |
||||
|
||||
public void ContextCaptureInForLoop() |
||||
{ |
||||
for (int i = 0; i < field; i++) { |
||||
void LocalWrite() => Console.WriteLine("Hello " + i + "/" + field); |
||||
LocalWrite(); |
||||
} |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,113 @@
@@ -0,0 +1,113 @@
|
||||
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); |
||||
|
||||
if ((method.Attributes & MethodAttributes.Assembly) == 0 || !method.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); |
||||
} |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue