| File: Microsoft.NetCore.Analyzers\Runtime\DoNotRaiseReservedExceptionTypes.cs | Web Access |
| Project: src\sdk\src\Microsoft.CodeAnalysis.NetAnalyzers\src\Microsoft.CodeAnalysis.NetAnalyzers\Microsoft.CodeAnalysis.NetAnalyzers.csproj (Microsoft.CodeAnalysis.NetAnalyzers) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections.Generic; using System.Collections.Immutable; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis; using Analyzer.Utilities; using Analyzer.Utilities.Extensions; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.NetCore.Analyzers.Runtime { using static MicrosoftNetCoreAnalyzersResources; /// <summary> /// CA2201: <inheritdoc cref="DoNotRaiseReservedExceptionTypesTitle"/> /// /// Too generic: /// System.Exception /// System.ApplicationException /// System.SystemException /// /// Reserved: /// System.OutOfMemoryException /// System.IndexOutOfRangeException /// System.ExecutionEngineException /// System.NullReferenceException /// System.StackOverflowException /// System.Runtime.InteropServices.ExternalException /// System.Runtime.InteropServices.COMException /// System.Runtime.InteropServices.SEHException /// System.AccessViolationException /// /// </summary> [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public sealed class DoNotRaiseReservedExceptionTypesAnalyzer : DiagnosticAnalyzer { internal const string RuleId = "CA2201"; private static readonly ImmutableArray<string> s_tooGenericExceptions = ImmutableArray.Create("System.Exception", "System.ApplicationException", "System.SystemException"); private static readonly ImmutableArray<string> s_reservedExceptions = ImmutableArray.Create("System.OutOfMemoryException", "System.IndexOutOfRangeException", "System.ExecutionEngineException", "System.NullReferenceException", "System.StackOverflowException", "System.Runtime.InteropServices.ExternalException", "System.Runtime.InteropServices.COMException", "System.Runtime.InteropServices.SEHException", "System.AccessViolationException"); private static readonly LocalizableString s_localizableTitle = CreateLocalizableResourceString(nameof(DoNotRaiseReservedExceptionTypesTitle)); private static readonly LocalizableString s_localizableDescription = CreateLocalizableResourceString(nameof(DoNotRaiseReservedExceptionTypesDescription)); internal static readonly DiagnosticDescriptor TooGenericRule = DiagnosticDescriptorHelper.Create( RuleId, s_localizableTitle, CreateLocalizableResourceString(nameof(DoNotRaiseReservedExceptionTypesMessageTooGeneric)), DiagnosticCategory.Usage, RuleLevel.IdeHidden_BulkConfigurable, description: s_localizableDescription, isPortedFxCopRule: true, isDataflowRule: false); internal static readonly DiagnosticDescriptor ReservedRule = DiagnosticDescriptorHelper.Create( RuleId, s_localizableTitle, CreateLocalizableResourceString(nameof(DoNotRaiseReservedExceptionTypesMessageReserved)), DiagnosticCategory.Usage, RuleLevel.IdeHidden_BulkConfigurable, description: s_localizableDescription, isPortedFxCopRule: true, isDataflowRule: false); private static readonly SymbolDisplayFormat s_symbolDisplayFormat = new(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(TooGenericRule, ReservedRule); public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); context.RegisterCompilationStartAction( compilationStartContext => { ImmutableHashSet<INamedTypeSymbol> tooGenericExceptionSymbols = CreateSymbolSet(compilationStartContext.Compilation, s_tooGenericExceptions); ImmutableHashSet<INamedTypeSymbol> reservedExceptionSymbols = CreateSymbolSet(compilationStartContext.Compilation, s_reservedExceptions); if (tooGenericExceptionSymbols.IsEmpty && reservedExceptionSymbols.IsEmpty) { return; } compilationStartContext.RegisterOperationAction( context => AnalyzeObjectCreation(context, tooGenericExceptionSymbols, reservedExceptionSymbols), OperationKind.ObjectCreation); }); } private static ImmutableHashSet<INamedTypeSymbol> CreateSymbolSet(Compilation compilation, IEnumerable<string> exceptionNames) { HashSet<INamedTypeSymbol>? set = null; foreach (string exp in exceptionNames) { INamedTypeSymbol? symbol = compilation.GetOrCreateTypeByMetadataName(exp); if (symbol == null) { continue; } set ??= new HashSet<INamedTypeSymbol>(); set.Add(symbol); } return set != null ? set.ToImmutableHashSet() : ImmutableHashSet<INamedTypeSymbol>.Empty; } private static void AnalyzeObjectCreation( OperationAnalysisContext context, ImmutableHashSet<INamedTypeSymbol> tooGenericExceptionSymbols, ImmutableHashSet<INamedTypeSymbol> reservedExceptionSymbols) { var objectCreation = (IObjectCreationOperation)context.Operation; if (objectCreation.Constructor == null) return; var typeSymbol = objectCreation.Constructor.ContainingType; if (tooGenericExceptionSymbols.Contains(typeSymbol)) { context.ReportDiagnostic(objectCreation.CreateDiagnostic(TooGenericRule, typeSymbol.ToDisplayString(s_symbolDisplayFormat))); } else if (reservedExceptionSymbols.Contains(typeSymbol)) { context.ReportDiagnostic(objectCreation.CreateDiagnostic(ReservedRule, typeSymbol.ToDisplayString(s_symbolDisplayFormat))); } } } }