C#: Fix Generated ScriptProperty Error.

1. Add "this." to prevent errors caused by duplicate variable names.
2. Try to find the default value of property getters.
This commit is contained in:
Magian 2022-11-27 17:40:40 +08:00
parent f16c5b564b
commit c41196f0f3
3 changed files with 150 additions and 11 deletions

View file

@ -12,6 +12,95 @@ namespace Godot.SourceGenerators.Sample
[SuppressMessage("ReSharper", "InconsistentNaming")] [SuppressMessage("ReSharper", "InconsistentNaming")]
public partial class ExportedProperties : Godot.Object public partial class ExportedProperties : Godot.Object
{ {
// Do not generate default value
private String _notGenerate_Property_String = new string("not generate");
[Export]
public String NotGenerate_Complex_Lamda_Property
{
get => _notGenerate_Property_String + Convert.ToInt32("1");
set => _notGenerate_Property_String = value;
}
[Export]
public String NotGenerate_Lamda_NoField_Property
{
get => new string("not generate");
set => _notGenerate_Property_String = value;
}
[Export]
public String NotGenerate_Complex_Return_Property
{
get
{
return _notGenerate_Property_String + Convert.ToInt32("1");
}
set
{
_notGenerate_Property_String = value;
}
}
private int _notGenerate_Property_Int = 1;
[Export]
public string NotGenerate_Returns_Property
{
get
{
if (_notGenerate_Property_Int == 1)
{
return "a";
}
else
{
return "b";
}
}
set
{
_notGenerate_Property_Int = value == "a" ? 1 : 2;
}
}
// Full Property
private String _fullProperty_String = "FullProperty_String";
[Export]
public String FullProperty_String
{
get
{
return _fullProperty_String;
}
set
{
_fullProperty_String = value;
}
}
private String _fullProperty_String_Complex = new string("FullProperty_String_Complex") + Convert.ToInt32("1");
[Export]
public String FullProperty_String_Complex
{
get
{
return _fullProperty_String_Complex;
}
set
{
_fullProperty_String_Complex = value;
}
}
// Lamda Property
private String _lamdaProperty_String = "LamdaProperty_String";
[Export]
public String LamdaProperty_String
{
get => _lamdaProperty_String;
set => _lamdaProperty_String = value;
}
// Auto Property
[Export] private Boolean property_Boolean { get; set; } = true; [Export] private Boolean property_Boolean { get; set; } = true;
[Export] private Char property_Char { get; set; } = 'f'; [Export] private Char property_Char { get; set; } = 'f';
[Export] private SByte property_SByte { get; set; } = 10; [Export] private SByte property_SByte { get; set; } = 10;

View file

@ -292,7 +292,7 @@ namespace Godot.SourceGenerators
source.Append("if (name == PropertyName.") source.Append("if (name == PropertyName.")
.Append(propertyMemberName) .Append(propertyMemberName)
.Append(") {\n") .Append(") {\n")
.Append(" ") .Append(" this.")
.Append(propertyMemberName) .Append(propertyMemberName)
.Append(" = ") .Append(" = ")
.AppendNativeVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType) .AppendNativeVariantToManagedExpr("value", propertyTypeSymbol, propertyMarshalType)
@ -317,7 +317,7 @@ namespace Godot.SourceGenerators
.Append(propertyMemberName) .Append(propertyMemberName)
.Append(") {\n") .Append(") {\n")
.Append(" value = ") .Append(" value = ")
.AppendManagedToNativeVariantExpr(propertyMemberName, propertyMarshalType) .AppendManagedToNativeVariantExpr("this." + propertyMemberName, propertyMarshalType)
.Append(";\n") .Append(";\n")
.Append(" return true;\n") .Append(" return true;\n")
.Append(" }\n"); .Append(" }\n");

View file

@ -2,6 +2,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
@ -163,19 +164,68 @@ namespace Godot.SourceGenerators
continue; continue;
} }
// TODO: Detect default value from simple property getters (currently we only detect from initializers) var propertyDeclarationSyntax = property.DeclaringSyntaxReferences
.Select(r => r.GetSyntax() as PropertyDeclarationSyntax).FirstOrDefault();
EqualsValueClauseSyntax? initializer = property.DeclaringSyntaxReferences
.Select(r => r.GetSyntax() as PropertyDeclarationSyntax)
.Select(s => s?.Initializer ?? null)
.FirstOrDefault();
// Fully qualify the value to avoid issues with namespaces. // Fully qualify the value to avoid issues with namespaces.
string? value = null; string? value = null;
if (initializer != null) if (propertyDeclarationSyntax != null)
{ {
var sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree); if (propertyDeclarationSyntax.Initializer != null)
value = initializer.Value.FullQualifiedSyntax(sm); {
var sm = context.Compilation.GetSemanticModel(propertyDeclarationSyntax.Initializer.SyntaxTree);
value = propertyDeclarationSyntax.Initializer.Value.FullQualifiedSyntax(sm);
}
else
{
var propertyGet = propertyDeclarationSyntax.AccessorList?.Accessors.Where(a => a.Keyword.IsKind(SyntaxKind.GetKeyword)).FirstOrDefault();
if (propertyGet != null)
{
if (propertyGet.ExpressionBody != null)
{
if (propertyGet.ExpressionBody.Expression is IdentifierNameSyntax identifierNameSyntax)
{
var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree);
var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol;
EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.OfType<VariableDeclaratorSyntax>()
.Select(s => s.Initializer)
.FirstOrDefault(i => i != null);
if (initializer != null)
{
sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
value = initializer.Value.FullQualifiedSyntax(sm);
}
}
}
else
{
var returns = propertyGet.DescendantNodes().OfType<ReturnStatementSyntax>();
if (returns.Count() == 1)
{// Generate only single return
var returnStatementSyntax = returns.Single();
if (returnStatementSyntax.Expression is IdentifierNameSyntax identifierNameSyntax)
{
var sm = context.Compilation.GetSemanticModel(identifierNameSyntax.SyntaxTree);
var fieldSymbol = sm.GetSymbolInfo(identifierNameSyntax).Symbol as IFieldSymbol;
EqualsValueClauseSyntax? initializer = fieldSymbol?.DeclaringSyntaxReferences
.Select(r => r.GetSyntax())
.OfType<VariableDeclaratorSyntax>()
.Select(s => s.Initializer)
.FirstOrDefault(i => i != null);
if (initializer != null)
{
sm = context.Compilation.GetSemanticModel(initializer.SyntaxTree);
value = initializer.Value.FullQualifiedSyntax(sm);
}
}
}
}
}
}
} }
exportedMembers.Add(new ExportedPropertyMetadata( exportedMembers.Add(new ExportedPropertyMetadata(