diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs index 94d447f61a6..636cd82a118 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptProperties.generated.cs @@ -37,6 +37,18 @@ partial class ExportedProperties /// public new static readonly global::Godot.StringName @LamdaPropertyString = "LamdaPropertyString"; /// + /// Cached name for the 'PrimaryCtorParameter' property. + /// + public new static readonly global::Godot.StringName @PrimaryCtorParameter = "PrimaryCtorParameter"; + /// + /// Cached name for the 'ConstantMath' property. + /// + public new static readonly global::Godot.StringName @ConstantMath = "ConstantMath"; + /// + /// Cached name for the 'StaticStringAddition' property. + /// + public new static readonly global::Godot.StringName @StaticStringAddition = "StaticStringAddition"; + /// /// Cached name for the 'PropertyBoolean' property. /// public new static readonly global::Godot.StringName @PropertyBoolean = "PropertyBoolean"; @@ -317,6 +329,18 @@ partial class ExportedProperties this.@LamdaPropertyString = global::Godot.NativeInterop.VariantUtils.ConvertTo(value); return true; } + if (name == PropertyName.@PrimaryCtorParameter) { + this.@PrimaryCtorParameter = global::Godot.NativeInterop.VariantUtils.ConvertTo(value); + return true; + } + if (name == PropertyName.@ConstantMath) { + this.@ConstantMath = global::Godot.NativeInterop.VariantUtils.ConvertTo(value); + return true; + } + if (name == PropertyName.@StaticStringAddition) { + this.@StaticStringAddition = global::Godot.NativeInterop.VariantUtils.ConvertTo(value); + return true; + } if (name == PropertyName.@PropertyBoolean) { this.@PropertyBoolean = global::Godot.NativeInterop.VariantUtils.ConvertTo(value); return true; @@ -599,6 +623,18 @@ partial class ExportedProperties value = global::Godot.NativeInterop.VariantUtils.CreateFrom(this.@LamdaPropertyString); return true; } + if (name == PropertyName.@PrimaryCtorParameter) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom(this.@PrimaryCtorParameter); + return true; + } + if (name == PropertyName.@ConstantMath) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom(this.@ConstantMath); + return true; + } + if (name == PropertyName.@StaticStringAddition) { + value = global::Godot.NativeInterop.VariantUtils.CreateFrom(this.@StaticStringAddition); + return true; + } if (name == PropertyName.@PropertyBoolean) { value = global::Godot.NativeInterop.VariantUtils.CreateFrom(this.@PropertyBoolean); return true; @@ -870,6 +906,9 @@ partial class ExportedProperties properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.@FullPropertyString_Complex, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.@_lamdaPropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4096, exported: false)); properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.@LamdaPropertyString, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); + properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.@PrimaryCtorParameter, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); + properties.Add(new(type: (global::Godot.Variant.Type)3, name: PropertyName.@ConstantMath, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); + properties.Add(new(type: (global::Godot.Variant.Type)4, name: PropertyName.@StaticStringAddition, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)1, name: PropertyName.@PropertyBoolean, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.@PropertyChar, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); properties.Add(new(type: (global::Godot.Variant.Type)2, name: PropertyName.@PropertySByte, hint: (global::Godot.PropertyHint)0, hintString: "", usage: (global::Godot.PropertyUsageFlags)4102, exported: true)); diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs index 0bf0b0845a4..57829cc226b 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/GeneratedSources/ExportedProperties_ScriptPropertyDefVal.generated.cs @@ -11,7 +11,7 @@ partial class ExportedProperties [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(64); + var values = new global::System.Collections.Generic.Dictionary(67); string __NotGenerateComplexLamdaProperty_default_value = default; values.Add(PropertyName.@NotGenerateComplexLamdaProperty, global::Godot.Variant.From(__NotGenerateComplexLamdaProperty_default_value)); string __NotGenerateLamdaNoFieldProperty_default_value = default; @@ -26,6 +26,12 @@ partial class ExportedProperties values.Add(PropertyName.@FullPropertyString_Complex, global::Godot.Variant.From(__FullPropertyString_Complex_default_value)); string __LamdaPropertyString_default_value = "LamdaPropertyString"; values.Add(PropertyName.@LamdaPropertyString, global::Godot.Variant.From(__LamdaPropertyString_default_value)); + string __PrimaryCtorParameter_default_value = default; + values.Add(PropertyName.@PrimaryCtorParameter, global::Godot.Variant.From(__PrimaryCtorParameter_default_value)); + float __ConstantMath_default_value = 2 * global::Godot.Mathf.Pi; + values.Add(PropertyName.@ConstantMath, global::Godot.Variant.From(__ConstantMath_default_value)); + string __StaticStringAddition_default_value = string.Empty + string.Empty; + values.Add(PropertyName.@StaticStringAddition, global::Godot.Variant.From(__StaticStringAddition_default_value)); bool __PropertyBoolean_default_value = true; values.Add(PropertyName.@PropertyBoolean, global::Godot.Variant.From(__PropertyBoolean_default_value)); char __PropertyChar_default_value = 'f'; diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs index d7fcdc6b1b5..2f55bcf6125 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/TestData/Sources/ExportedProperties.cs @@ -1,7 +1,7 @@ using Godot; using System; -public partial class ExportedProperties : GodotObject +public partial class ExportedProperties(string primaryCtorParameter) : GodotObject { // Do not generate default value private String _notGeneratePropertyString = new string("not generate"); @@ -91,6 +91,18 @@ public partial class ExportedProperties : GodotObject set => _lamdaPropertyString = value; } + // Primary Constructor Parameter + [Export] + public String PrimaryCtorParameter { get; set; } = primaryCtorParameter; + + // Constant Math Expression + [Export] + public Single ConstantMath { get; set; } = 2 * Mathf.Pi; + + // Static Strings Addition + [Export] + public string StaticStringAddition { get; set; } = string.Empty + string.Empty; + // Auto Property [Export] private Boolean PropertyBoolean { get; set; } = true; [Export] private Char PropertyChar { get; set; } = 'f'; 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 e2422ae1ed5..5400115fa44 100644 --- a/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs +++ b/modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators/ScriptPropertyDefValGenerator.cs @@ -336,7 +336,11 @@ namespace Godot.SourceGenerators if (initializer != null) { var sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree); - value = initializer.Value.FullQualifiedSyntax(sm); + var initializerValue = initializer.Value; + if (!IsStaticallyResolvable(initializerValue, sm)) + value = "default"; + else + value = initializer.Value.FullQualifiedSyntax(sm); } exportedMembers.Add(new ExportedPropertyMetadata( @@ -424,109 +428,28 @@ namespace Godot.SourceGenerators private static bool IsStaticallyResolvable(ExpressionSyntax expression, SemanticModel semanticModel) { - // Handle literals (e.g., `10`, `"string"`, `true`, etc.) - if (expression is LiteralExpressionSyntax) + // Find non-static node in expression + foreach (SyntaxNode descendant in expression.DescendantNodesAndSelf()) { - return true; - } - - // Handle negative literals (e.g., `-10`) - if (expression is PrefixUnaryExpressionSyntax { Operand: LiteralExpressionSyntax } && - expression.Kind() == SyntaxKind.UnaryMinusExpression) - { - return true; - } - - // Handle identifiers (e.g., variable names) - if (expression is IdentifierNameSyntax identifier) - { - var symbolInfo = semanticModel.GetSymbolInfo(identifier).Symbol; - - // Ensure it's a static member - return symbolInfo is { IsStatic: true }; - } - - // Handle member access (e.g., `MyClass.StaticValue`) - if (expression is MemberAccessExpressionSyntax memberAccess) - { - var symbolInfo = semanticModel.GetSymbolInfo(memberAccess).Symbol; - - // Ensure it's referring to a static member - return symbolInfo is { IsStatic: true }; - } - - // Handle object creation expressions (e.g., `new Vector2(1.0f, 2.0f)`) - if (expression is ObjectCreationExpressionSyntax objectCreation) - { - // Recursively ensure all its arguments are self-contained - if (objectCreation.ArgumentList == null) + // Constant nodes are static + if (semanticModel.GetConstantValue(descendant).HasValue) { - return true; + continue; } - foreach (var argument in objectCreation.ArgumentList.Arguments) + + // Check non-static symbol + SymbolInfo symbolInfo = semanticModel.GetSymbolInfo(descendant); + if (symbolInfo.Symbol is ISymbol symbol) { - if (!IsStaticallyResolvable(argument.Expression, semanticModel)) + if (symbol.Kind is SymbolKind.Local or SymbolKind.Parameter) { return false; } } - - return true; } - if (expression is ImplicitObjectCreationExpressionSyntax) - { - return true; - } - - if (expression is InvocationExpressionSyntax invocationExpression) - { - // Resolve the method being invoked - var symbolInfo = semanticModel.GetSymbolInfo(invocationExpression).Symbol; - - if (symbolInfo is IMethodSymbol methodSymbol) - { - // Ensure the method is static - if (methodSymbol.IsStatic) - { - return true; - } - } - } - - if (expression is InterpolatedStringExpressionSyntax interpolatedString) - { - foreach (var content in interpolatedString.Contents) - { - if (content is not InterpolationSyntax interpolation) - { - continue; - } - // Analyze the expression inside `${...}` - var interpolatedExpression = interpolation.Expression; - - if (!IsStaticallyResolvable(interpolatedExpression, semanticModel)) - { - return false; - } - } - return true; - } - - if (expression is InitializerExpressionSyntax initializerExpressionSyntax) - { - foreach (var content in initializerExpressionSyntax.Expressions) - { - if (!IsStaticallyResolvable(content, semanticModel)) - { - return false; - } - } - return true; - } - - // Handle other expressions conservatively (e.g., method calls, instance references, etc.) - return false; + // No non-static nodes found + return true; } private static bool MemberHasNodeType(ITypeSymbol memberType, MarshalType marshalType)