コード例 #1
0
        public override void Initialize(AnalysisContext context)
        {
            context.EnableConcurrentExecution();
            context.RegisterOperationAction(
                ctx =>
            {
                var invoke          = (IInvocationOperation)ctx.Operation;
                bool hasAnyConstant = invoke.Arguments.Any(x => x.Value.ConstantValue.HasValue);
                if (!hasAnyConstant)
                {
                    return;
                }

                if (!FormatStringHelper.TryGetFormattingParameters(invoke, out var formatArgument, out var formatArguments, null, ctx.CancellationToken))
                {
                    return;
                }

                var format        = (string)formatArgument.Value.ConstantValue.Value;
                var parsingResult = new CompositeFormatStringParser().Parse(format);
                CheckSegments(ctx, parsingResult.Segments, formatArgument.Syntax.SpanStart + 1, formatArguments);

                var argUsed = new HashSet <int>();

                foreach (var item in parsingResult.Segments)
                {
                    if (!(item is FormatItem fi))
                    {
                        continue;
                    }
                    argUsed.Add(fi.Index);
                }

                var text = GettextCatalog.GetString("Argument is not used in format string");
                for (int i = 0; i < formatArguments.Count; i++)
                {
                    if (!argUsed.Contains(i))
                    {
                        ctx.ReportDiagnostic(Diagnostic.Create(
                                                 descriptor,
                                                 formatArguments[i].Syntax.GetLocation(),
                                                 text
                                                 ));
                    }
                }
            },
                OperationKind.Invocation
                );
        }
        void AnalyzeInvocation(SyntaxNodeAnalysisContext ctx)
        {
            var invocationExpression = (InvocationExpressionSyntax)ctx.Node;

            // Speed up the inspector by discarding some invocations early
            var hasEligibleArgument = invocationExpression.ArgumentList.Arguments.Any(argument => {
                var primitiveArg = argument.Expression as LiteralExpressionSyntax;
                return(primitiveArg != null && primitiveArg.Token.IsKind(SyntaxKind.StringLiteralToken));
            });

            if (!hasEligibleArgument)
            {
                return;
            }

            var invocationResolveResult = ctx.SemanticModel.GetSymbolInfo(invocationExpression);

            if (invocationResolveResult.Symbol == null)
            {
                return;
            }
            ExpressionSyntax         formatArgument;
            IList <ExpressionSyntax> formatArguments;

            if (!FormatStringHelper.TryGetFormattingParameters(ctx.SemanticModel, invocationExpression,
                                                               out formatArgument, out formatArguments, null, ctx.CancellationToken))
            {
                return;
            }
            var primitiveArgument = formatArgument as LiteralExpressionSyntax;

            if (primitiveArgument == null || !primitiveArgument.Token.IsKind(SyntaxKind.StringLiteralToken))
            {
                return;
            }
            var format        = primitiveArgument.Token.ValueText;
            var parsingResult = new CompositeFormatStringParser().Parse(format);

            CheckSegments(ctx, parsingResult.Segments, formatArgument.SpanStart + 1, 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))
                {
                    ctx.ReportDiagnostic(Diagnostic.Create(
                                             descriptor,
                                             formatArguments[i].GetLocation(),
                                             GettextCatalog.GetString("Argument is not used in format string")
                                             ));
                }
            }
        }