| File: JSInvokableAnalyzer.cs | Web Access |
| Project: src\aspnetcore\src\Components\Analyzers\src\Microsoft.AspNetCore.Components.Analyzers.csproj (Microsoft.AspNetCore.Components.Analyzers) |
// 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 System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; #nullable enable namespace Microsoft.AspNetCore.Components.Analyzers; [DiagnosticAnalyzer(LanguageNames.CSharp)] public sealed class JSInvokableAnalyzer : DiagnosticAnalyzer { private const string JSInvokableAttributeTypeName = "Microsoft.JSInterop.JSInvokableAttribute"; public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptors.JSInvokableMethodShouldBePublic); public override void Initialize(AnalysisContext context) { context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics); context.RegisterCompilationStartAction(context => { var jsInvokableAttribute = context.Compilation.GetTypeByMetadataName(JSInvokableAttributeTypeName); if (jsInvokableAttribute is null) { // The attribute isn't available return; } context.RegisterSymbolAction(context => { var method = (IMethodSymbol)context.Symbol; var attributes = method.GetAttributes(); if (attributes.Length == 0) { return; } var isJsInvokable = attributes.Any(a => SymbolEqualityComparer.Default.Equals(a.AttributeClass, jsInvokableAttribute)); if (!isJsInvokable) { return; } var methodLocation = method.Locations.FirstOrDefault(); if (methodLocation == null) { return; } if (method.DeclaredAccessibility != Accessibility.Public) { context.ReportDiagnostic(Diagnostic.Create( DiagnosticDescriptors.JSInvokableMethodShouldBePublic, methodLocation, method.ToDisplayString(SymbolDisplayFormat.CSharpErrorMessageFormat))); } }, SymbolKind.Method); }); } }