Ejemplo n.º 1
0
    public static ImmutableArray <Diagnostic> GetDiagnostics(
        SyntaxNode node,
        SemanticModel model,
        CancellationToken token)
    {
        var nullableParametersVisitor = new NullableParametersVisitor(model, token);

        nullableParametersVisitor.Visit(node);
        var nullableParameters = nullableParametersVisitor.NullableParameters;

        var existingNullChecksVisitor = new ExistingNullChecksVisitor(model, token);

        existingNullChecksVisitor.Visit(node);
        var existingNullChecks = existingNullChecksVisitor.ExistingNullChecks;

        var builder = ImmutableArray.CreateBuilder <Diagnostic>();

        foreach (var nullableParameter in nullableParameters)
        {
            if (!existingNullChecks.Any(nullCheck => nullCheck.ParameterIndex == nullableParameter.Index))
            {
                var diagnostic = Diagnostic.Create(
                    Descriptor,
                    nullableParameter.Syntax.Identifier.GetLocation(),
                    properties: ImmutableDictionary <string, string?> .Empty.Add(
                        nameof(NullableParameter.Index),
                        nullableParameter.Index.ToString()));
                builder.Add(diagnostic);
            }
        }
        return(builder.ToImmutable());
    }
Ejemplo n.º 2
0
    private Document FixDiagnostics(
        Document document,
        ImmutableArray <Diagnostic> diagnostics,
        SyntaxNode root,
        SemanticModel model,
        SyntaxNode node,
        CancellationToken token)
    {
        var parameterIndexes = new List <int>();

        foreach (var diagnostic in diagnostics)
        {
            if (diagnostic.Properties.TryGetValue(nameof(NullableParameter.Index), out string?index) &&
                int.TryParse(index, out int parameterIndex))
            {
                parameterIndexes.Add(parameterIndex);
            }
        }

        var nullableParametersVisitor = new NullableParametersVisitor(model, token);

        nullableParametersVisitor.Visit(node);
        var nullableParameters = nullableParametersVisitor.NullableParameters
                                 .Where(x => parameterIndexes.Contains(x.Index))
                                 .ToImmutableArray();

        var addNullChecksRewriter = GetRewriter(document, model, nullableParameters, token);
        var newNode     = addNullChecksRewriter.Visit(node);
        var newDocument = document.WithSyntaxRoot(root.ReplaceNode(node, newNode));

        return(newDocument);
    }
Ejemplo n.º 3
0
    public override async Task RegisterCodeFixesAsync(CodeFixContext context)
    {
        var document = context.Document;
        var token    = context.CancellationToken;
        var root     = await document.GetSyntaxRootAsync(token);

        if (root is null)
        {
            return;
        }
        var model = await document.GetSemanticModelAsync(token);

        if (model is null)
        {
            return;
        }

        foreach (var diagnostic in context.Diagnostics)
        {
            if (diagnostic.Id != NullCheckAnalyzer.Id)
            {
                continue;
            }
            var node = root.FindNode(diagnostic.Location.SourceSpan)
                       .Ancestors()
                       .Where(node => node is BaseMethodDeclarationSyntax or LocalFunctionStatementSyntax)
                       .FirstOrDefault();
            if (node is null)
            {
                continue;
            }
            if (!diagnostic.Properties.TryGetValue(nameof(NullableParameter.Index), out string?index) ||
                !int.TryParse(index, out int parameterIndex))
            {
                continue;
            }
            var nullableParametersVisitor = new NullableParametersVisitor(model, token);
            nullableParametersVisitor.Visit(node);
            var nullableParameters = nullableParametersVisitor.NullableParameters;
            var nullableParameter  = nullableParameters.SingleOrDefault(x => x.Index == parameterIndex);
            if (nullableParameter is null)
            {
                continue;
            }
            if (!ShouldRegisterCodeFix(nullableParameter))
            {
                continue;
            }

            // Add null check.
            {
                var codeAction = CodeAction.Create(
                    AddNullCheckTitle,
                    token =>
                {
                    var newDocument = FixDiagnostic(document, nullableParameter, root, model, node, token);
                    return(Task.FromResult(newDocument));
                },
                    equivalenceKey: AddNullCheckTitle);
                context.RegisterCodeFix(codeAction, diagnostic);
            }

            // Add null checks.
            var methodNullCheckDiagnostics = NullCheckAnalyzer.GetDiagnostics(node, model, token);
            if (methodNullCheckDiagnostics.Length > 1)
            {
                var codeAction = CodeAction.Create(
                    AddNullChecksTitle,
                    token =>
                {
                    var newDocument = FixDiagnostics(
                        document,
                        methodNullCheckDiagnostics,
                        root,
                        model,
                        node,
                        token);
                    return(Task.FromResult(newDocument));
                },
                    equivalenceKey: AddNullChecksTitle);
                context.RegisterCodeFix(codeAction, diagnostic);
            }
        }
    }