| File: Analyzers\ResourceUsageAnalyzer.cs | Web Access |
| Project: src\arcade\src\Microsoft.DotNet.CodeAnalysis\Microsoft.DotNet.CodeAnalysis.csproj (Microsoft.DotNet.CodeAnalysis) |
// 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.Immutable; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Diagnostics; namespace Microsoft.DotNet.CodeAnalysis.Analyzers { [DiagnosticAnalyzer(LanguageNames.CSharp)] public class ResourceUsageAnalyzer : BaseAnalyzer { private const string Title = "Invalid SR.Format call"; private const string Description = "The SR.Format call should be removed."; private const string AnalyzerName = "ResourceUsageAnalyzer"; private static DiagnosticDescriptor InvalidSRFormatCall = new DiagnosticDescriptor(DiagnosticIds.BCL0020.ToString(), Title, "", AnalyzerName, DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description); public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get { return ImmutableArray.Create(InvalidSRFormatCall); } } INamedTypeSymbol SRSymbol { get; set; } public override void OnCompilationStart(CompilationStartAnalysisContext context) { SRSymbol = context.Compilation.GetTypeByMetadataName("System.SR"); if (SRSymbol != null) { context.RegisterSyntaxNodeAction(AnalyzeNode, SyntaxKind.InvocationExpression); } } private void AnalyzeNode(SyntaxNodeAnalysisContext context) { InvocationExpressionSyntax invokeExpr = context.Node as InvocationExpressionSyntax; if (invokeExpr == null) return; MemberAccessExpressionSyntax memberAccessExpr = invokeExpr.Expression as MemberAccessExpressionSyntax; if (memberAccessExpr == null) return; IMethodSymbol memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccessExpr).Symbol as IMethodSymbol; if (memberSymbol == null) return; if (memberSymbol.Name.Equals("Format") && SymbolEqualityComparer.Default.Equals(memberSymbol.ContainingType, SRSymbol) && memberSymbol.Parameters.Length == 1) { // There's no valid reason to call SR.Format(singleArg). This generally happens accidentally // if someone is porting code and ends up with `SR.Format(SR.Something)`, in which case it should // just be simplified to `SR.Something`. context.ReportDiagnostic(Diagnostic.Create(InvalidSRFormatCall, invokeExpr.GetLocation(), invokeExpr.GetText())); } } } }