예제 #1
0
        public override void VisitInvocationExpression(InvocationExpression invocationExpression)
        {
            base.VisitInvocationExpression(invocationExpression);
            var mre    = invocationExpression.Target as MemberReferenceExpression;
            var method = invocationExpression.GetSymbol() as IMethod;

            if (method == null || !method.IsExtensionMethod || mre == null || !(mre.Target is TypeReferenceExpression) || !invocationExpression.Arguments.Any())
            {
                return;
            }
            var firstArgument = invocationExpression.Arguments.First();
            var target        = firstArgument.GetResolveResult();
            var args          = invocationExpression.Arguments.Skip(1).Select(a => a.GetResolveResult()).ToArray();
            var rr            = resolver.ResolveMemberAccess(target, method.Name, method.TypeArguments, NameLookupMode.InvocationTarget) as MethodGroupResolveResult;

            if (rr == null)
            {
                return;
            }
            var or = rr.PerformOverloadResolution(resolveContext.Compilation, args, allowExtensionMethods: true);

            if (or == null || or.IsAmbiguous)
            {
                return;
            }
            if (firstArgument is NullReferenceExpression)
            {
                firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach()));
            }
            else
            {
                mre.Target = firstArgument.Detach();
            }
        }
예제 #2
0
        public override void VisitInvocationExpression(InvocationExpression invocationExpression)
        {
            base.VisitInvocationExpression(invocationExpression);
            var mre    = invocationExpression.Target as MemberReferenceExpression;
            var method = invocationExpression.GetSymbol() as IMethod;

            if (method == null || !method.IsExtensionMethod || mre == null || !(mre.Target is TypeReferenceExpression) || !invocationExpression.Arguments.Any())
            {
                return;
            }
            var typeArguments = mre.TypeArguments.Any() ? method.TypeArguments : EmptyList <IType> .Instance;
            var firstArgument = invocationExpression.Arguments.First();
            var target        = firstArgument.GetResolveResult();
            var args          = invocationExpression.Arguments.Skip(1).Select(a => a.GetResolveResult()).ToArray();

            if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args))
            {
                return;
            }
            if (firstArgument is NullReferenceExpression)
            {
                firstArgument = firstArgument.ReplaceWith(expr => new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.Parameters[0].Type), expr.Detach()));
            }
            else
            {
                mre.Target = firstArgument.Detach();
            }
        }
예제 #3
0
        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();
            var target        = firstArgument.GetResolveResult();

            if (target is ConstantResolveResult crr && crr.ConstantValue == null)
            {
                target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion);
            }
            var args = invocationExpression.Arguments.Skip(1).Select(a => a.GetResolveResult()).ToArray();

            if (!CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args))
            {
                return;
            }
            if (firstArgument is NullReferenceExpression)
            {
                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();
            }
        }
예제 #4
0
        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);
            }
        }
