public override void VisitInvocationExpression(InvocationExpression invocationExpression) { base.VisitInvocationExpression(invocationExpression); // Speed up the inspector by discarding some invocations early var hasEligibleArgument = invocationExpression.Arguments.Any(argument => { var primitiveArg = argument as PrimitiveExpression; return(primitiveArg != null && primitiveArg.Value is string); }); if (!hasEligibleArgument) { return; } var invocationResolveResult = context.Resolve(invocationExpression) as AlInvocationResolveResult; if (invocationResolveResult == null) { return; } Expression formatArgument; IList <Expression> formatArguments; if (!FormatStringHelper.TryGetFormattingParameters(invocationResolveResult, invocationExpression, out formatArgument, out formatArguments, null)) { return; } var primitiveArgument = formatArgument as PrimitiveExpression; if (primitiveArgument == null || !(primitiveArgument.Value is string)) { return; } var format = (string)primitiveArgument.Value; var parsingResult = context.ParseFormatString(format); CheckSegments(parsingResult.Segments, formatArgument.StartLocation, formatArguments, invocationExpression); var argUsed = new HashSet <int> (); foreach (var item in parsingResult.Segments) { var fi = item as FormatItem; if (fi == null) { continue; } argUsed.Add(fi.Index); } for (int i = 0; i < formatArguments.Count; i++) { if (!argUsed.Contains(i)) { AddIssue(new CodeIssue(formatArguments[i], ctx.TranslateString("Argument is not used in format string")) { IssueMarker = IssueMarker.GrayOut }); } } }