C#: Replace most conversions between Variant and System.Object

This commit replaces most usages of `ConvertManagedObjectToVariant` and
`ConvertVariantToManagedObjectOfType`, by using the `Godot.Variant`
struct instead of `System.Object`.

The most notable change is to the `GetGodotPropertyDefaultValues` method
that's generated for scripts. The dictionary it returns now stores
`Godot.Variant` values.

Remaining usages are:

- The `DelegateUtils` class, for the serialization of closure display
  classes during assembly reloading by the editor. These display classes
  are compiler generated classes to store values captured by a closure.
  Since it's generated by the compiler, the only way we have to access
  the fields is through reflection. This leads to using `System.Object`.
- Converting parameters when invoking constructors from the engine.
  This will be replaced with source generators in the future.
- Legacy support for old `GetGodotPropertyDefaultValues` return values.
  We need to keep supporting the old version of this generated method
  for some time. Otherwise, if loading a project built with the previous
  version, it could lead to the loss of exported property values.
  Ideally, we should remove this legacy support before a stable release.
This commit is contained in:
Ignacio Roldán Etcheverry 2022-11-29 01:01:36 +01:00
parent 3afeb28560
commit f86c6b6ac4
8 changed files with 350 additions and 443 deletions

View file

@ -174,7 +174,8 @@ namespace Godot.SourceGenerators
}
else
{
var propertyGet = propertyDeclarationSyntax.AccessorList?.Accessors.Where(a => a.Keyword.IsKind(SyntaxKind.GetKeyword)).FirstOrDefault();
var propertyGet = propertyDeclarationSyntax.AccessorList?.Accessors
.Where(a => a.Keyword.IsKind(SyntaxKind.GetKeyword)).FirstOrDefault();
if (propertyGet != null)
{
if (propertyGet.ExpressionBody != null)
@ -200,7 +201,8 @@ namespace Godot.SourceGenerators
{
var returns = propertyGet.DescendantNodes().OfType<ReturnStatementSyntax>();
if (returns.Count() == 1)
{// Generate only single return
{
// Generate only single return
var returnStatementSyntax = returns.Single();
if (returnStatementSyntax.Expression is IdentifierNameSyntax identifierNameSyntax)
{
@ -277,7 +279,8 @@ namespace Godot.SourceGenerators
{
source.Append("#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword\n");
string dictionaryType = "System.Collections.Generic.Dictionary<Godot.StringName, object>";
string dictionaryType =
"global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>";
source.Append("#if TOOLS\n");
source.Append(" internal new static ");
@ -304,7 +307,7 @@ namespace Godot.SourceGenerators
source.Append(" values.Add(PropertyName.");
source.Append(exportedMember.Name);
source.Append(", ");
source.Append(defaultValueLocalName);
source.AppendManagedToVariantExpr(defaultValueLocalName, exportedMember.Type);
source.Append(");\n");
}