summaryrefslogtreecommitdiffstats
path: root/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators')
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs30
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs6
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs2
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs3
-rw-r--r--modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs65
6 files changed, 106 insertions, 3 deletions
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md
index 7286853f7a..90c8491177 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/AnalyzerReleases.Unshipped.md
@@ -3,3 +3,6 @@
Rule ID | Category | Severity | Notes
--------|----------|----------|--------------------
GD0003 | Usage | Error | ScriptPathAttributeGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0003.html)
+GD0108 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0108.html)
+GD0109 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0109.html)
+GD0110 | Usage | Error | ScriptPropertiesGenerator, [Documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/c_sharp/diagnostics/GD0110.html)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
index ad7962e7df..8da0818e42 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/Common.cs
@@ -107,6 +107,36 @@ namespace Godot.SourceGenerators
"Types not derived from Node should not export Node members. Node export is only supported in Node-derived classes.",
helpLinkUri: string.Format(_helpLinkFormat, "GD0107"));
+ public static readonly DiagnosticDescriptor OnlyToolClassesShouldUseExportToolButtonRule =
+ new DiagnosticDescriptor(id: "GD0108",
+ title: "The exported tool button is not in a tool class",
+ messageFormat: "The exported tool button '{0}' is not in a tool class",
+ category: "Usage",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ "The exported tool button is not in a tool class. Annotate the class with the '[Tool]' attribute, or remove the '[ExportToolButton]' attribute.",
+ helpLinkUri: string.Format(_helpLinkFormat, "GD0108"));
+
+ public static readonly DiagnosticDescriptor ExportToolButtonShouldNotBeUsedWithExportRule =
+ new DiagnosticDescriptor(id: "GD0109",
+ title: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute",
+ messageFormat: "The '[ExportToolButton]' attribute cannot be used with another '[Export]' attribute on '{0}'",
+ category: "Usage",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ "The '[ExportToolButton]' attribute cannot be used with the '[Export]' attribute. Remove one of the attributes.",
+ helpLinkUri: string.Format(_helpLinkFormat, "GD0109"));
+
+ public static readonly DiagnosticDescriptor ExportToolButtonIsNotCallableRule =
+ new DiagnosticDescriptor(id: "GD0110",
+ title: "The exported tool button is not a Callable",
+ messageFormat: "The exported tool button '{0}' is not a Callable",
+ category: "Usage",
+ DiagnosticSeverity.Error,
+ isEnabledByDefault: true,
+ "The exported tool button is not a Callable. The '[ExportToolButton]' attribute is only supported on members of type Callable.",
+ helpLinkUri: string.Format(_helpLinkFormat, "GD0110"));
+
public static readonly DiagnosticDescriptor SignalDelegateMissingSuffixRule =
new DiagnosticDescriptor(id: "GD0201",
title: "The name of the delegate must end with 'EventHandler'",
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
index 62fa7b0a36..46c446169a 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ExtensionMethods.cs
@@ -287,6 +287,12 @@ namespace Godot.SourceGenerators
public static bool IsGodotGlobalClassAttribute(this INamedTypeSymbol symbol)
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.GlobalClassAttr;
+ public static bool IsGodotExportToolButtonAttribute(this INamedTypeSymbol symbol)
+ => symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ExportToolButtonAttr;
+
+ public static bool IsGodotToolAttribute(this INamedTypeSymbol symbol)
+ => symbol.FullQualifiedNameOmitGlobal() == GodotClasses.ToolAttr;
+
public static bool IsSystemFlagsAttribute(this INamedTypeSymbol symbol)
=> symbol.FullQualifiedNameOmitGlobal() == GodotClasses.SystemFlagsAttr;
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
index af39a54b0b..f6de09e25b 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotClasses.cs
@@ -9,10 +9,12 @@ namespace Godot.SourceGenerators
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
public const string ExportGroupAttr = "Godot.ExportGroupAttribute";
public const string ExportSubgroupAttr = "Godot.ExportSubgroupAttribute";
+ public const string ExportToolButtonAttr = "Godot.ExportToolButtonAttribute";
public const string SignalAttr = "Godot.SignalAttribute";
public const string MustBeVariantAttr = "Godot.MustBeVariantAttribute";
public const string GodotClassNameAttr = "Godot.GodotClassNameAttribute";
public const string GlobalClassAttr = "Godot.GlobalClassAttribute";
+ public const string ToolAttr = "Godot.ToolAttribute";
public const string SystemFlagsAttr = "System.FlagsAttribute";
}
}
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
index bb4c4824e7..d77ebc3cec 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/GodotEnums.cs
@@ -89,7 +89,8 @@ namespace Godot.SourceGenerators
Password = 36,
LayersAvoidance = 37,
DictionaryType = 38,
- Max = 39
+ ToolButton = 39,
+ Max = 40
}
[Flags]
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
index 0f86b3b91c..eb9dc35255 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertiesGenerator.cs
@@ -69,6 +69,7 @@ namespace Godot.SourceGenerators
bool hasNamespace = classNs.Length != 0;
bool isInnerClass = symbol.ContainingType != null;
+ bool isToolClass = symbol.GetAttributes().Any(a => a.AttributeClass?.IsGodotToolAttribute() ?? false);
string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
+ "_ScriptProperties.generated";
@@ -277,6 +278,16 @@ namespace Godot.SourceGenerators
if (propertyInfo == null)
continue;
+ if (propertyInfo.Value.Hint == PropertyHint.ToolButton && !isToolClass)
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ Common.OnlyToolClassesShouldUseExportToolButtonRule,
+ member.Symbol.Locations.FirstLocationWithSourceTreeOrDefault(),
+ member.Symbol.ToDisplayString()
+ ));
+ continue;
+ }
+
AppendPropertyInfo(source, propertyInfo.Value);
}
@@ -418,6 +429,19 @@ namespace Godot.SourceGenerators
var exportAttr = memberSymbol.GetAttributes()
.FirstOrDefault(a => a.AttributeClass?.IsGodotExportAttribute() ?? false);
+ var exportToolButtonAttr = memberSymbol.GetAttributes()
+ .FirstOrDefault(a => a.AttributeClass?.IsGodotExportToolButtonAttribute() ?? false);
+
+ if (exportAttr != null && exportToolButtonAttr != null)
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ Common.ExportToolButtonShouldNotBeUsedWithExportRule,
+ memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
+ memberSymbol.ToDisplayString()
+ ));
+ return null;
+ }
+
var propertySymbol = memberSymbol as IPropertySymbol;
var fieldSymbol = memberSymbol as IFieldSymbol;
@@ -446,19 +470,56 @@ namespace Godot.SourceGenerators
}
}
+ if (exportToolButtonAttr != null && propertySymbol != null && propertySymbol.GetMethod == null)
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ Common.ExportedPropertyIsWriteOnlyRule,
+ propertySymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
+ propertySymbol.ToDisplayString()
+ ));
+ return null;
+ }
+
var memberType = propertySymbol?.Type ?? fieldSymbol!.Type;
var memberVariantType = MarshalUtils.ConvertMarshalTypeToVariantType(marshalType)!.Value;
string memberName = memberSymbol.Name;
+ string? hintString = null;
+
+ if (exportToolButtonAttr != null)
+ {
+ if (memberVariantType != VariantType.Callable)
+ {
+ context.ReportDiagnostic(Diagnostic.Create(
+ Common.ExportToolButtonIsNotCallableRule,
+ memberSymbol.Locations.FirstLocationWithSourceTreeOrDefault(),
+ memberSymbol.ToDisplayString()
+ ));
+ return null;
+ }
+
+ hintString = exportToolButtonAttr.ConstructorArguments[0].Value?.ToString() ?? "";
+ foreach (var namedArgument in exportToolButtonAttr.NamedArguments)
+ {
+ if (namedArgument is { Key: "Icon", Value.Value: string { Length: > 0 } })
+ {
+ hintString += $",{namedArgument.Value.Value}";
+ }
+ }
+
+ return new PropertyInfo(memberVariantType, memberName, PropertyHint.ToolButton,
+ hintString: hintString, PropertyUsageFlags.Editor, exported: true);
+ }
+
if (exportAttr == null)
{
return new PropertyInfo(memberVariantType, memberName, PropertyHint.None,
- hintString: null, PropertyUsageFlags.ScriptVariable, exported: false);
+ hintString: hintString, PropertyUsageFlags.ScriptVariable, exported: false);
}
if (!TryGetMemberExportHint(typeCache, memberType, exportAttr, memberVariantType,
- isTypeArgument: false, out var hint, out var hintString))
+ isTypeArgument: false, out var hint, out hintString))
{
var constructorArguments = exportAttr.ConstructorArguments;