public static bool TryGetFormattingParameters(CSharpInvocationResolveResult invocationResolveResult, InvocationExpression invocationExpression,
		                                     		  out Expression formatArgument, out TextLocation formatStart, out IList<Expression> arguments,
		                                              Func<IParameter, Expression, bool> argumentFilter)
		{
			if (argumentFilter == null)
				argumentFilter = (p, e) => true;

			formatArgument = null;
			formatStart = default(TextLocation);
			arguments = new List<Expression>();
			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 parameter, skip it
					continue;
				}
				var parameter = resolvedParameters[parameterIndex];
				var argument = allArguments[i];
				if (parameter.Type.IsKnownType(KnownTypeCode.String) && parameterNames.Contains(parameter.Name)) {
					formatArgument = argument;
					formatStart = argument.StartLocation;
				} else if ((formatArgument != null || parameter.IsParams) && argumentFilter(parameter, argument)) {
					arguments.Add(argument);
				}
			}
			return formatArgument != null;
		}
		AstNode ToStaticMethodInvocation(InvocationExpression invocation, MemberReferenceExpression memberReference,
		                                 CSharpInvocationResolveResult invocationRR)
		{
			var newArgumentList = invocation.Arguments.Select(arg => arg.Clone()).ToList();
			newArgumentList.Insert(0, memberReference.Target.Clone());
			var newTarget = memberReference.Clone() as MemberReferenceExpression;
			newTarget.Target = new IdentifierExpression(invocationRR.Member.DeclaringType.Name);
			return new InvocationExpression(newTarget, newArgumentList);
		}
			void CheckFormattingCall(InvocationExpression invocationExpression, CSharpInvocationResolveResult invocationResolveResult)
			{
				Expression formatArgument;
				IList<Expression> formatArguments;
				TextLocation formatStart;
				// Only check parameters that are of type object: String means it is neccessary, others
				// means that there is another problem (ie no matching overload of the method).
				Func<IParameter, Expression, bool> predicate = (parameter, argument) => {
					var type = parameter.Type;
					if (type is TypeWithElementType && parameter.IsParams) {
						type = ((TypeWithElementType)type).ElementType;
					}
					var typeDefinition = type.GetDefinition();
					if (typeDefinition == null)
						return false;
					return typeDefinition.IsKnownType(KnownTypeCode.Object);
				};
				if (FormatStringHelper.TryGetFormattingParameters(invocationResolveResult, invocationExpression,
				                                                  out formatArgument, out formatStart, out formatArguments, predicate)) {
					foreach (var argument in formatArguments) {
						CheckExpressionInAutoCallContext(argument);
					}
				}
			}