IList <Expression> GetRedundantArguments(Expression[] arguments, CSharpInvocationResolveResult invocationResolveResult) { var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); var resolvedParameters = invocationResolveResult.Member.Parameters; IList <Expression> redundantArguments = new List <Expression>(); for (int i = arguments.Length - 1; i >= 0; i--) { var parameterIndex = argumentToParameterMap[i]; if (parameterIndex == -1) { // This particular parameter is an error, but keep trying the other ones continue; } var parameter = resolvedParameters[parameterIndex]; var argument = arguments[i]; if (argument is PrimitiveExpression) { if (parameter.IsParams) { // before positional params arguments all optional arguments are needed, otherwise some of the // param arguments will be shifted out of the params into the fixed parameters break; } if (!parameter.IsOptional) { // There can be no optional parameters preceding a required one break; } var argumentResolveResult = ctx.Resolve(argument) as ConstantResolveResult; if (argumentResolveResult == null || parameter.ConstantValue != argumentResolveResult.ConstantValue) { // Stop here since any arguments before this one has to be there // to enable the passing of this argument break; } redundantArguments.Add(argument); } else if (argument is NamedArgumentExpression) { var expression = ((NamedArgumentExpression)argument).Expression as PrimitiveExpression; if (expression == null) { continue; } var expressionResolveResult = ctx.Resolve(expression) as ConstantResolveResult; if (expressionResolveResult == null || parameter.ConstantValue != expressionResolveResult.ConstantValue) { // continue, since there can still be more arguments that are redundant continue; } redundantArguments.Add(argument); } else { // This is a non-constant positional argument => no more redundancies are possible break; } } return(redundantArguments); }
public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression, out Expression formatArgument, out IList <Expression> arguments, Func <IParameter, Expression, bool> argumentFilter) { if (argumentFilter == null) { argumentFilter = (p, e) => true; } formatArgument = null; arguments = new List <Expression>(); // Serach for method of type: void Name(string format, params object[] args); if (invocationResolveResult.Member.SymbolKind == SymbolKind.Method && invocationResolveResult.Member.DeclaringType != null) { var methods = invocationResolveResult.Member.DeclaringType.GetMethods(m => m.Name == invocationResolveResult.Member.Name).ToList(); if (!methods.Any(m => m.Parameters.Count == 2 && m.Parameters[0].Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(m.Parameters[0].Name) && m.Parameters[1].IsParams)) { return(false); } } var argumentToParameterMap = invocationResolveResult.GetArgumentToParameterMap(); var resolvedParameters = invocationResolveResult.Member.Parameters; var allArguments = invocationExpression.Arguments.ToArray(); for (int i = 0; i < allArguments.Length; i++) { var parameterIndex = argumentToParameterMap[i]; if (parameterIndex < 0 || parameterIndex >= resolvedParameters.Count) { // No valid mapping for this argument, skip it continue; } var parameter = resolvedParameters[parameterIndex]; var argument = allArguments[i]; if (i == 0 && parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name)) { formatArgument = argument; } else if (formatArgument != null && parameter.IsParams && !invocationResolveResult.IsExpandedForm) { var ace = argument as ArrayCreateExpression; if (ace == null || ace.Initializer.IsNull) { return(false); } foreach (var element in ace.Initializer.Elements) { if (argumentFilter(parameter, element)) { arguments.Add(argument); } } } else if (formatArgument != null && argumentFilter(parameter, argument)) { arguments.Add(argument); } } return(formatArgument != null); }