Browse Source

Clean up CallBuilder.HandleDelegateConstruction

pull/1586/head
Siegfried Pammer 6 years ago
parent
commit
763ea38644
  1. 17
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/LocalFunctions.cs
  2. 98
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  3. 5
      ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs
  4. 2
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

17
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() public void NamedArgument()
{ {
Use(Get(1), Get(2), Get(3)); Use(Get(1), Get(2), Get(3));

98
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -1227,69 +1227,67 @@ namespace ICSharpCode.Decompiler.CSharp
CallOpCode = inst.OpCode CallOpCode = inst.OpCode
}; };
ResolveResult result = null; ResolveResult result = null;
string methodName; string methodName = method.Name;
if (method.IsLocalFunction) { if (method.IsLocalFunction) {
requireTarget = false; requireTarget = false;
var localFunction = expressionBuilder.ResolveLocalFunction(method); var localFunction = expressionBuilder.ResolveLocalFunction(method);
result = ToMethodGroup(method, localFunction); result = ToMethodGroup(method, localFunction);
target = default; target = default;
targetType = default;
methodName = localFunction.Name; methodName = localFunction.Name;
} else { } else if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) {
methodName = method.Name; targetType = method.Parameters[0].Type;
if (method.IsExtensionMethod && invokeMethod != null && method.Parameters.Count - 1 == invokeMethod.Parameters.Count) { if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) {
targetType = method.Parameters[0].Type; targetType = ((ByReferenceType)targetType).ElementType;
if (targetType.Kind == TypeKind.ByReference && thisArg is Box thisArgBox) { thisArg = thisArgBox.Argument;
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));
} }
var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectReadOnlyArray(p => new TypeResolveResult(p.Type))); target = expressionBuilder.Translate(thisArg, targetType);
if (!requireTarget) { requireTarget = true;
result = resolver.ResolveSimpleName(method.Name, method.TypeArguments, isInvocationTarget: false); } else {
if (result is MethodGroupResolveResult mgrr) { targetType = method.DeclaringType;
or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); if (targetType.IsReferenceType == false && thisArg is Box thisArgBox) {
requireTarget = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate)); // 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 { } else {
requireTarget = true; thisArg = new AddressOf(thisArgBox.Argument);
} }
} }
MemberLookup lookup = null; target = expressionBuilder.TranslateTarget(thisArg,
bool needsCast = false; nonVirtualInvocation: func.OpCode == OpCode.LdFtn,
if (requireTarget) { memberStatic: method.IsStatic,
lookup = new MemberLookup(resolver.CurrentTypeDefinition, resolver.CurrentTypeDefinition.ParentModule); memberDeclaringType: method.DeclaringType);
var rr = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, false); requireTarget = expressionBuilder.HidesVariableWithName(method.Name)
needsCast = true; || (method.IsStatic ? !expressionBuilder.IsCurrentOrContainingType(method.DeclaringTypeDefinition) : !(target.Expression is ThisReferenceExpression));
result = rr; }
if (rr is MethodGroupResolveResult mgrr) { var or = new OverloadResolution(resolver.Compilation, method.Parameters.SelectReadOnlyArray(p => new TypeResolveResult(p.Type)));
or.AddMethodLists(mgrr.MethodsGroupedByDeclaringType.ToArray()); if (!method.IsLocalFunction && !requireTarget) {
needsCast = (or.BestCandidateErrors != OverloadResolutionErrors.None || !IsAppropriateCallTarget(expectedTargetDetails, method, or.BestCandidate)); 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); MemberLookup lookup = null;
target = target.ConvertTo(targetType, expressionBuilder); bool needsCast = false;
result = lookup.Lookup(target.ResolveResult, method.Name, method.TypeArguments, 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; Expression targetExpression;
if (requireTarget) { if (requireTarget) {
var mre = new MemberReferenceExpression(target, methodName); var mre = new MemberReferenceExpression(target, methodName);

5
ICSharpCode.Decompiler/CSharp/Resolver/CSharpInvocationResolveResult.cs

@ -47,11 +47,6 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
/// </summary> /// </summary>
public readonly bool IsExpandedForm; public readonly bool IsExpandedForm;
/// <summary>
/// Gets whether this invocation is calling a local function.
/// </summary>
public readonly bool IsLocalFunctionInvocation;
readonly IReadOnlyList<int> argumentToParameterMap; readonly IReadOnlyList<int> argumentToParameterMap;
public CSharpInvocationResolveResult( public CSharpInvocationResolveResult(

2
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

@ -154,7 +154,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var newResolveResult = new CSharpInvocationResolveResult( var newResolveResult = new CSharpInvocationResolveResult(
irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors, irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors,
isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation, isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation,
irr.IsLocalFunctionInvocation, irr.GetArgumentToParameterMap(), irr.InitializerStatements); irr.GetArgumentToParameterMap(), irr.InitializerStatements);
invocationExpression.AddAnnotation(newResolveResult); invocationExpression.AddAnnotation(newResolveResult);
} }
} }

Loading…
Cancel
Save