public override AstNode VisitInvocationExpression(InvocationExpression invocationExpression, ICecilArgumentsResolver argumentsResolver) { MethodReference reference = null; invocationExpression.Arguments.ForEach(a => a.AcceptVisitor(this, argumentsResolver)); invocationExpression.Target.AcceptVisitor(this, argumentsResolver); var specification = invocationExpression.Annotation <MethodSpecification>(); if (specification != null && specification.IsGenericInstance) { var genericMethod = specification as GenericInstanceMethod; var genericArguments = genericMethod.GenericArguments.ToArray(); var parameters = genericMethod.Parameters.Select(p => p.ParameterType); reference = specification.GetElementMethod(); reference = ResolveGenericMethod(parameters, reference, genericArguments, argumentsResolver); invocationExpression.RemoveAnnotations <MethodSpecification>(); invocationExpression.AddAnnotation(reference); } else { reference = invocationExpression.Annotation <MethodReference>(); if (reference != null) { TypeReference returnType = reference.ReturnType; TypeReference declaringType = reference.DeclaringType; if (declaringType.IsGenericInstance || returnType.IsGenericParameter) { if (declaringType.IsGenericInstance) { var genericMethod = declaringType as GenericInstanceType; var parameters = reference.Parameters.Select(p => p.ParameterType); reference = ResolveGenericMethod(parameters, reference, genericMethod.GenericArguments, argumentsResolver); genericMethod.GenericArguments.Clear(); reference.GenericParameters.ForEach(p => genericMethod.GenericArguments.Add(p)); } if (reference.ReturnType.IsGenericParameter) { var genericInstanceType = declaringType as GenericInstanceType; var genericParameter = reference.ReturnType as GenericParameter; var genericReturnType = genericParameter.GetGenericActualType(genericInstanceType.GenericArguments.ToArray()); reference = reference.MakeGenericMethod(new TypeReference[] { }, genericReturnType); } invocationExpression.RemoveAnnotations <MethodReference>(); invocationExpression.AddAnnotation(reference); } } } return(invocationExpression); }
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); } }
public override void VisitInvocationExpression(InvocationExpression invocationExpression) { base.VisitInvocationExpression(invocationExpression); var method = invocationExpression.GetSymbol() as IMethod; if (method == null || !method.IsExtensionMethod || !invocationExpression.Arguments.Any()) { return; } IReadOnlyList <IType> typeArguments; MemberReferenceExpression memberRefExpr; switch (invocationExpression.Target) { case MemberReferenceExpression mre: typeArguments = mre.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance; memberRefExpr = mre; break; case IdentifierExpression ide: typeArguments = ide.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance; memberRefExpr = null; break; default: return; } var firstArgument = invocationExpression.Arguments.First(); if (firstArgument is NamedArgumentExpression) { return; } var target = firstArgument.GetResolveResult(); if (target is ConstantResolveResult crr && crr.ConstantValue == null) { target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion); } ResolveResult[] args = new ResolveResult[invocationExpression.Arguments.Count - 1]; string[] argNames = null; int pos = 0; foreach (var arg in invocationExpression.Arguments.Skip(1)) { if (arg is NamedArgumentExpression nae) { if (argNames == null) { argNames = new string[args.Length]; } argNames[pos] = nae.Name; args[pos] = nae.Expression.GetResolveResult(); } else { args[pos] = arg.GetResolveResult(); } 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); } }
public override void VisitBinaryOperatorExpression (BinaryOperatorExpression binaryOperatorExpression) { base.VisitBinaryOperatorExpression (binaryOperatorExpression); var leftT = GetTypeDef (binaryOperatorExpression.Left); if (leftT != null && !(leftT.IsPrimitive || leftT.FullName=="System.String")) { var name = ""; switch (binaryOperatorExpression.Operator) { case BinaryOperatorType.Add: name = "op_Addition"; break; case BinaryOperatorType.Subtract: name = "op_Subtraction"; break; case BinaryOperatorType.Multiply: name = "op_Multiply"; break; case BinaryOperatorType.Divide: name = "op_Division"; break; case BinaryOperatorType.Equality: name = "op_Equality"; break; case BinaryOperatorType.InEquality: name = "op_Inequality"; break; case BinaryOperatorType.LessThan: name = "op_LessThan"; break; case BinaryOperatorType.LessThanOrEqual: name = "op_LessThanOrEqual"; break; case BinaryOperatorType.GreaterThan: name = "op_GreaterThan"; break; case BinaryOperatorType.GreaterThanOrEqual: name = "op_GreaterThanOrEqual"; break; } var m = FindMethod (leftT, name); if (m != null && m.DeclaringType.FullName != "System.MulticastDelegate") { var left = binaryOperatorExpression.Left; var right = binaryOperatorExpression.Right; left.Remove (); right.Remove (); var n = new InvocationExpression ( new MemberReferenceExpression (new IdentifierExpression (leftT.Name), name), left, right); n.AddAnnotation (m.ReturnType); binaryOperatorExpression.ReplaceWith (n); } } }
public override void VisitInvocationExpression (InvocationExpression invocationExpression) { base.VisitInvocationExpression (invocationExpression); var memberReferenceExpression = invocationExpression.Target as MemberReferenceExpression; if (memberReferenceExpression == null) return; var t = GetTypeRef (memberReferenceExpression.Target); if (t == null) return; HashSet<string> repls = null; string newTypeName = null; if (t.FullName == "System.Object") { repls = objectRepls; newTypeName = "NObject"; } else if (t.FullName == "System.String") { repls = stringRepls; newTypeName = "NString"; } else if (t.FullName == "System.Boolean") { repls = boolRepls; newTypeName = "NBoolean"; } else if (t != null && t.IsPrimitive) { repls = numberRepls; newTypeName = "NNumber"; } if (repls != null && repls.Contains (memberReferenceExpression.MemberName)) { if (memberReferenceExpression.MemberName == "Equals") { var left = memberReferenceExpression.Target; var right = invocationExpression.Arguments.First (); left.Remove (); right.Remove (); invocationExpression.ReplaceWith (new BinaryOperatorExpression (left, BinaryOperatorType.Equality, right)); } else { var newName = memberReferenceExpression.MemberName; if (newTypeName == "NObject") { newName = "Generic" + newName; } var n = new InvocationExpression ( new MemberReferenceExpression ( new TypeReferenceExpression (new SimpleType (newTypeName)), newName), new Expression[] { memberReferenceExpression.Target.Clone () } .Concat (invocationExpression.Arguments.Select (x => x.Clone ()))); var td = t.Resolve (); var meth = td.Methods.First (x => x.Name == memberReferenceExpression.MemberName); n.AddAnnotation (meth.ReturnType); invocationExpression.ReplaceWith (n); } } }