mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-14 19:29:36 +01:00
This allows us to make it obsolete to *inherit* from a class, and only that. Intended so people stop inheriting UI controls for no good reason. Fixes #5856
76 lines
2.4 KiB
C#
76 lines
2.4 KiB
C#
#nullable enable
|
|
using System.Collections.Immutable;
|
|
using Microsoft.CodeAnalysis;
|
|
using Microsoft.CodeAnalysis.Diagnostics;
|
|
using Robust.Roslyn.Shared;
|
|
|
|
namespace Robust.Analyzers;
|
|
|
|
[DiagnosticAnalyzer(LanguageNames.CSharp)]
|
|
public sealed class ObsoleteInheritanceAnalyzer : DiagnosticAnalyzer
|
|
{
|
|
private const string Attribute = "Robust.Shared.Analyzers.ObsoleteInheritanceAttribute";
|
|
|
|
public static readonly DiagnosticDescriptor Rule = new(
|
|
Diagnostics.IdObsoleteInheritance,
|
|
"Parent type has obsoleted inheritance",
|
|
"Type '{0}' inherits from '{1}', which has obsoleted inheriting from itself",
|
|
"Usage",
|
|
DiagnosticSeverity.Warning,
|
|
true);
|
|
|
|
public static readonly DiagnosticDescriptor RuleWithMessage = new(
|
|
Diagnostics.IdObsoleteInheritanceWithMessage,
|
|
"Parent type has obsoleted inheritance",
|
|
"Type '{0}' inherits from '{1}', which has obsoleted inheriting from itself: \"{2}\"",
|
|
"Usage",
|
|
DiagnosticSeverity.Warning,
|
|
true);
|
|
|
|
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Rule, RuleWithMessage];
|
|
|
|
public override void Initialize(AnalysisContext context)
|
|
{
|
|
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
|
|
context.EnableConcurrentExecution();
|
|
context.RegisterSymbolAction(CheckClass, SymbolKind.NamedType);
|
|
}
|
|
|
|
private static void CheckClass(SymbolAnalysisContext context)
|
|
{
|
|
if (context.Symbol is not INamedTypeSymbol typeSymbol)
|
|
return;
|
|
|
|
if (typeSymbol.IsValueType || typeSymbol.BaseType is not { } baseType)
|
|
return;
|
|
|
|
if (!AttributeHelper.HasAttribute(baseType, Attribute, out var data))
|
|
return;
|
|
|
|
var location = context.Symbol.Locations[0];
|
|
|
|
if (GetMessageFromAttributeData(data) is { } message)
|
|
{
|
|
context.ReportDiagnostic(Diagnostic.Create(
|
|
RuleWithMessage,
|
|
location,
|
|
[typeSymbol.Name, baseType.Name, message]));
|
|
}
|
|
else
|
|
{
|
|
context.ReportDiagnostic(Diagnostic.Create(
|
|
Rule,
|
|
location,
|
|
[typeSymbol.Name, baseType.Name]));
|
|
}
|
|
}
|
|
|
|
private static string? GetMessageFromAttributeData(AttributeData data)
|
|
{
|
|
if (data.ConstructorArguments is not [var message, ..])
|
|
return null;
|
|
|
|
return message.Value as string;
|
|
}
|
|
}
|