From e0137647f01f4b093053d7adc08300af28009e3c Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 27 Apr 2026 15:59:56 +0200
Subject: [PATCH 01/10] SourceGeneration
---
.../AnalyzerReleases.Shipped.md | 3 +
.../AnalyzerReleases.Unshipped.md | 7 +
.../Builders/Builder.cs | 19 +++
.../Builders/ClassBuilder.cs | 60 +++++++
.../Builders/MethodBuilder.cs | 44 +++++
SecretAPI.SourceGenerators/Diagnostics.cs | 28 ++++
.../Generators/CallOnLoadGenerator.cs | 152 ++++++++++++++++++
SecretAPI.SourceGenerators/GlobalUsings.cs | 19 +++
.../SecretAPI.SourceGenerators.csproj | 26 +++
.../Utils/GeneratedIdentifyUtils.cs | 19 +++
.../Utils/GenericTypeUtils.cs | 12 ++
.../Utils/MethodParameter.cs | 40 +++++
.../Utils/MethodUtils.cs | 20 +++
SecretAPI.SourceGenerators/Utils/TypeUtils.cs | 10 ++
SecretAPI.sln | 6 +
SecretAPI/SecretAPI.csproj | 2 +
SecretAPI/SecretApi.cs | 2 +-
17 files changed, 468 insertions(+), 1 deletion(-)
create mode 100644 SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md
create mode 100644 SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
create mode 100644 SecretAPI.SourceGenerators/Builders/Builder.cs
create mode 100644 SecretAPI.SourceGenerators/Builders/ClassBuilder.cs
create mode 100644 SecretAPI.SourceGenerators/Builders/MethodBuilder.cs
create mode 100644 SecretAPI.SourceGenerators/Diagnostics.cs
create mode 100644 SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
create mode 100644 SecretAPI.SourceGenerators/GlobalUsings.cs
create mode 100644 SecretAPI.SourceGenerators/SecretAPI.SourceGenerators.csproj
create mode 100644 SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
create mode 100644 SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs
create mode 100644 SecretAPI.SourceGenerators/Utils/MethodParameter.cs
create mode 100644 SecretAPI.SourceGenerators/Utils/MethodUtils.cs
create mode 100644 SecretAPI.SourceGenerators/Utils/TypeUtils.cs
diff --git a/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md b/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md
new file mode 100644
index 0000000..60b59dd
--- /dev/null
+++ b/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md
@@ -0,0 +1,3 @@
+; Shipped analyzer releases
+; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
+
diff --git a/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md b/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
new file mode 100644
index 0000000..ad9f9dc
--- /dev/null
+++ b/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
@@ -0,0 +1,7 @@
+### New Rules
+
+ Rule ID | Category | Severity | Notes
+------------|----------|----------|---------------------
+ SecretGen0 | Usage | Error | CA6000_AnalyzerName
+ SecretGen1 | Usage | Error | CA6000_AnalyzerName
+ SecretGen2 | Usage | Error | CA6000_AnalyzerName
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Builders/Builder.cs b/SecretAPI.SourceGenerators/Builders/Builder.cs
new file mode 100644
index 0000000..4cc8b63
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Builders/Builder.cs
@@ -0,0 +1,19 @@
+namespace SecretAPI.SourceGenerators.Builders;
+
+///
+/// Base of a builder.
+///
+/// The this is handling.
+internal abstract class Builder
+ where TBuilder : Builder
+{
+ protected readonly List _modifiers = new();
+
+ internal TBuilder AddModifiers(params SyntaxKind[] modifiers)
+ {
+ foreach (SyntaxKind token in modifiers)
+ _modifiers.Add(Token(token));
+
+ return (TBuilder)this;
+ }
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs b/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs
new file mode 100644
index 0000000..671cf80
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs
@@ -0,0 +1,60 @@
+namespace SecretAPI.SourceGenerators.Builders;
+
+internal class ClassBuilder : Builder
+{
+ private NamespaceDeclarationSyntax _namespaceDeclaration;
+ private ClassDeclarationSyntax _classDeclaration;
+
+ private readonly List _usings = new();
+ private readonly List _methods = new();
+
+ private ClassBuilder(NamespaceDeclarationSyntax namespaceDeclaration, ClassDeclarationSyntax classDeclaration)
+ {
+ _namespaceDeclaration = namespaceDeclaration;
+ _classDeclaration = classDeclaration;
+
+ AddUsingStatements("System.CodeDom.Compiler");
+ }
+
+ internal static ClassBuilder CreateBuilder(INamedTypeSymbol namedClass)
+ => CreateBuilder(NamespaceDeclaration(ParseName(namedClass.ContainingNamespace.ToDisplayString())), ClassDeclaration(namedClass.Name));
+
+ internal static ClassBuilder CreateBuilder(NamespaceDeclarationSyntax namespaceDeclaration, ClassDeclarationSyntax classDeclaration)
+ => new(namespaceDeclaration, classDeclaration);
+
+ internal ClassBuilder AddUsingStatements(params string[] usingStatements)
+ {
+ foreach (string statement in usingStatements)
+ {
+ UsingDirectiveSyntax usings = UsingDirective(ParseName(statement));
+ if (!_usings.Any(existing => existing.IsEquivalentTo(usings)))
+ _usings.Add(usings);
+ }
+
+ return this;
+ }
+
+ internal MethodBuilder StartMethodCreation(string methodName, TypeSyntax returnType) => new(this, methodName, returnType);
+ internal MethodBuilder StartMethodCreation(string methodName, SyntaxKind returnType) => StartMethodCreation(methodName, GetPredefinedTypeSyntax(returnType));
+
+ internal void AddMethodDefinition(MethodDeclarationSyntax method) => _methods.Add(method);
+
+ internal CompilationUnitSyntax Build()
+ {
+ _classDeclaration = _classDeclaration
+ .AddAttributeLists(GetGeneratedCodeAttributeListSyntax())
+ .AddModifiers(_modifiers.ToArray())
+ .AddMembers(_methods.Cast().ToArray());
+
+ _namespaceDeclaration = _namespaceDeclaration
+ .AddUsings(_usings.ToArray())
+ .AddMembers(_classDeclaration);
+
+ return CompilationUnit()
+ .AddMembers(_namespaceDeclaration)
+ .NormalizeWhitespace()
+ .WithLeadingTrivia(Comment("// "), LineFeed, Comment("#pragma warning disable"), LineFeed, Comment("#nullable enable"), LineFeed, LineFeed);
+ }
+
+ internal void Build(SourceProductionContext context, string name) => context.AddSource(name, Build().ToFullString());
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Builders/MethodBuilder.cs b/SecretAPI.SourceGenerators/Builders/MethodBuilder.cs
new file mode 100644
index 0000000..6538e4a
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Builders/MethodBuilder.cs
@@ -0,0 +1,44 @@
+namespace SecretAPI.SourceGenerators.Builders;
+
+internal class MethodBuilder : Builder
+{
+ private readonly ClassBuilder _classBuilder;
+ private readonly List _parameters = new();
+ private readonly List _statements = new();
+ private readonly string _methodName;
+ private readonly TypeSyntax _returnType;
+
+ internal MethodBuilder(ClassBuilder classBuilder, string methodName, TypeSyntax returnType)
+ {
+ _classBuilder = classBuilder;
+ _methodName = methodName;
+ _returnType = returnType;
+ }
+
+ internal MethodBuilder AddStatements(params StatementSyntax[] statements)
+ {
+ _statements.AddRange(statements);
+ return this;
+ }
+
+ internal MethodBuilder AddParameters(params MethodParameter[] parameters)
+ {
+ foreach (MethodParameter parameter in parameters)
+ _parameters.Add(parameter.Syntax);
+
+ return this;
+ }
+
+ internal ClassBuilder FinishMethodBuild()
+ {
+ BlockSyntax body = _statements.Any() ? Block(_statements) : Block();
+
+ MethodDeclarationSyntax methodDeclaration = MethodDeclaration(_returnType, _methodName)
+ .AddModifiers(_modifiers.ToArray())
+ .AddParameterListParameters(_parameters.ToArray())
+ .WithBody(body);
+
+ _classBuilder.AddMethodDefinition(methodDeclaration);
+ return _classBuilder;
+ }
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Diagnostics.cs b/SecretAPI.SourceGenerators/Diagnostics.cs
new file mode 100644
index 0000000..8b3e2b4
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Diagnostics.cs
@@ -0,0 +1,28 @@
+namespace SecretAPI.SourceGenerators;
+
+internal static class Diagnostics
+{
+ internal static readonly DiagnosticDescriptor MustBePartialPluginClass = new(
+ "SecretGen0",
+ "Plugin class must be partial",
+ "Plugin class '{0}' is missing partial modifier",
+ "Usage",
+ DiagnosticSeverity.Error,
+ true);
+
+ internal static readonly DiagnosticDescriptor MustBeAccessibleMethod = new(
+ "SecretGen1",
+ "Method must be accessible",
+ "Method '{0}' has accessibility '{1}', which is not supported for generated calls",
+ "Usage",
+ DiagnosticSeverity.Error,
+ true);
+
+ internal static readonly DiagnosticDescriptor MustBeStaticMethod = new(
+ "SecretGen2",
+ "Method must be static",
+ "Method '{0}' is not marked as static",
+ "Usage",
+ DiagnosticSeverity.Error,
+ true);
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs b/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
new file mode 100644
index 0000000..7147eb0
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
@@ -0,0 +1,152 @@
+namespace SecretAPI.SourceGenerators.Generators;
+
+///
+/// Code generator for CallOnLoad/CallOnUnload
+///
+[Generator]
+public class CallOnLoadGenerator : IIncrementalGenerator
+{
+ private const string PluginNamespace = "LabApi.Loader.Features.Plugins";
+ private const string PluginBaseClassName = "Plugin";
+ private const string CallOnLoadAttributeLocation = "SecretAPI.Attributes.CallOnLoadAttribute";
+ private const string CallOnUnloadAttributeLocation = "SecretAPI.Attributes.CallOnUnloadAttribute";
+
+ ///
+ public void Initialize(IncrementalGeneratorInitializationContext context)
+ {
+ IncrementalValuesProvider methodProvider =
+ context.SyntaxProvider.CreateSyntaxProvider(
+ static (node, _) => node is MethodDeclarationSyntax { AttributeLists.Count: > 0 },
+ static (ctx, _) =>
+ ctx.SemanticModel.GetDeclaredSymbol(ctx.Node) as IMethodSymbol)
+ .Where(static m => m is not null)!;
+
+ IncrementalValuesProvider<(IMethodSymbol method, bool isLoad, bool isUnload)> callProvider =
+ methodProvider.Select(static (method, _) => (
+ method,
+ HasAttribute(method, CallOnLoadAttributeLocation),
+ HasAttribute(method, CallOnUnloadAttributeLocation)))
+ .Where(static m => m.Item2 || m.Item3);
+
+ IncrementalValuesProvider<(ClassDeclarationSyntax?, INamedTypeSymbol?)> pluginClassProvider =
+ context.SyntaxProvider.CreateSyntaxProvider(
+ static (node, _) => node is ClassDeclarationSyntax,
+ static (ctx, _) => (
+ ctx.Node as ClassDeclarationSyntax, ctx.SemanticModel.GetDeclaredSymbol(ctx.Node) as INamedTypeSymbol))
+ .Where(static c => c.Item2 != null && !c.Item2.IsAbstract && c.Item2.BaseType?.Name == PluginBaseClassName &&
+ c.Item2.BaseType.ContainingNamespace.ToDisplayString() == PluginNamespace);
+
+ context.RegisterSourceOutput(pluginClassProvider.Combine(callProvider.Collect()), static (context, data) =>
+ {
+ Generate(context, new Tuple(data.Left.Item1, data.Left.Item2), data.Right);
+ });
+ }
+
+ private static bool HasAttribute(IMethodSymbol? method, string attributeLocation)
+ {
+ if (method == null)
+ return false;
+
+ foreach (AttributeData attribute in method.GetAttributes())
+ {
+ if (attribute.AttributeClass?.ToDisplayString() == attributeLocation)
+ return true;
+ }
+
+ return false;
+ }
+
+ private static int GetPriority(IMethodSymbol method, string attributeLocation)
+ {
+ AttributeData? attribute = method.GetAttributes()
+ .FirstOrDefault(a => a.AttributeClass?.ToDisplayString() == attributeLocation);
+ if (attribute == null)
+ return 0;
+
+ if (attribute.ConstructorArguments.Length > 0)
+ return (int)attribute.ConstructorArguments[0].Value!;
+
+ return 0;
+ }
+
+ private static bool ValidateMethod(SourceProductionContext context, Tuple pluginInfo, IMethodSymbol method)
+ {
+ bool isValid = true;
+
+ if (!method.IsStatic)
+ {
+ context.ReportDiagnostic(
+ Diagnostic.Create(
+ Diagnostics.MustBeStaticMethod,
+ method.Locations.FirstOrDefault(),
+ method.Name));
+
+ isValid = false;
+ }
+
+ if (method.DeclaredAccessibility is Accessibility.Private)
+ {
+ context.ReportDiagnostic(
+ Diagnostic.Create(
+ Diagnostics.MustBeAccessibleMethod,
+ method.Locations.FirstOrDefault(),
+ method.Name,
+ method.DeclaredAccessibility));
+
+ isValid = false;
+ }
+
+ return isValid;
+ }
+
+ private static void Generate(
+ SourceProductionContext context,
+ Tuple pluginInfo,
+ ImmutableArray<(IMethodSymbol method, bool isLoad, bool isUnload)> methods)
+ {
+ if (pluginInfo.Item1 == null || pluginInfo.Item2 == null || methods.IsEmpty)
+ return;
+
+ if (!pluginInfo.Item1.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
+ {
+ context.ReportDiagnostic(
+ Diagnostic.Create(
+ Diagnostics.MustBePartialPluginClass,
+ pluginInfo.Item1.GetLocation(),
+ pluginInfo.Item1.Identifier.Text
+ )
+ );
+ }
+
+ IMethodSymbol[] loadCalls = methods
+ .Where(m => m.isLoad && ValidateMethod(context, pluginInfo, m.method))
+ .Select(m => m.method)
+ .OrderBy(m => GetPriority(m, CallOnLoadAttributeLocation))
+ .ToArray();
+
+ IMethodSymbol[] unloadCalls = methods
+ .Where(m => m.isUnload && ValidateMethod(context, pluginInfo, m.method))
+ .Select(m => m.method)
+ .OrderBy(m => GetPriority(m, CallOnUnloadAttributeLocation))
+ .ToArray();
+
+ if (!loadCalls.Any() && !unloadCalls.Any())
+ return;
+
+ ClassBuilder classBuilder = ClassBuilder.CreateBuilder(pluginInfo.Item2)
+ .AddUsingStatements("System")
+ .AddModifiers(SyntaxKind.PartialKeyword);
+
+ classBuilder.StartMethodCreation("OnLoad", SyntaxKind.VoidKeyword)
+ .AddModifiers(SyntaxKind.PublicKeyword)
+ .AddStatements(MethodCallStatements(loadCalls))
+ .FinishMethodBuild();
+
+ classBuilder.StartMethodCreation("OnUnload", SyntaxKind.VoidKeyword)
+ .AddModifiers(SyntaxKind.PublicKeyword)
+ .AddStatements(MethodCallStatements(unloadCalls))
+ .FinishMethodBuild();
+
+ classBuilder.Build(context, $"{pluginInfo.Item2.Name}.g.cs");
+ }
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/GlobalUsings.cs b/SecretAPI.SourceGenerators/GlobalUsings.cs
new file mode 100644
index 0000000..eb69204
--- /dev/null
+++ b/SecretAPI.SourceGenerators/GlobalUsings.cs
@@ -0,0 +1,19 @@
+//? Utils from other places
+global using Microsoft.CodeAnalysis;
+global using Microsoft.CodeAnalysis.CSharp;
+global using Microsoft.CodeAnalysis.CSharp.Syntax;
+global using System.Collections.Immutable;
+
+//? Static utils from other places
+global using static Microsoft.CodeAnalysis.CSharp.SyntaxFactory;
+global using static Microsoft.CodeAnalysis.CSharp.SyntaxFacts;
+
+//? Utils from SecretAPI
+global using SecretAPI.SourceGenerators.Builders;
+global using SecretAPI.SourceGenerators.Utils;
+
+//? Static utils from SecretAPI
+global using static SecretAPI.SourceGenerators.Utils.GenericTypeUtils;
+global using static SecretAPI.SourceGenerators.Utils.GeneratedIdentifyUtils;
+global using static SecretAPI.SourceGenerators.Utils.MethodUtils;
+global using static SecretAPI.SourceGenerators.Utils.TypeUtils;
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/SecretAPI.SourceGenerators.csproj b/SecretAPI.SourceGenerators/SecretAPI.SourceGenerators.csproj
new file mode 100644
index 0000000..b6bd4b5
--- /dev/null
+++ b/SecretAPI.SourceGenerators/SecretAPI.SourceGenerators.csproj
@@ -0,0 +1,26 @@
+
+
+
+ netstandard2.0
+ 14
+ true
+ enable
+
+
+
+ true
+ false
+ Library
+ true
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs b/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
new file mode 100644
index 0000000..063d3b1
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
@@ -0,0 +1,19 @@
+namespace SecretAPI.SourceGenerators.Utils;
+
+internal static class GeneratedIdentifyUtils
+{
+ private static AttributeSyntax GetGeneratedCodeAttributeSyntax()
+ => Attribute(IdentifierName("GeneratedCode"))
+ .WithArgumentList(
+ AttributeArgumentList(
+ SeparatedList(
+ new SyntaxNodeOrToken[]
+ {
+ AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("SecretAPI.CodeGeneration"))),
+ Token(SyntaxKind.CommaToken),
+ AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("1.0.0"))),
+ })));
+
+ internal static AttributeListSyntax GetGeneratedCodeAttributeListSyntax()
+ => AttributeList(SingletonSeparatedList(GetGeneratedCodeAttributeSyntax()));
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs b/SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs
new file mode 100644
index 0000000..f530632
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs
@@ -0,0 +1,12 @@
+namespace SecretAPI.SourceGenerators.Utils;
+
+internal static class GenericTypeUtils
+{
+ internal static TypeSyntax GetSingleGenericTypeSyntax(string genericName, SyntaxKind predefinedType)
+ => GenericName(genericName)
+ .WithTypeArgumentList(
+ TypeArgumentList(
+ SingletonSeparatedList(
+ PredefinedType(
+ Token(predefinedType)))));
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Utils/MethodParameter.cs b/SecretAPI.SourceGenerators/Utils/MethodParameter.cs
new file mode 100644
index 0000000..b2dd8db
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Utils/MethodParameter.cs
@@ -0,0 +1,40 @@
+namespace SecretAPI.SourceGenerators.Utils;
+
+///
+/// Represents a method parameter used during code generation.
+///
+internal readonly struct MethodParameter
+{
+ private readonly SyntaxList _attributeLists;
+ private readonly SyntaxTokenList _modifiers;
+ private readonly TypeSyntax? _type;
+ private readonly SyntaxToken _identifier;
+ private readonly EqualsValueClauseSyntax? _default;
+
+ ///
+ /// Creates a new instance of .
+ ///
+ /// The name of the parameter.
+ /// The parameter type. May be for implicitly-typed parameters.
+ /// Optional parameter modifiers (e.g. ref, out, in).
+ /// Optional attribute lists applied to the parameter.
+ /// Optional default value.
+ internal MethodParameter(
+ string identifier,
+ TypeSyntax? type = null,
+ SyntaxTokenList modifiers = default,
+ SyntaxList attributeLists = default,
+ EqualsValueClauseSyntax? @default = null)
+ {
+ _identifier = IsValidIdentifier(identifier)
+ ? Identifier(identifier)
+ : throw new ArgumentException("Identifier is not valid.", nameof(identifier));
+
+ _type = type;
+ _modifiers = modifiers;
+ _attributeLists = attributeLists;
+ _default = @default;
+ }
+
+ public ParameterSyntax Syntax => Parameter(_attributeLists, _modifiers, _type, _identifier, _default);
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Utils/MethodUtils.cs b/SecretAPI.SourceGenerators/Utils/MethodUtils.cs
new file mode 100644
index 0000000..d0f4b05
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Utils/MethodUtils.cs
@@ -0,0 +1,20 @@
+namespace SecretAPI.SourceGenerators.Utils;
+
+internal static class MethodUtils
+{
+ internal static StatementSyntax MethodCallStatement(string typeName, string methodName) =>
+ MethodCallStatement(ParseTypeName(typeName), IdentifierName(methodName));
+
+ internal static StatementSyntax MethodCallStatement(TypeSyntax type, IdentifierNameSyntax method)
+ => ExpressionStatement(
+ InvocationExpression(
+ MemberAccessExpression(
+ SyntaxKind.SimpleMemberAccessExpression,
+ type, method)));
+
+ internal static StatementSyntax[] MethodCallStatements(IMethodSymbol[] methodCalls)
+ {
+ IEnumerable statements = methodCalls.Select(s => MethodCallStatement(s.ContainingType.ToDisplayString(), s.Name));
+ return statements.ToArray();
+ }
+}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Utils/TypeUtils.cs b/SecretAPI.SourceGenerators/Utils/TypeUtils.cs
new file mode 100644
index 0000000..1b59b10
--- /dev/null
+++ b/SecretAPI.SourceGenerators/Utils/TypeUtils.cs
@@ -0,0 +1,10 @@
+namespace SecretAPI.SourceGenerators.Utils;
+
+internal static class TypeUtils
+{
+ internal static PredefinedTypeSyntax GetPredefinedTypeSyntax(SyntaxKind kind)
+ => PredefinedType(Token(kind));
+
+ internal static TypeSyntax GetTypeSyntax(string typeIdentifier)
+ => IdentifierName(typeIdentifier);
+}
\ No newline at end of file
diff --git a/SecretAPI.sln b/SecretAPI.sln
index 4ed659a..ad97fde 100644
--- a/SecretAPI.sln
+++ b/SecretAPI.sln
@@ -4,6 +4,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecretAPI", "SecretAPI\Secr
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecretAPI.Examples", "SecretAPI.Examples\SecretAPI.Examples.csproj", "{0064C982-5FE1-4B65-82F9-2EEF85651188}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SecretAPI.SourceGenerators", "SecretAPI.SourceGenerators\SecretAPI.SourceGenerators.csproj", "{15C8D708-16DE-4533-AEB6-003C3EDCAD45}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -18,5 +20,9 @@ Global
{0064C982-5FE1-4B65-82F9-2EEF85651188}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0064C982-5FE1-4B65-82F9-2EEF85651188}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0064C982-5FE1-4B65-82F9-2EEF85651188}.Release|Any CPU.Build.0 = Release|Any CPU
+ {15C8D708-16DE-4533-AEB6-003C3EDCAD45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {15C8D708-16DE-4533-AEB6-003C3EDCAD45}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {15C8D708-16DE-4533-AEB6-003C3EDCAD45}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {15C8D708-16DE-4533-AEB6-003C3EDCAD45}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/SecretAPI/SecretAPI.csproj b/SecretAPI/SecretAPI.csproj
index 0302f70..055b9de 100644
--- a/SecretAPI/SecretAPI.csproj
+++ b/SecretAPI/SecretAPI.csproj
@@ -31,6 +31,8 @@
+
+
diff --git a/SecretAPI/SecretApi.cs b/SecretAPI/SecretApi.cs
index 9033e9a..941f7b3 100644
--- a/SecretAPI/SecretApi.cs
+++ b/SecretAPI/SecretApi.cs
@@ -11,7 +11,7 @@
///
/// Main class handling loading API.
///
-public class SecretApi : Plugin
+public partial class SecretApi : Plugin
{
///
public override string Name => "SecretAPI";
From ff689db62795fd254cf33305e3409e957d4eec06 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 27 Apr 2026 16:01:24 +0200
Subject: [PATCH 02/10] Removed unused class
---
SecretAPI.SourceGenerators/GlobalUsings.cs | 1 -
.../Utils/GeneratedIdentifyUtils.cs | 2 +-
SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs | 12 ------------
3 files changed, 1 insertion(+), 14 deletions(-)
delete mode 100644 SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs
diff --git a/SecretAPI.SourceGenerators/GlobalUsings.cs b/SecretAPI.SourceGenerators/GlobalUsings.cs
index eb69204..8869bf3 100644
--- a/SecretAPI.SourceGenerators/GlobalUsings.cs
+++ b/SecretAPI.SourceGenerators/GlobalUsings.cs
@@ -13,7 +13,6 @@
global using SecretAPI.SourceGenerators.Utils;
//? Static utils from SecretAPI
-global using static SecretAPI.SourceGenerators.Utils.GenericTypeUtils;
global using static SecretAPI.SourceGenerators.Utils.GeneratedIdentifyUtils;
global using static SecretAPI.SourceGenerators.Utils.MethodUtils;
global using static SecretAPI.SourceGenerators.Utils.TypeUtils;
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs b/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
index 063d3b1..da236f0 100644
--- a/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
+++ b/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
@@ -13,7 +13,7 @@ private static AttributeSyntax GetGeneratedCodeAttributeSyntax()
Token(SyntaxKind.CommaToken),
AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("1.0.0"))),
})));
-
+
internal static AttributeListSyntax GetGeneratedCodeAttributeListSyntax()
=> AttributeList(SingletonSeparatedList(GetGeneratedCodeAttributeSyntax()));
}
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs b/SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs
deleted file mode 100644
index f530632..0000000
--- a/SecretAPI.SourceGenerators/Utils/GenericTypeUtils.cs
+++ /dev/null
@@ -1,12 +0,0 @@
-namespace SecretAPI.SourceGenerators.Utils;
-
-internal static class GenericTypeUtils
-{
- internal static TypeSyntax GetSingleGenericTypeSyntax(string genericName, SyntaxKind predefinedType)
- => GenericName(genericName)
- .WithTypeArgumentList(
- TypeArgumentList(
- SingletonSeparatedList(
- PredefinedType(
- Token(predefinedType)))));
-}
\ No newline at end of file
From a9decf7a499b0b90b8c20fa932b5326e8a089e73 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 27 Apr 2026 16:18:00 +0200
Subject: [PATCH 03/10] Remove unused pluginInfo parameter
---
.../Generators/CallOnLoadGenerator.cs | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs b/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
index 7147eb0..6171c97 100644
--- a/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
+++ b/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
@@ -69,7 +69,7 @@ private static int GetPriority(IMethodSymbol method, string attributeLocation)
return 0;
}
- private static bool ValidateMethod(SourceProductionContext context, Tuple pluginInfo, IMethodSymbol method)
+ private static bool ValidateMethod(SourceProductionContext context, IMethodSymbol method)
{
bool isValid = true;
@@ -119,13 +119,13 @@ private static void Generate(
}
IMethodSymbol[] loadCalls = methods
- .Where(m => m.isLoad && ValidateMethod(context, pluginInfo, m.method))
+ .Where(m => m.isLoad && ValidateMethod(context, m.method))
.Select(m => m.method)
.OrderBy(m => GetPriority(m, CallOnLoadAttributeLocation))
.ToArray();
IMethodSymbol[] unloadCalls = methods
- .Where(m => m.isUnload && ValidateMethod(context, pluginInfo, m.method))
+ .Where(m => m.isUnload && ValidateMethod(context, m.method))
.Select(m => m.method)
.OrderBy(m => GetPriority(m, CallOnUnloadAttributeLocation))
.ToArray();
From f6322bcc01477ec88c8a32d50b05abb4a5d00753 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 27 Apr 2026 16:26:55 +0200
Subject: [PATCH 04/10] Rules
---
SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md | 6 +++---
SecretAPI.SourceGenerators/Diagnostics.cs | 6 +++---
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md b/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
index ad9f9dc..08f562d 100644
--- a/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
+++ b/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
@@ -2,6 +2,6 @@
Rule ID | Category | Severity | Notes
------------|----------|----------|---------------------
- SecretGen0 | Usage | Error | CA6000_AnalyzerName
- SecretGen1 | Usage | Error | CA6000_AnalyzerName
- SecretGen2 | Usage | Error | CA6000_AnalyzerName
\ No newline at end of file
+ SG001 | Usage | Error | MustBePartialPluginClass
+ SG002 | Usage | Error | MustBeAccessibleMethod
+ SG003 | Usage | Error | MustBeStaticMethod
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Diagnostics.cs b/SecretAPI.SourceGenerators/Diagnostics.cs
index 8b3e2b4..21d8073 100644
--- a/SecretAPI.SourceGenerators/Diagnostics.cs
+++ b/SecretAPI.SourceGenerators/Diagnostics.cs
@@ -3,7 +3,7 @@
internal static class Diagnostics
{
internal static readonly DiagnosticDescriptor MustBePartialPluginClass = new(
- "SecretGen0",
+ "SG001",
"Plugin class must be partial",
"Plugin class '{0}' is missing partial modifier",
"Usage",
@@ -11,7 +11,7 @@ internal static class Diagnostics
true);
internal static readonly DiagnosticDescriptor MustBeAccessibleMethod = new(
- "SecretGen1",
+ "SG002",
"Method must be accessible",
"Method '{0}' has accessibility '{1}', which is not supported for generated calls",
"Usage",
@@ -19,7 +19,7 @@ internal static class Diagnostics
true);
internal static readonly DiagnosticDescriptor MustBeStaticMethod = new(
- "SecretGen2",
+ "SG003",
"Method must be static",
"Method '{0}' is not marked as static",
"Usage",
From de7fb2f34a504161ea0024ac3cd061dccac2de00 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 27 Apr 2026 16:37:47 +0200
Subject: [PATCH 05/10] Fix version number & OnLoad() not being utilized
---
SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs | 6 ++++--
SecretAPI/SecretApi.cs | 2 +-
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs b/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
index da236f0..02a4988 100644
--- a/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
+++ b/SecretAPI.SourceGenerators/Utils/GeneratedIdentifyUtils.cs
@@ -2,6 +2,8 @@
internal static class GeneratedIdentifyUtils
{
+ private static SyntaxToken CurrentVersion => Literal(typeof(GeneratedIdentifyUtils).Assembly.GetName().Version.ToString());
+
private static AttributeSyntax GetGeneratedCodeAttributeSyntax()
=> Attribute(IdentifierName("GeneratedCode"))
.WithArgumentList(
@@ -9,9 +11,9 @@ private static AttributeSyntax GetGeneratedCodeAttributeSyntax()
SeparatedList(
new SyntaxNodeOrToken[]
{
- AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("SecretAPI.CodeGeneration"))),
+ AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("SecretAPI.SourceGenerators"))),
Token(SyntaxKind.CommaToken),
- AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, Literal("1.0.0"))),
+ AttributeArgument(LiteralExpression(SyntaxKind.StringLiteralExpression, CurrentVersion)),
})));
internal static AttributeListSyntax GetGeneratedCodeAttributeListSyntax()
diff --git a/SecretAPI/SecretApi.cs b/SecretAPI/SecretApi.cs
index 941f7b3..7c5931d 100644
--- a/SecretAPI/SecretApi.cs
+++ b/SecretAPI/SecretApi.cs
@@ -48,7 +48,7 @@ public partial class SecretApi : Plugin
///
public override void Enable()
{
- CallOnLoadAttribute.Load(Assembly);
+ OnLoad();
}
///
From 34cf80c9832fea052be2fbc41ba7f922c33d19e7 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Wed, 29 Apr 2026 21:54:33 +0200
Subject: [PATCH 06/10] Fix: Add SourceGenerators as a project to solution
---
SecretAPI.slnx | 1 +
1 file changed, 1 insertion(+)
diff --git a/SecretAPI.slnx b/SecretAPI.slnx
index 99c20fd..6995b49 100644
--- a/SecretAPI.slnx
+++ b/SecretAPI.slnx
@@ -1,4 +1,5 @@
+
From ec9c08f96ec3eb3fd98680c55b91bd964695ad21 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Sat, 2 May 2026 22:29:17 +0200
Subject: [PATCH 07/10] Source Generate: Use SecretApiGenerated naming
---
.../Builders/ClassBuilder.cs | 32 +++++++++++---
.../Generators/CallOnLoadGenerator.cs | 42 +++++--------------
SecretAPI/SecretApi.cs | 2 +-
3 files changed, 37 insertions(+), 39 deletions(-)
diff --git a/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs b/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs
index 671cf80..7f14306 100644
--- a/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs
+++ b/SecretAPI.SourceGenerators/Builders/ClassBuilder.cs
@@ -2,13 +2,13 @@
internal class ClassBuilder : Builder
{
- private NamespaceDeclarationSyntax _namespaceDeclaration;
+ private NamespaceDeclarationSyntax? _namespaceDeclaration;
private ClassDeclarationSyntax _classDeclaration;
private readonly List _usings = new();
private readonly List _methods = new();
- private ClassBuilder(NamespaceDeclarationSyntax namespaceDeclaration, ClassDeclarationSyntax classDeclaration)
+ private ClassBuilder(NamespaceDeclarationSyntax? namespaceDeclaration, ClassDeclarationSyntax classDeclaration)
{
_namespaceDeclaration = namespaceDeclaration;
_classDeclaration = classDeclaration;
@@ -16,12 +16,19 @@ private ClassBuilder(NamespaceDeclarationSyntax namespaceDeclaration, ClassDecla
AddUsingStatements("System.CodeDom.Compiler");
}
+ private ClassBuilder(ClassDeclarationSyntax classDeclaration)
+ : this(null, classDeclaration)
+ {
+ }
+
internal static ClassBuilder CreateBuilder(INamedTypeSymbol namedClass)
=> CreateBuilder(NamespaceDeclaration(ParseName(namedClass.ContainingNamespace.ToDisplayString())), ClassDeclaration(namedClass.Name));
internal static ClassBuilder CreateBuilder(NamespaceDeclarationSyntax namespaceDeclaration, ClassDeclarationSyntax classDeclaration)
=> new(namespaceDeclaration, classDeclaration);
+ internal static ClassBuilder CreateBuilder(ClassDeclarationSyntax classDeclaration) => new(classDeclaration);
+
internal ClassBuilder AddUsingStatements(params string[] usingStatements)
{
foreach (string statement in usingStatements)
@@ -46,14 +53,27 @@ internal CompilationUnitSyntax Build()
.AddModifiers(_modifiers.ToArray())
.AddMembers(_methods.Cast().ToArray());
- _namespaceDeclaration = _namespaceDeclaration
+ _namespaceDeclaration = _namespaceDeclaration?
.AddUsings(_usings.ToArray())
.AddMembers(_classDeclaration);
- return CompilationUnit()
- .AddMembers(_namespaceDeclaration)
+ CompilationUnitSyntax unit = CompilationUnit();
+
+ if (_namespaceDeclaration != null)
+ {
+ _namespaceDeclaration = _namespaceDeclaration
+ .AddUsings(_usings.ToArray())
+ .AddMembers(_classDeclaration);
+ unit = unit.AddMembers(_namespaceDeclaration);
+ }
+ else
+ {
+ unit = unit.AddUsings(_usings.ToArray()).AddMembers(_classDeclaration);
+ }
+
+ return unit
.NormalizeWhitespace()
- .WithLeadingTrivia(Comment("// "), LineFeed, Comment("#pragma warning disable"), LineFeed, Comment("#nullable enable"), LineFeed, LineFeed);
+ .WithLeadingTrivia(Comment("// "), LineFeed, LineFeed, Comment("#pragma warning disable"), LineFeed, Comment("#nullable enable"), LineFeed, LineFeed);
}
internal void Build(SourceProductionContext context, string name) => context.AddSource(name, Build().ToFullString());
diff --git a/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs b/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
index 6171c97..dce991e 100644
--- a/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
+++ b/SecretAPI.SourceGenerators/Generators/CallOnLoadGenerator.cs
@@ -2,12 +2,12 @@
///
/// Code generator for CallOnLoad/CallOnUnload
+/// TODO: Implement IRegister source generation
///
[Generator]
public class CallOnLoadGenerator : IIncrementalGenerator
{
- private const string PluginNamespace = "LabApi.Loader.Features.Plugins";
- private const string PluginBaseClassName = "Plugin";
+ private const string GeneratedClassName = "SecretApiGenerated";
private const string CallOnLoadAttributeLocation = "SecretAPI.Attributes.CallOnLoadAttribute";
private const string CallOnUnloadAttributeLocation = "SecretAPI.Attributes.CallOnUnloadAttribute";
@@ -27,19 +27,8 @@ public void Initialize(IncrementalGeneratorInitializationContext context)
HasAttribute(method, CallOnLoadAttributeLocation),
HasAttribute(method, CallOnUnloadAttributeLocation)))
.Where(static m => m.Item2 || m.Item3);
-
- IncrementalValuesProvider<(ClassDeclarationSyntax?, INamedTypeSymbol?)> pluginClassProvider =
- context.SyntaxProvider.CreateSyntaxProvider(
- static (node, _) => node is ClassDeclarationSyntax,
- static (ctx, _) => (
- ctx.Node as ClassDeclarationSyntax, ctx.SemanticModel.GetDeclaredSymbol(ctx.Node) as INamedTypeSymbol))
- .Where(static c => c.Item2 != null && !c.Item2.IsAbstract && c.Item2.BaseType?.Name == PluginBaseClassName &&
- c.Item2.BaseType.ContainingNamespace.ToDisplayString() == PluginNamespace);
- context.RegisterSourceOutput(pluginClassProvider.Combine(callProvider.Collect()), static (context, data) =>
- {
- Generate(context, new Tuple(data.Left.Item1, data.Left.Item2), data.Right);
- });
+ context.RegisterSourceOutput(callProvider.Collect(), Generate);
}
private static bool HasAttribute(IMethodSymbol? method, string attributeLocation)
@@ -101,23 +90,11 @@ private static bool ValidateMethod(SourceProductionContext context, IMethodSymbo
private static void Generate(
SourceProductionContext context,
- Tuple pluginInfo,
ImmutableArray<(IMethodSymbol method, bool isLoad, bool isUnload)> methods)
{
- if (pluginInfo.Item1 == null || pluginInfo.Item2 == null || methods.IsEmpty)
+ if (methods.IsEmpty)
return;
- if (!pluginInfo.Item1.Modifiers.Any(m => m.IsKind(SyntaxKind.PartialKeyword)))
- {
- context.ReportDiagnostic(
- Diagnostic.Create(
- Diagnostics.MustBePartialPluginClass,
- pluginInfo.Item1.GetLocation(),
- pluginInfo.Item1.Identifier.Text
- )
- );
- }
-
IMethodSymbol[] loadCalls = methods
.Where(m => m.isLoad && ValidateMethod(context, m.method))
.Select(m => m.method)
@@ -133,20 +110,21 @@ private static void Generate(
if (!loadCalls.Any() && !unloadCalls.Any())
return;
- ClassBuilder classBuilder = ClassBuilder.CreateBuilder(pluginInfo.Item2)
+ // ClassBuilder classBuilder = ClassBuilder.CreateBuilder(pluginInfo.Item2)
+ ClassBuilder classBuilder = ClassBuilder.CreateBuilder(ClassDeclaration(GeneratedClassName))
.AddUsingStatements("System")
- .AddModifiers(SyntaxKind.PartialKeyword);
+ .AddModifiers(SyntaxKind.InternalKeyword, SyntaxKind.StaticKeyword);
classBuilder.StartMethodCreation("OnLoad", SyntaxKind.VoidKeyword)
- .AddModifiers(SyntaxKind.PublicKeyword)
+ .AddModifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword)
.AddStatements(MethodCallStatements(loadCalls))
.FinishMethodBuild();
classBuilder.StartMethodCreation("OnUnload", SyntaxKind.VoidKeyword)
- .AddModifiers(SyntaxKind.PublicKeyword)
+ .AddModifiers(SyntaxKind.PublicKeyword, SyntaxKind.StaticKeyword)
.AddStatements(MethodCallStatements(unloadCalls))
.FinishMethodBuild();
- classBuilder.Build(context, $"{pluginInfo.Item2.Name}.g.cs");
+ classBuilder.Build(context, $"{GeneratedClassName}.g.cs");
}
}
\ No newline at end of file
diff --git a/SecretAPI/SecretApi.cs b/SecretAPI/SecretApi.cs
index 7c5931d..1c44952 100644
--- a/SecretAPI/SecretApi.cs
+++ b/SecretAPI/SecretApi.cs
@@ -48,7 +48,7 @@ public partial class SecretApi : Plugin
///
public override void Enable()
{
- OnLoad();
+ SecretApiGenerated.OnLoad();
}
///
From 9be338329c08cb500d81f3c2dcad9c26d3d3c747 Mon Sep 17 00:00:00 2001
From: Evelyn <85962933+obvEve@users.noreply.github.com>
Date: Mon, 4 May 2026 14:53:28 +0200
Subject: [PATCH 08/10] Remove partial modifier
---
SecretAPI/SecretApi.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/SecretAPI/SecretApi.cs b/SecretAPI/SecretApi.cs
index 1c44952..2a288bd 100644
--- a/SecretAPI/SecretApi.cs
+++ b/SecretAPI/SecretApi.cs
@@ -11,7 +11,7 @@
///
/// Main class handling loading API.
///
-public partial class SecretApi : Plugin
+public class SecretApi : Plugin
{
///
public override string Name => "SecretAPI";
@@ -56,4 +56,4 @@ public override void Disable()
{
Harmony.UnpatchAll(Harmony.Id);
}
-}
\ No newline at end of file
+}
From d1b85e5f8fae14eea44ac8263e6ed60cc8e8bfd0 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 4 May 2026 18:05:44 +0200
Subject: [PATCH 09/10] Remove unused diagnostic
---
SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md | 5 ++---
SecretAPI.SourceGenerators/Diagnostics.cs | 8 --------
2 files changed, 2 insertions(+), 11 deletions(-)
diff --git a/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md b/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
index 08f562d..3d2453f 100644
--- a/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
+++ b/SecretAPI.SourceGenerators/AnalyzerReleases.Unshipped.md
@@ -2,6 +2,5 @@
Rule ID | Category | Severity | Notes
------------|----------|----------|---------------------
- SG001 | Usage | Error | MustBePartialPluginClass
- SG002 | Usage | Error | MustBeAccessibleMethod
- SG003 | Usage | Error | MustBeStaticMethod
\ No newline at end of file
+ SG001 | Usage | Error | MustBeAccessibleMethod
+ SG002 | Usage | Error | MustBeStaticMethod
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Diagnostics.cs b/SecretAPI.SourceGenerators/Diagnostics.cs
index 21d8073..a010b5f 100644
--- a/SecretAPI.SourceGenerators/Diagnostics.cs
+++ b/SecretAPI.SourceGenerators/Diagnostics.cs
@@ -2,14 +2,6 @@
internal static class Diagnostics
{
- internal static readonly DiagnosticDescriptor MustBePartialPluginClass = new(
- "SG001",
- "Plugin class must be partial",
- "Plugin class '{0}' is missing partial modifier",
- "Usage",
- DiagnosticSeverity.Error,
- true);
-
internal static readonly DiagnosticDescriptor MustBeAccessibleMethod = new(
"SG002",
"Method must be accessible",
From 122a66fdfca792b6c4ab1938bab0eb707f0421e4 Mon Sep 17 00:00:00 2001
From: Eve <85962933+obvEve@users.noreply.github.com>
Date: Mon, 4 May 2026 18:11:02 +0200
Subject: [PATCH 10/10] Fix: Diagnostic ids
---
SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md | 4 +---
SecretAPI.SourceGenerators/Diagnostics.cs | 4 ++--
2 files changed, 3 insertions(+), 5 deletions(-)
diff --git a/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md b/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md
index 60b59dd..5f28270 100644
--- a/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md
+++ b/SecretAPI.SourceGenerators/AnalyzerReleases.Shipped.md
@@ -1,3 +1 @@
-; Shipped analyzer releases
-; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
-
+
\ No newline at end of file
diff --git a/SecretAPI.SourceGenerators/Diagnostics.cs b/SecretAPI.SourceGenerators/Diagnostics.cs
index a010b5f..8361192 100644
--- a/SecretAPI.SourceGenerators/Diagnostics.cs
+++ b/SecretAPI.SourceGenerators/Diagnostics.cs
@@ -3,7 +3,7 @@
internal static class Diagnostics
{
internal static readonly DiagnosticDescriptor MustBeAccessibleMethod = new(
- "SG002",
+ "SG001",
"Method must be accessible",
"Method '{0}' has accessibility '{1}', which is not supported for generated calls",
"Usage",
@@ -11,7 +11,7 @@ internal static class Diagnostics
true);
internal static readonly DiagnosticDescriptor MustBeStaticMethod = new(
- "SG003",
+ "SG002",
"Method must be static",
"Method '{0}' is not marked as static",
"Usage",