You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-11 13:10:58 +00:00
Implement [ExportToolButton]
This commit is contained in:
@@ -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)
|
||||
|
||||
@@ -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'",
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -89,7 +89,8 @@ namespace Godot.SourceGenerators
|
||||
Password = 36,
|
||||
LayersAvoidance = 37,
|
||||
DictionaryType = 38,
|
||||
Max = 39
|
||||
ToolButton = 39,
|
||||
Max = 40
|
||||
}
|
||||
|
||||
[Flags]
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user