File: CallAnalysis\Throws.cs
Web Access
Project: src\src\Analyzers\Microsoft.Analyzers.Local\Microsoft.Analyzers.Local.csproj (Microsoft.Analyzers.Local)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;
 
namespace Microsoft.Extensions.LocalAnalyzers.CallAnalysis;
 
/// <summary>
/// Recommends using Throw helpers.
/// </summary>
internal sealed class Throws
{
    private static readonly string[] _useThrowsExceptionTypes = new[]
    {
        "System.ArgumentException",
        "System.ArgumentNullException",
        "System.ArgumentOutOfRangeException",
    };
 
    public Throws(CallAnalyzer.Registrar reg)
    {
        reg.RegisterExceptionTypes(_useThrowsExceptionTypes, Handle);
 
        static void Handle(OperationAnalysisContext context, IThrowOperation op)
        {
            var convOp = (IConversionOperation?)op.Exception;
            var creationOp = (IObjectCreationOperation?)convOp?.Operand;
 
            if (creationOp?.Type != null)
            {
                if (op.Syntax.IsKind(SyntaxKind.ThrowStatement))
                {
                    var diagnostic = Diagnostic.Create(
                        DiagDescriptors.ThrowsStatement,
                        op.Syntax.GetLocation(),
                        $"Microsoft.Shared.Diagnostics.Throws.{creationOp.Type.Name}");
 
                    context.ReportDiagnostic(diagnostic);
                }
                else if (op.Syntax.IsKind(SyntaxKind.ThrowExpression))
                {
                    if (creationOp.Type.Name == "ArgumentNullException")
                    {
                        var throwExpression = (ThrowExpressionSyntax)op.Syntax;
                        if (throwExpression.Parent is BinaryExpressionSyntax binaryExpression)
                        {
                            var diagnostic = Diagnostic.Create(
                                DiagDescriptors.ThrowsExpression,
                                binaryExpression.GetLocation(),
                                "Microsoft.Shared.Diagnostics.Throws.IfNull");
 
                            context.ReportDiagnostic(diagnostic);
                        }
                    }
                }
            }
        }
    }
}