diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
index 806e9a57f..03c37273a 100644
--- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
+++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
@@ -148,6 +148,23 @@ namespace LocalFunctions
}
}
+ private void Name()
+ {
+
+ }
+
+ private void LocalFunctionHidingMethod()
+ {
+ Action action = this.Name;
+ Name();
+ action();
+
+ void Name()
+ {
+
+ }
+ }
+
public void NamedArgument()
{
Use(Get(1), Get(2), Get(3));
diff --git a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs
index 510930f1e..fc50633d5 100644
--- a/ICSharpCode.Decompiler/CSharp/CallBuilder.cs
+++ b/ICSharpCode.Decompiler/CSharp/CallBuilder.cs
@@ -1227,69 +1227,67 @@ namespace ICSharpCode.Decompiler.CSharp
CallOpCode = inst.OpCode
};
ResolveResult result = null;
- string methodName;
+ string methodName = method.Name;
if (method.IsLocalFunction) {
requireTarget = false;
var localFunction = expressionBuilder.ResolveLocalFunction(method);
result = ToMethodGroup(method, localFunction);
target = default;
+ targetType = default;
methodName = localFunction.Name;
- } else {
- methodName = method.Name;
- if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) {
- targetType = method.Parameters[0].Type;
- if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) {
- targetType = ((ByReferenceType)targetType).ElementType;
- thisArg = thisArgBox.Argument;
- }
- target = expressionBuilder.Translate(thisArg, targetType);
- requireTarget = true;
- } else {
- targetType = method.DeclaringType;
- if (targetType.IsReferenceType == false && thisArg is Box thisArgBox) {
- // Normal struct instance method calls (which TranslateTarget is meant for) expect a 'ref T',
- // but delegate construction uses a 'box T'.
- if (thisArgBox.Argument is LdObj ldobj) {
- thisArg = ldobj.Target;
- } else {
- thisArg = new AddressOf(thisArgBox.Argument);
- }
- }
- target = expressionBuilder.TranslateTarget(thisArg,
- nonVirtualInvocation: func.OpCode == OpCode.LdFtn,
- memberStatic: method.IsStatic,
- memberDeclaringType: method.DeclaringType);
- requireTarget = expressionBuilder.HidesVariableWithName(method.Name)
- || (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression));
+ } else if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) {
+ targetType = method.Parameters[0].Type;
+ if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) {
+ targetType = ((ByReferenceType)targetType).ElementType;
+ thisArg = thisArgBox.Argument;
}
- var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectReadOnlyArray(p => new TypeResolveResult(p.Type)));
- if (!requireTarget) {
- result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false);
- if (result is MethodGroupResolveResult mgrr) {
- or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
- requireTarget = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
+ target = expressionBuilder.Translate(thisArg, targetType);
+ requireTarget = true;
+ } else {
+ targetType = method.DeclaringType;
+ if (targetType.IsReferenceType == false && thisArg is Box thisArgBox) {
+ // Normal struct instance method calls (which TranslateTarget is meant for) expect a 'ref T',
+ // but delegate construction uses a 'box T'.
+ if (thisArgBox.Argument is LdObj ldobj) {
+ thisArg = ldobj.Target;
} else {
- requireTarget = true;
+ thisArg = new AddressOf(thisArgBox.Argument);
}
}
- MemberLookup lookup = null;
- bool needsCast = false;
- if (requireTarget) {
- lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule);
- var rr = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
- needsCast = true;
- result = rr;
- if (rr is MethodGroupResolveResult mgrr) {
- or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
- needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
- }
+ target = expressionBuilder.TranslateTarget(thisArg,
+ nonVirtualInvocation: func.OpCode == OpCode.LdFtn,
+ memberStatic: method.IsStatic,
+ memberDeclaringType: method.DeclaringType);
+ requireTarget = expressionBuilder.HidesVariableWithName(method.Name)
+ || (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression));
+ }
+ var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectReadOnlyArray(p => new TypeResolveResult(p.Type)));
+ if (!method.IsLocalFunction && !requireTarget) {
+ result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false);
+ if (result is MethodGroupResolveResult mgrr) {
+ or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
+ requireTarget = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
+ } else {
+ requireTarget = true;
}
- if (needsCast) {
- Debug.Assert(requireTarget);
- target = target.ConvertTo(targetType, expressionBuilder);
- result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
+ }
+ MemberLookup lookup = null;
+ bool needsCast = false;
+ if (requireTarget) {
+ lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule);
+ var rr = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
+ needsCast = true;
+ result = rr;
+ if (rr is MethodGroupResolveResult mgrr) {
+ or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray());
+ needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate));
}
}
+ if (needsCast) {
+ Debug.Assert(requireTarget);
+ target = target.ConvertTo(targetType, expressionBuilder);
+ result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false);
+ }
Expression targetExpression;
if (requireTarget) {
var mre = new MemberReferenceExpression(target, methodName);
diff --git a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs
index 784c6b9e5..2b71dfc82 100644
--- a/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs
+++ b/ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs
@@ -47,11 +47,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
///
public readonly bool IsExpandedForm;
- ///
- /// Gets whether this invocation is calling a local function.
- ///
- public readonly bool IsLocalFunctionInvocation;
-
readonly IReadOnlyList argumentToParameterMap;
public CSharpInvocationResolveResult(
diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
index e3bd8d7fc..3b11cd87f 100644
--- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
+++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
@@ -154,7 +154,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var newResolveResult = new CSharpInvocationResolveResult(
irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors,
isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation,
- irr.IsLocalFunctionInvocation, irr.GetArgumentToParameterMap(), irr.InitializerStatements);
+ irr.GetArgumentToParameterMap(), irr.InitializerStatements);
invocationExpression.AddAnnotation(newResolveResult);
}
}