예제 #5
0
        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(false);
            }
            IReadOnlyList <IType> typeArguments;

            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(false);
            }

            firstArgument = invocationExpression.Arguments.First();
            if (firstArgument is NamedArgumentExpression)
            {
                return(false);
            }
            target = firstArgument.GetResolveResult();
            if (target is ConstantResolveResult crr && crr.ConstantValue == null)
            {
                target = new ConversionResolveResult(method.Parameters[0].Type, crr, Conversion.NullLiteralConversion);
            }
        void ProcessInvocationExpression(InvocationExpression invocationExpression)
        {
            var method = invocationExpression.GetSymbol() as IMethod;

            if (method == null)
            {
                return;
            }
            var arguments = invocationExpression.Arguments.ToArray();

            // Reduce "String.Concat(a, b)" to "a + b"
            if (IsStringConcat(method) && CheckArgumentsForStringConcat(arguments))
            {
                bool isInExpressionTree = invocationExpression.Ancestors.OfType <LambdaExpression>().Any(
                    lambda => lambda.Annotation <IL.ILFunction>()?.Kind == IL.ILFunctionKind.ExpressionTree);
                Expression expr = arguments[0].Detach();
                if (!isInExpressionTree)
                {
                    expr = RemoveRedundantToStringInConcat(expr, method, isLastArgument: false).Detach();
                }
                for (int i = 1; i < arguments.Length; i++)
                {
                    var arg = arguments[i].Detach();
                    if (!isInExpressionTree)
                    {
                        arg = RemoveRedundantToStringInConcat(arg, method, isLastArgument: i == arguments.Length - 1).Detach();
                    }
                    expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arg);
                }
                expr.CopyAnnotationsFrom(invocationExpression);
                invocationExpression.ReplaceWith(expr);
                return;
            }

            switch (method.FullName)
            {
            case "System.Type.GetTypeFromHandle":
                if (arguments.Length == 1)
                {
                    if (typeHandleOnTypeOfPattern.IsMatch(arguments[0]))
                    {
                        Expression target = ((MemberReferenceExpression)arguments[0]).Target;
                        target.CopyInstructionsFrom(invocationExpression);
                        invocationExpression.ReplaceWith(target);
                        return;
                    }
                }
                break;

            /*
             * case "System.Reflection.FieldInfo.GetFieldFromHandle":
             * // TODO : This is dead code because LdTokenAnnotation is not added anywhere:
             * if (arguments.Length == 1) {
             *      MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
             *      if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation<LdTokenAnnotation>() != null) {
             *              invocationExpression.ReplaceWith(mre.Target);
             *              return;
             *      }
             * } else if (arguments.Length == 2) {
             *      MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression;
             *      MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression;
             *      if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation<LdTokenAnnotation>() != null) {
             *              if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) {
             *                      Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single();
             *                      FieldReference field = oldArg.Annotation<FieldReference>();
             *                      if (field != null) {
             *                              AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach();
             *                              oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg));
             *                              invocationExpression.ReplaceWith(mre1.Target);
             *                              return;
             *                      }
             *              }
             *      }
             * }
             * break;
             */
            case "System.Activator.CreateInstance":
                if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0]))
                {
                    invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First())));
                }
                break;
            }

            BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(method.Name);

            if (bop != null && arguments.Length == 2)
            {
                invocationExpression.Arguments.Clear();                 // detach arguments from invocationExpression
                invocationExpression.ReplaceWith(
                    new BinaryOperatorExpression(
                        arguments[0].UnwrapInDirectionExpression(),
                        bop.Value,
                        arguments[1].UnwrapInDirectionExpression()
                        ).CopyAnnotationsFrom(invocationExpression)
                    );
                return;
            }
            UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(method.Name);

            if (uop != null && arguments.Length == 1)
            {
                if (uop == UnaryOperatorType.Increment || uop == UnaryOperatorType.Decrement)
                {
                    // `op_Increment(a)` is not equivalent to `++a`,
                    // because it doesn't assign the incremented value to a.
                    if (method.DeclaringType.IsKnownType(KnownTypeCode.Decimal))
                    {
                        // Legacy csc optimizes "d + 1m" to "op_Increment(d)",
                        // so reverse that optimization here:
                        invocationExpression.ReplaceWith(
                            new BinaryOperatorExpression(
                                arguments[0].UnwrapInDirectionExpression().Detach(),
                                (uop == UnaryOperatorType.Increment ? BinaryOperatorType.Add : BinaryOperatorType.Subtract),
                                new PrimitiveExpression(1m)
                                ).CopyAnnotationsFrom(invocationExpression)
                            );
                    }
                    return;
                }
                arguments[0].Remove();                 // detach argument
                invocationExpression.ReplaceWith(
                    new UnaryOperatorExpression(uop.Value, arguments[0].UnwrapInDirectionExpression()).CopyAnnotationsFrom(invocationExpression)
                    );
                return;
            }
            if (method.Name == "op_Explicit" && arguments.Length == 1)
            {
                arguments[0].Remove();                 // detach argument
                invocationExpression.ReplaceWith(
                    new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.ReturnType), arguments[0].UnwrapInDirectionExpression())
                    .CopyAnnotationsFrom(invocationExpression)
                    );
                return;
            }
            if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition)
            {
                invocationExpression.ReplaceWith(arguments[0].UnwrapInDirectionExpression());
                return;
            }

            return;
        }
