From 8aa444d2123c9ccdcdcb0df73edd5034eb576083 Mon Sep 17 00:00:00 2001 From: Juan Pablo Arce Date: Sun, 21 Jul 2024 17:07:29 -0300 Subject: [PATCH] Fix GD0107 not applying to arrays and dictionaries containing nodes --- ...D0107_OK_ScriptPropertyDefVal.generated.cs | 18 ++++++- .../Sources/ExportDiagnostics_GD0107.cs | 49 ++++++++++++++++++ .../ScriptPropertyDefValGenerator.cs | 51 ++++++++++++------- 3 files changed, 99 insertions(+), 19 deletions(-) diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs index 217f4676376..9a8b3ea8463 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs @@ -11,11 +11,27 @@ partial class ExportDiagnostics_GD0107_OK [global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] internal new static global::System.Collections.Generic.Dictionary GetGodotPropertyDefaultValues() { - var values = new global::System.Collections.Generic.Dictionary(2); + var values = new global::System.Collections.Generic.Dictionary(10); global::Godot.Node __NodeProperty_default_value = default; values.Add(PropertyName.@NodeProperty, global::Godot.Variant.From(__NodeProperty_default_value)); + global::Godot.Node[] __SystemArrayOfNodesProperty_default_value = default; + values.Add(PropertyName.@SystemArrayOfNodesProperty, global::Godot.Variant.CreateFrom(__SystemArrayOfNodesProperty_default_value)); + global::Godot.Collections.Array __GodotArrayOfNodesProperty_default_value = default; + values.Add(PropertyName.@GodotArrayOfNodesProperty, global::Godot.Variant.CreateFrom(__GodotArrayOfNodesProperty_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsKeyProperty_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsKeyProperty, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsKeyProperty_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsValueProperty_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsValueProperty, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsValueProperty_default_value)); global::Godot.Node __NodeField_default_value = default; values.Add(PropertyName.@NodeField, global::Godot.Variant.From(__NodeField_default_value)); + global::Godot.Node[] __SystemArrayOfNodesField_default_value = default; + values.Add(PropertyName.@SystemArrayOfNodesField, global::Godot.Variant.CreateFrom(__SystemArrayOfNodesField_default_value)); + global::Godot.Collections.Array __GodotArrayOfNodesField_default_value = default; + values.Add(PropertyName.@GodotArrayOfNodesField, global::Godot.Variant.CreateFrom(__GodotArrayOfNodesField_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsKeyField_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsKeyField, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsKeyField_default_value)); + global::Godot.Collections.Dictionary __GodotDictionaryWithNodeAsValueField_default_value = default; + values.Add(PropertyName.@GodotDictionaryWithNodeAsValueField, global::Godot.Variant.CreateFrom(__GodotDictionaryWithNodeAsValueField_default_value)); return values; } #endif // TOOLS diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs index 067783ea66d..4613d883c2c 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportDiagnostics_GD0107.cs @@ -1,12 +1,37 @@ using Godot; +using Godot.Collections; public partial class ExportDiagnostics_GD0107_OK : Node { [Export] public Node NodeField; + [Export] + public Node[] SystemArrayOfNodesField; + + [Export] + public Array GodotArrayOfNodesField; + + [Export] + public Dictionary GodotDictionaryWithNodeAsKeyField; + + [Export] + public Dictionary GodotDictionaryWithNodeAsValueField; + [Export] public Node NodeProperty { get; set; } + + [Export] + public Node[] SystemArrayOfNodesProperty { get; set; } + + [Export] + public Array GodotArrayOfNodesProperty { get; set; } + + [Export] + public Dictionary GodotDictionaryWithNodeAsKeyProperty { get; set; } + + [Export] + public Dictionary GodotDictionaryWithNodeAsValueProperty { get; set; } } public partial class ExportDiagnostics_GD0107_KO : Resource @@ -14,6 +39,30 @@ public partial class ExportDiagnostics_GD0107_KO : Resource [Export] public Node {|GD0107:NodeField|}; + [Export] + public Node[] {|GD0107:SystemArrayOfNodesField|}; + + [Export] + public Array {|GD0107:GodotArrayOfNodesField|}; + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsKeyField|}; + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsValueField|}; + [Export] public Node {|GD0107:NodeProperty|} { get; set; } + + [Export] + public Node[] {|GD0107:SystemArrayOfNodesProperty|} { get; set; } + + [Export] + public Array {|GD0107:GodotArrayOfNodesProperty|} { get; set; } + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsKeyProperty|} { get; set; } + + [Export] + public Dictionary {|GD0107:GodotDictionaryWithNodeAsValueProperty|} { get; set; } } diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs index efe88d84680..626f51ecae1 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -196,16 +196,13 @@ namespace Godot.SourceGenerators continue; } - if (marshalType == MarshalType.GodotObjectOrDerived) + if (!isNode && MemberHasNodeType(propertyType, marshalType.Value)) { - if (!isNode && propertyType.InheritsFrom("GodotSharp", GodotClasses.Node)) - { - context.ReportDiagnostic(Diagnostic.Create( - Common.OnlyNodesShouldExportNodesRule, - property.Locations.FirstLocationWithSourceTreeOrDefault() - )); - continue; - } + context.ReportDiagnostic(Diagnostic.Create( + Common.OnlyNodesShouldExportNodesRule, + property.Locations.FirstLocationWithSourceTreeOrDefault() + )); + continue; } var propertyDeclarationSyntax = property.DeclaringSyntaxReferences @@ -315,16 +312,13 @@ namespace Godot.SourceGenerators continue; } - if (marshalType == MarshalType.GodotObjectOrDerived) + if (!isNode && MemberHasNodeType(fieldType, marshalType.Value)) { - if (!isNode && fieldType.InheritsFrom("GodotSharp", GodotClasses.Node)) - { - context.ReportDiagnostic(Diagnostic.Create( - Common.OnlyNodesShouldExportNodesRule, - field.Locations.FirstLocationWithSourceTreeOrDefault() - )); - continue; - } + context.ReportDiagnostic(Diagnostic.Create( + Common.OnlyNodesShouldExportNodesRule, + field.Locations.FirstLocationWithSourceTreeOrDefault() + )); + continue; } EqualsValueClauseSyntax? initializer = field.DeclaringSyntaxReferences @@ -424,6 +418,27 @@ namespace Godot.SourceGenerators context.AddSource(uniqueHint, SourceText.From(source.ToString(), Encoding.UTF8)); } + private static bool MemberHasNodeType(ITypeSymbol memberType, MarshalType marshalType) + { + if (marshalType == MarshalType.GodotObjectOrDerived) + { + return memberType.InheritsFrom("GodotSharp", GodotClasses.Node); + } + if (marshalType == MarshalType.GodotObjectOrDerivedArray) + { + var elementType = ((IArrayTypeSymbol)memberType).ElementType; + return elementType.InheritsFrom("GodotSharp", GodotClasses.Node); + } + if (memberType is INamedTypeSymbol { IsGenericType: true } genericType) + { + return genericType.TypeArguments + .Any(static typeArgument + => typeArgument.InheritsFrom("GodotSharp", GodotClasses.Node)); + } + + return false; + } + private struct ExportedPropertyMetadata { public ExportedPropertyMetadata(string name, MarshalType type, ITypeSymbol typeSymbol, string? value)