mirror of
https://github.com/RPCS3/discord-bot.git
synced 2024-11-27 12:10:22 +00:00
92751ba6e9
some formatting might be fucked
76 lines
3.3 KiB
C#
76 lines
3.3 KiB
C#
using System.Collections.Immutable;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.Diagnostics;
|
|
|
|
namespace SourceGenerators;
|
|
|
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
|
public class AttributeUsageAnalyzer : DiagnosticAnalyzer
|
|
{
|
|
// You can change these strings in the Resources.resx file. If you do not want your analyzer to be localize-able, you can use regular strings for Title and MessageFormat.
|
|
// See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Localizing%20Analyzers.md for more on localization
|
|
private const string Category = "Usage";
|
|
private const string DiagnosticId = "DSharpPlusAttributeUsage";
|
|
|
|
private static readonly DiagnosticDescriptor AccessCheckAttributeOnGroupCommandRule = new DiagnosticDescriptor(
|
|
DiagnosticId,
|
|
"Access check attributes are ignored",
|
|
"Attribute {0} will be ignored for GroupCommand",
|
|
Category,
|
|
DiagnosticSeverity.Error,
|
|
isEnabledByDefault: true,
|
|
description: "GroupCommand methods will silently ignore any access check attributes, so instead create an instance of the required check attribute and call it explicitly inside the method."
|
|
);
|
|
|
|
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(AccessCheckAttributeOnGroupCommandRule);
|
|
|
|
public override void Initialize(AnalysisContext context)
|
|
{
|
|
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
|
context.EnableConcurrentExecution();
|
|
|
|
// TODO: Consider registering other actions that act on syntax instead of or in addition to symbols
|
|
// See https://github.com/dotnet/roslyn/blob/master/docs/analyzers/Analyzer%20Actions%20Semantics.md for more information
|
|
context.RegisterSymbolAction(AnalyzeSymbol, SymbolKind.Method);
|
|
}
|
|
|
|
private static void AnalyzeSymbol(SymbolAnalysisContext context)
|
|
{
|
|
var methodSymbol = (IMethodSymbol)context.Symbol;
|
|
var methodAttributes = methodSymbol.GetAttributes();
|
|
if (methodAttributes.IsEmpty)
|
|
return;
|
|
|
|
var hasGroupCommand = false;
|
|
foreach (var attr in methodAttributes)
|
|
if (IsDescendantOfAttribute(attr, "DSharpPlus.CommandsNext.Attributes.GroupCommandAttribute"))
|
|
{
|
|
hasGroupCommand = true;
|
|
break;
|
|
}
|
|
|
|
if (!hasGroupCommand)
|
|
return;
|
|
|
|
foreach (var attr in methodAttributes)
|
|
if (IsDescendantOfAttribute(attr, "DSharpPlus.CommandsNext.Attributes.CheckBaseAttribute"))
|
|
{
|
|
var attrLocation = attr.ApplicationSyntaxReference?.SyntaxTree.GetLocation(attr.ApplicationSyntaxReference.Span);
|
|
var diagnostic = Diagnostic.Create(AccessCheckAttributeOnGroupCommandRule, attrLocation ?? methodSymbol.Locations[0], attr.AttributeClass?.Name ?? methodSymbol.Name);
|
|
context.ReportDiagnostic(diagnostic);
|
|
}
|
|
}
|
|
|
|
private static bool IsDescendantOfAttribute(AttributeData attributeData, string baseAttributeClassNameWithNamespace)
|
|
{
|
|
var attrClass = attributeData.AttributeClass;
|
|
do
|
|
{
|
|
if (attrClass.ToDisplayString() == baseAttributeClassNameWithNamespace)
|
|
return true;
|
|
|
|
attrClass = attrClass.BaseType;
|
|
} while (attrClass != null);
|
|
return false;
|
|
}
|
|
} |