예제 #7
0
        void ProcessInvocationExpression(InvocationExpression invocationExpression)
        {
            var method = invocationExpression.GetSymbol() as IMethod;

            if (method == null)
            {
                return;
            }
            var arguments = invocationExpression.Arguments.ToArray();

            // Reduce "String.Concat(a, b)" to "a + b"
            if (method.Name == "Concat" && method.DeclaringType.FullName == "System.String" && CheckArgumentsForStringConcat(arguments))
            {
                invocationExpression.Arguments.Clear();                 // detach arguments from invocationExpression
                Expression expr = arguments[0];
                for (int i = 1; i < arguments.Length; i++)
                {
                    expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]);
                }
                invocationExpression.ReplaceWith(expr);
                return;
            }

            switch (method.FullName)
            {
            case "System.Type.GetTypeFromHandle":
                if (arguments.Length == 1)
                {
                    if (typeHandleOnTypeOfPattern.IsMatch(arguments[0]))
                    {
                        Expression target = ((MemberReferenceExpression)arguments[0]).Target;
                        target.CopyInstructionsFrom(invocationExpression);
                        invocationExpression.ReplaceWith(target);
                        return;
                    }
                }
                break;

            case "System.Reflection.FieldInfo.GetFieldFromHandle":
                if (arguments.Length == 1)
                {
                    MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
                    if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation <LdTokenAnnotation>() != null)
                    {
                        invocationExpression.ReplaceWith(mre.Target);
                        return;
                    }
                }
                else if (arguments.Length == 2)
                {
                    MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression;
                    MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression;
                    if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation <LdTokenAnnotation>() != null)
                    {
                        if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression)
                        {
                            Expression     oldArg = ((InvocationExpression)mre1.Target).Arguments.Single();
                            FieldReference field  = oldArg.Annotation <FieldReference>();
                            if (field != null)
                            {
                                AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach();
                                oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg));
                                invocationExpression.ReplaceWith(mre1.Target);
                                return;
                            }
                        }
                    }
                }
                break;

            case "System.Activator.CreateInstance":
                if (method.TypeArguments.Count == 1 && arguments.Length == 0 && method.TypeArguments[0].Kind == TypeKind.TypeParameter)
                {
                    invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First())));
                }
                break;
            }

            BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(method.Name);

            if (bop != null && arguments.Length == 2)
            {
                invocationExpression.Arguments.Clear();                 // detach arguments from invocationExpression
                invocationExpression.ReplaceWith(
                    new BinaryOperatorExpression(arguments[0], bop.Value, arguments[1]).CopyAnnotationsFrom(invocationExpression)
                    );
                return;
            }
            UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(method.Name);

            if (uop != null && arguments.Length == 1)
            {
                arguments[0].Remove();                 // detach argument
                invocationExpression.ReplaceWith(
                    new UnaryOperatorExpression(uop.Value, arguments[0]).CopyAnnotationsFrom(invocationExpression)
                    );
                return;
            }
            if (method.Name == "op_Explicit" && arguments.Length == 1)
            {
                arguments[0].Remove();                 // detach argument
                invocationExpression.ReplaceWith(
                    new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.ReturnType), arguments[0])
                    .CopyAnnotationsFrom(invocationExpression)
                    );
                return;
            }
            if (method.Name == "op_Implicit" && arguments.Length == 1)
            {
                invocationExpression.ReplaceWith(arguments[0]);
                return;
            }
            if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition)
            {
                invocationExpression.ReplaceWith(arguments[0]);
                return;
            }

            return;
        }
예제 #8
0
        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 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();
            }
        }
