|
|
|
@ -106,11 +106,59 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
@@ -106,11 +106,59 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
|
|
|
|
|
public override void VisitInvocationExpression(InvocationExpression invocationExpression) |
|
|
|
|
{ |
|
|
|
|
base.VisitInvocationExpression(invocationExpression); |
|
|
|
|
if (!CanTransformToExtensionMethodCall(resolver, invocationExpression, out var memberRefExpr, |
|
|
|
|
out var target, out var firstArgument)) |
|
|
|
|
{ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
var method = (IMethod)invocationExpression.GetSymbol(); |
|
|
|
|
if (firstArgument is DirectionExpression dirExpr) |
|
|
|
|
{ |
|
|
|
|
if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out) |
|
|
|
|
return; |
|
|
|
|
firstArgument = dirExpr.Expression; |
|
|
|
|
target = firstArgument.GetResolveResult(); |
|
|
|
|
dirExpr.Detach(); |
|
|
|
|
} |
|
|
|
|
else if (firstArgument is NullReferenceExpression) |
|
|
|
|
{ |
|
|
|
|
Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace)); |
|
|
|
|
firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach())); |
|
|
|
|
} |
|
|
|
|
if (invocationExpression.Target is IdentifierExpression identifierExpression) |
|
|
|
|
{ |
|
|
|
|
identifierExpression.Detach(); |
|
|
|
|
memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach()); |
|
|
|
|
invocationExpression.Target = memberRefExpr; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
memberRefExpr.Target = firstArgument.Detach(); |
|
|
|
|
} |
|
|
|
|
if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr) |
|
|
|
|
{ |
|
|
|
|
// do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true
|
|
|
|
|
invocationExpression.RemoveAnnotations<CSharpInvocationResolveResult>(); |
|
|
|
|
var newResolveResult = new CSharpInvocationResolveResult( |
|
|
|
|
irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors, |
|
|
|
|
isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation, |
|
|
|
|
irr.GetArgumentToParameterMap(), irr.InitializerStatements); |
|
|
|
|
invocationExpression.AddAnnotation(newResolveResult); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, |
|
|
|
|
InvocationExpression invocationExpression, out MemberReferenceExpression memberRefExpr, |
|
|
|
|
out ResolveResult target, |
|
|
|
|
out Expression firstArgument) |
|
|
|
|
{ |
|
|
|
|
var method = invocationExpression.GetSymbol() as IMethod; |
|
|
|
|
memberRefExpr = null; |
|
|
|
|
target = null; |
|
|
|
|
firstArgument = null; |
|
|
|
|
if (method == null || !method.IsExtensionMethod || !invocationExpression.Arguments.Any()) |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
IReadOnlyList<IType> typeArguments; |
|
|
|
|
MemberReferenceExpression memberRefExpr; |
|
|
|
|
switch (invocationExpression.Target) |
|
|
|
|
{ |
|
|
|
|
case MemberReferenceExpression mre: |
|
|
|
@ -122,13 +170,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
@@ -122,13 +170,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
|
|
|
|
|
memberRefExpr = null; |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
var firstArgument = invocationExpression.Arguments.First(); |
|
|
|
|
firstArgument = invocationExpression.Arguments.First(); |
|
|
|
|
if (firstArgument is NamedArgumentExpression) |
|
|
|
|
return; |
|
|
|
|
var target = firstArgument.GetResolveResult(); |
|
|
|
|
return false; |
|
|
|
|
target = firstArgument.GetResolveResult(); |
|
|
|
|
if (target is ConstantResolveResult crr && crr.ConstantValue == null) |
|
|
|
|
{ |
|
|
|
|
target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); |
|
|
|
@ -153,41 +201,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
@@ -153,41 +201,14 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
|
|
|
|
|
} |
|
|
|
|
pos++; |
|
|
|
|
} |
|
|
|
|
if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames)) |
|
|
|
|
return; |
|
|
|
|
if (firstArgument is DirectionExpression dirExpr) |
|
|
|
|
{ |
|
|
|
|
if (!context.Settings.RefExtensionMethods || dirExpr.FieldDirection == FieldDirection.Out) |
|
|
|
|
return; |
|
|
|
|
firstArgument = dirExpr.Expression; |
|
|
|
|
target = firstArgument.GetResolveResult(); |
|
|
|
|
dirExpr.Detach(); |
|
|
|
|
} |
|
|
|
|
else if (firstArgument is NullReferenceExpression) |
|
|
|
|
{ |
|
|
|
|
Debug.Assert(context.RequiredNamespacesSuperset.Contains(method.Parameters[0].Type.Namespace)); |
|
|
|
|
firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach())); |
|
|
|
|
} |
|
|
|
|
if (invocationExpression.Target is IdentifierExpression identifierExpression) |
|
|
|
|
{ |
|
|
|
|
identifierExpression.Detach(); |
|
|
|
|
memberRefExpr = new MemberReferenceExpression(firstArgument.Detach(), method.Name, identifierExpression.TypeArguments.Detach()); |
|
|
|
|
invocationExpression.Target = memberRefExpr; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
memberRefExpr.Target = firstArgument.Detach(); |
|
|
|
|
} |
|
|
|
|
if (invocationExpression.GetResolveResult() is CSharpInvocationResolveResult irr) |
|
|
|
|
{ |
|
|
|
|
// do not forget to update the CSharpInvocationResolveResult => set IsExtensionMethodInvocation == true
|
|
|
|
|
invocationExpression.RemoveAnnotations<CSharpInvocationResolveResult>(); |
|
|
|
|
var newResolveResult = new CSharpInvocationResolveResult( |
|
|
|
|
irr.TargetResult, irr.Member, irr.Arguments, irr.OverloadResolutionErrors, |
|
|
|
|
isExtensionMethodInvocation: true, irr.IsExpandedForm, irr.IsDelegateInvocation, |
|
|
|
|
irr.GetArgumentToParameterMap(), irr.InitializerStatements); |
|
|
|
|
invocationExpression.AddAnnotation(newResolveResult); |
|
|
|
|
} |
|
|
|
|
return CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool CanTransformToExtensionMethodCall(CSharpTypeResolveContext resolveContext, |
|
|
|
|
InvocationExpression invocationExpression) |
|
|
|
|
{ |
|
|
|
|
return CanTransformToExtensionMethodCall(new CSharpResolver(resolveContext), |
|
|
|
|
invocationExpression, out _, out _, out _); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public static bool CanTransformToExtensionMethodCall(CSharpResolver resolver, IMethod method, |
|
|
|
|