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;
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; }
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": * // 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], 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_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) { invocationExpression.ReplaceWith(arguments[0]); return; } return; }