1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-13 13:31:48 +00:00

C#: Add source generator for properties and exports default values

The editor no longer needs to create temporary instances to get the
default values. The initializer values of the exported properties are
still evaluated at runtime. For example, in the following example,
`GetInitialValue()` will be called when first looks for default values:

```
[Export] int MyValue = GetInitialValue();
```

Exporting fields with a non-supported type now results in a compiler
error rather than a runtime error when the script is used.
This commit is contained in:
Ignacio Roldán Etcheverry
2022-02-27 21:57:30 +01:00
parent 88e367a406
commit 92503ae8db
34 changed files with 2182 additions and 773 deletions

View File

@@ -1,3 +1,4 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -60,5 +61,110 @@ namespace Godot.SourceGenerators
outerTypeDeclSyntax.GetLocation(),
outerTypeDeclSyntax.SyntaxTree.FilePath));
}
public static void ReportExportedMemberIsStatic(
GeneratorExecutionContext context,
ISymbol exportedMemberSymbol
)
{
var locations = exportedMemberSymbol.Locations;
var location = locations.FirstOrDefault(l => l.SourceTree != null) ?? locations.FirstOrDefault();
bool isField = exportedMemberSymbol is IFieldSymbol;
string message = $"Attempted to export static {(isField ? "field" : "property")}: " +
$"'{exportedMemberSymbol.ToDisplayString()}'";
string description = $"{message}. Only instance fields and properties can be exported." +
" Remove the 'static' modifier or the '[Export]' attribute.";
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor(id: "GODOT-G0101",
title: message,
messageFormat: message,
category: "Usage",
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description),
location,
location?.SourceTree?.FilePath));
}
public static void ReportExportedMemberTypeNotSupported(
GeneratorExecutionContext context,
ISymbol exportedMemberSymbol
)
{
var locations = exportedMemberSymbol.Locations;
var location = locations.FirstOrDefault(l => l.SourceTree != null) ?? locations.FirstOrDefault();
bool isField = exportedMemberSymbol is IFieldSymbol;
string message = $"The type of the exported {(isField ? "field" : "property")} " +
$"is not supported: '{exportedMemberSymbol.ToDisplayString()}'";
string description = $"{message}. Use a supported type or remove the '[Export]' attribute.";
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor(id: "GODOT-G0102",
title: message,
messageFormat: message,
category: "Usage",
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description),
location,
location?.SourceTree?.FilePath));
}
public static void ReportExportedMemberIsReadOnly(
GeneratorExecutionContext context,
ISymbol exportedMemberSymbol
)
{
var locations = exportedMemberSymbol.Locations;
var location = locations.FirstOrDefault(l => l.SourceTree != null) ?? locations.FirstOrDefault();
bool isField = exportedMemberSymbol is IFieldSymbol;
string message = $"The exported {(isField ? "field" : "property")} " +
$"is read-only: '{exportedMemberSymbol.ToDisplayString()}'";
string description = isField ?
$"{message}. Exported fields cannot be read-only." :
$"{message}. Exported properties must be writable.";
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor(id: "GODOT-G0103",
title: message,
messageFormat: message,
category: "Usage",
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description),
location,
location?.SourceTree?.FilePath));
}
public static void ReportExportedMemberIsWriteOnly(
GeneratorExecutionContext context,
ISymbol exportedMemberSymbol
)
{
var locations = exportedMemberSymbol.Locations;
var location = locations.FirstOrDefault(l => l.SourceTree != null) ?? locations.FirstOrDefault();
string message = $"The exported property is write-only: '{exportedMemberSymbol.ToDisplayString()}'";
string description = $"{message}. Exported properties must be readable.";
context.ReportDiagnostic(Diagnostic.Create(
new DiagnosticDescriptor(id: "GODOT-G0104",
title: message,
messageFormat: message,
category: "Usage",
DiagnosticSeverity.Error,
isEnabledByDefault: true,
description),
location,
location?.SourceTree?.FilePath));
}
}
}