File: src\Analyzers\CSharp\Analyzers\UseNullPropagation\CSharpUseNullPropagationDiagnosticAnalyzer.cs
Web Access
Project: src\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageService;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.UseNullPropagation;
 
namespace Microsoft.CodeAnalysis.CSharp.UseNullPropagation;
 
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpUseNullPropagationDiagnosticAnalyzer :
    AbstractUseNullPropagationDiagnosticAnalyzer<
        SyntaxKind,
        ExpressionSyntax,
        StatementSyntax,
        ConditionalExpressionSyntax,
        BinaryExpressionSyntax,
        InvocationExpressionSyntax,
        ConditionalAccessExpressionSyntax,
        ElementAccessExpressionSyntax,
        MemberAccessExpressionSyntax,
        IfStatementSyntax,
        ExpressionStatementSyntax>
{
    protected override SyntaxKind IfStatementSyntaxKind
        => SyntaxKind.IfStatement;
 
    protected override bool ShouldAnalyze(Compilation compilation)
        => compilation.LanguageVersion() >= LanguageVersion.CSharp6;
 
    protected override ISemanticFacts SemanticFacts
        => CSharpSemanticFacts.Instance;
 
    protected override bool TryAnalyzePatternCondition(
        ISyntaxFacts syntaxFacts, ExpressionSyntax conditionNode,
        [NotNullWhen(true)] out ExpressionSyntax? conditionPartToCheck, out bool isEquals)
    {
        conditionPartToCheck = null;
        isEquals = true;
 
        if (conditionNode is not IsPatternExpressionSyntax patternExpression)
            return false;
 
        var pattern = patternExpression.Pattern;
        if (pattern is UnaryPatternSyntax(SyntaxKind.NotPattern) notPattern)
        {
            isEquals = false;
            pattern = notPattern.Pattern;
        }
 
        if (pattern is not ConstantPatternSyntax constantPattern)
            return false;
 
        if (!syntaxFacts.IsNullLiteralExpression(constantPattern.Expression))
            return false;
 
        conditionPartToCheck = patternExpression.Expression;
        return true;
    }
 
    protected override bool TryGetPartsOfIfStatement(
        IfStatementSyntax ifStatement,
        [NotNullWhen(true)] out ExpressionSyntax? condition,
        [NotNullWhen(true)] out StatementSyntax? trueStatement)
    {
        // has to be of the form:
        //
        //   if (...)
        //      statement
        //
        // or
        //
        //   if (...)
        //   {
        //       statement
        //   }
 
        condition = ifStatement.Condition;
 
        trueStatement = null;
        if (ifStatement.Else == null)
        {
            if (ifStatement.Statement is BlockSyntax block)
            {
                if (block.Statements.Count == 1)
                    trueStatement = block.Statements[0];
            }
            else
            {
                trueStatement = ifStatement.Statement;
            }
        }
 
        return trueStatement != null;
    }
}