예제 #9
0
        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);
            }
        }
예제 #10
0
        void ProcessInvocationExpression(InvocationExpression invocationExpression)
        {
            var method = invocationExpression.GetSymbol() as IMethod;

            if (method == null)
            {
                return;
            }
            var arguments = invocationExpression.Arguments.ToArray();

            // Reduce "String.Concat(a, b)" to "a + b"
            if (method.Name == "Concat" && method.DeclaringType.FullName == "System.String" && CheckArgumentsForStringConcat(arguments))
            {
                invocationExpression.Arguments.Clear();                 // detach arguments from invocationExpression
                Expression expr = arguments[0];
                for (int i = 1; i < arguments.Length; i++)
                {
                    expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arguments[i]);
                }
                expr.CopyAnnotationsFrom(invocationExpression);
                invocationExpression.ReplaceWith(expr);
                return;
            }

            switch (method.FullName)
            {
            case "System.Type.GetTypeFromHandle":
                if (arguments.Length == 1)
                {
                    if (typeHandleOnTypeOfPattern.IsMatch(arguments[0]))
                    {
                        Expression target = ((MemberReferenceExpression)arguments[0]).Target;
                        target.CopyInstructionsFrom(invocationExpression);
                        invocationExpression.ReplaceWith(target);
                        return;
                    }
                }
                break;

            case "System.Reflection.FieldInfo.GetFieldFromHandle":
                if (arguments.Length == 1)
                {
                    MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression;
                    if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation <LdTokenAnnotation>() != null)
                    {
                        invocationExpression.ReplaceWith(mre.Target);
                        return;
                    }
                }
                else if (arguments.Length == 2)
                {
                    MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression;
                    MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression;
                    if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation <LdTokenAnnotation>() != null)
                    {
                        if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression)
                        {
                            Expression     oldArg = ((InvocationExpression)mre1.Target).Arguments.Single();
                            FieldReference field  = oldArg.Annotation <FieldReference>();
                            if (field != null)
                            {
                                AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach();
                                oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg));
                                invocationExpression.ReplaceWith(mre1.Target);
                                return;
                            }
                        }
                    }
                }
                break;

            case "System.Activator.CreateInstance":
                if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0]))
                {
                    invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First())));
                }
                break;

            case "System.String.Format":
                if (context.Settings.StringInterpolation && arguments.Length > 1 &&
                    arguments[0] is PrimitiveExpression stringExpression && stringExpression.Value is string &&
                    arguments.Skip(1).All(a => !a.DescendantsAndSelf.OfType <PrimitiveExpression>().Any(p => p.Value is string)))
                {
                    var tokens = new List <(TokenKind, int, string)>();
                    int i      = 0;
                    foreach (var(kind, data) in TokenizeFormatString((string)stringExpression.Value))
                    {
                        int index;
                        switch (kind)
                        {
                        case TokenKind.Error:
                            return;

                        case TokenKind.String:
                            tokens.Add((kind, -1, data));
                            break;

                        case TokenKind.Argument:
                            if (!int.TryParse(data, out index) || index != i)
                            {
                                return;
                            }
                            i++;
                            tokens.Add((kind, index, null));
                            break;

                        case TokenKind.ArgumentWithFormat:
                            string[] arg = data.Split(new[] { ':' }, 2);
                            if (arg.Length != 2 || arg[1].Length == 0)
                            {
                                return;
                            }
                            if (!int.TryParse(arg[0], out index) || index != i)
                            {
                                return;
                            }
                            i++;
                            tokens.Add((kind, index, arg[1]));
                            break;
예제 #11
0
        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(false);
            }
            IReadOnlyList <IType> typeArguments;

            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(false);
            }

            firstArgument = invocationExpression.Arguments.First();
            if (firstArgument is NamedArgumentExpression)
            {
                return(false);
            }
            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++;
            }
            return(CanTransformToExtensionMethodCall(resolver, method, typeArguments, target, args, argNames));
        }