Merge pull request #88495 from paulloz/dotnet/test-and-fix-exports-diagnostics
[.NET] Test and fix exports diagnostics
This commit is contained in:
commit
aeaec000fc
|
@ -0,0 +1,77 @@
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Godot.SourceGenerators.Tests;
|
||||||
|
|
||||||
|
public class ExportDiagnosticsTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async void StaticMembers()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
"ExportDiagnostics_GD0101.cs",
|
||||||
|
"ExportDiagnostics_GD0101_ScriptPropertyDefVal.generated.cs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void TypeIsNotSupported()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
"ExportDiagnostics_GD0102.cs",
|
||||||
|
"ExportDiagnostics_GD0102_ScriptPropertyDefVal.generated.cs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ReadOnly()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
"ExportDiagnostics_GD0103.cs",
|
||||||
|
"ExportDiagnostics_GD0103_ScriptPropertyDefVal.generated.cs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void WriteOnly()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
"ExportDiagnostics_GD0104.cs",
|
||||||
|
"ExportDiagnostics_GD0104_ScriptPropertyDefVal.generated.cs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void Indexer()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
"ExportDiagnostics_GD0105.cs",
|
||||||
|
"ExportDiagnostics_GD0105_ScriptPropertyDefVal.generated.cs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void ExplicitInterfaceImplementation()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
new string[] { "ExportDiagnostics_GD0106.cs" },
|
||||||
|
new string[]
|
||||||
|
{
|
||||||
|
"ExportDiagnostics_GD0106_OK_ScriptPropertyDefVal.generated.cs",
|
||||||
|
"ExportDiagnostics_GD0106_KO_ScriptPropertyDefVal.generated.cs",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async void NodeExports()
|
||||||
|
{
|
||||||
|
await CSharpSourceGeneratorVerifier<ScriptPropertyDefValGenerator>.Verify(
|
||||||
|
new string[] { "ExportDiagnostics_GD0107.cs" },
|
||||||
|
new string[]
|
||||||
|
{
|
||||||
|
"ExportDiagnostics_GD0107_OK_ScriptPropertyDefVal.generated.cs",
|
||||||
|
"ExportDiagnostics_GD0107_KO_ScriptPropertyDefVal.generated.cs",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0101
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0102
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0103
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0104
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0105
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0106_KO
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
partial class ExportDiagnostics_GD0106_OK
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||||
|
#if TOOLS
|
||||||
|
/// <summary>
|
||||||
|
/// Get the default values for all properties declared in this class.
|
||||||
|
/// This method is used by Godot to determine the value that will be
|
||||||
|
/// used by the inspector when resetting properties.
|
||||||
|
/// Do not call this method.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
internal new static global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant> GetGodotPropertyDefaultValues()
|
||||||
|
{
|
||||||
|
var values = new global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>(1);
|
||||||
|
int __MyProperty_default_value = default;
|
||||||
|
values.Add(PropertyName.MyProperty, global::Godot.Variant.From<int>(__MyProperty_default_value));
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
#endif // TOOLS
|
||||||
|
#pragma warning restore CS0109
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
partial class ExportDiagnostics_GD0107_KO
|
||||||
|
{
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
partial class ExportDiagnostics_GD0107_OK
|
||||||
|
{
|
||||||
|
#pragma warning disable CS0109 // Disable warning about redundant 'new' keyword
|
||||||
|
#if TOOLS
|
||||||
|
/// <summary>
|
||||||
|
/// Get the default values for all properties declared in this class.
|
||||||
|
/// This method is used by Godot to determine the value that will be
|
||||||
|
/// used by the inspector when resetting properties.
|
||||||
|
/// Do not call this method.
|
||||||
|
/// </summary>
|
||||||
|
[global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)]
|
||||||
|
internal new static global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant> GetGodotPropertyDefaultValues()
|
||||||
|
{
|
||||||
|
var values = new global::System.Collections.Generic.Dictionary<global::Godot.StringName, global::Godot.Variant>(2);
|
||||||
|
global::Godot.Node __NodeProperty_default_value = default;
|
||||||
|
values.Add(PropertyName.NodeProperty, global::Godot.Variant.From<global::Godot.Node>(__NodeProperty_default_value));
|
||||||
|
global::Godot.Node __NodeField_default_value = default;
|
||||||
|
values.Add(PropertyName.NodeField, global::Godot.Variant.From<global::Godot.Node>(__NodeField_default_value));
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
#endif // TOOLS
|
||||||
|
#pragma warning restore CS0109
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0101 : Node
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public static string {|GD0101:StaticField|};
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public static int {|GD0101:StaticProperty|} { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0102 : Node
|
||||||
|
{
|
||||||
|
public struct MyStruct { }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public MyStruct {|GD0102:StructField|};
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public MyStruct {|GD0102:StructProperty|} { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0103 : Node
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public readonly string {|GD0103:ReadOnlyField|};
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public string {|GD0103:ReadOnlyProperty|} { get; }
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0104 : Node
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public string {|GD0104:WriteOnlyProperty|} { set { } }
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0105 : Node
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public int {|GD0105:this|}[int index]
|
||||||
|
{
|
||||||
|
get { return index; }
|
||||||
|
set { }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public interface MyInterface
|
||||||
|
{
|
||||||
|
public int MyProperty { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0106_OK : Node, MyInterface
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public int MyProperty { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0106_KO : Node, MyInterface
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
int MyInterface.{|GD0106:MyProperty|} { get; set; }
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
using Godot;
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0107_OK : Node
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public Node NodeField;
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public Node NodeProperty { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public partial class ExportDiagnostics_GD0107_KO : Resource
|
||||||
|
{
|
||||||
|
[Export]
|
||||||
|
public Node {|GD0107:NodeField|};
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public Node {|GD0107:NodeProperty|} { get; set; }
|
||||||
|
}
|
|
@ -3,6 +3,7 @@ namespace Godot.SourceGenerators
|
||||||
public static class GodotClasses
|
public static class GodotClasses
|
||||||
{
|
{
|
||||||
public const string GodotObject = "Godot.GodotObject";
|
public const string GodotObject = "Godot.GodotObject";
|
||||||
|
public const string Node = "Godot.Node";
|
||||||
public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
|
public const string AssemblyHasScriptsAttr = "Godot.AssemblyHasScriptsAttribute";
|
||||||
public const string ExportAttr = "Godot.ExportAttribute";
|
public const string ExportAttr = "Godot.ExportAttribute";
|
||||||
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
|
public const string ExportCategoryAttr = "Godot.ExportCategoryAttribute";
|
||||||
|
|
|
@ -66,11 +66,13 @@ namespace Godot.SourceGenerators
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
|
INamespaceSymbol namespaceSymbol = symbol.ContainingNamespace;
|
||||||
string classNs = namespaceSymbol != null && !namespaceSymbol.IsGlobalNamespace ?
|
string classNs = namespaceSymbol is { IsGlobalNamespace: false }
|
||||||
namespaceSymbol.FullQualifiedNameOmitGlobal() :
|
? namespaceSymbol.FullQualifiedNameOmitGlobal()
|
||||||
string.Empty;
|
: string.Empty;
|
||||||
bool hasNamespace = classNs.Length != 0;
|
bool hasNamespace = classNs.Length != 0;
|
||||||
|
|
||||||
|
bool isNode = symbol.InheritsFrom("GodotSharp", GodotClasses.Node);
|
||||||
|
|
||||||
bool isInnerClass = symbol.ContainingType != null;
|
bool isInnerClass = symbol.ContainingType != null;
|
||||||
|
|
||||||
string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
|
string uniqueHint = symbol.FullQualifiedNameOmitGlobal().SanitizeQualifiedNameForUniqueHint()
|
||||||
|
@ -114,14 +116,14 @@ namespace Godot.SourceGenerators
|
||||||
var members = symbol.GetMembers();
|
var members = symbol.GetMembers();
|
||||||
|
|
||||||
var exportedProperties = members
|
var exportedProperties = members
|
||||||
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Property)
|
.Where(s => s.Kind == SymbolKind.Property)
|
||||||
.Cast<IPropertySymbol>()
|
.Cast<IPropertySymbol>()
|
||||||
.Where(s => s.GetAttributes()
|
.Where(s => s.GetAttributes()
|
||||||
.Any(a => a.AttributeClass?.IsGodotExportAttribute() ?? false))
|
.Any(a => a.AttributeClass?.IsGodotExportAttribute() ?? false))
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
var exportedFields = members
|
var exportedFields = members
|
||||||
.Where(s => !s.IsStatic && s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared)
|
.Where(s => s.Kind == SymbolKind.Field && !s.IsImplicitlyDeclared)
|
||||||
.Cast<IFieldSymbol>()
|
.Cast<IFieldSymbol>()
|
||||||
.Where(s => s.GetAttributes()
|
.Where(s => s.GetAttributes()
|
||||||
.Any(a => a.AttributeClass?.IsGodotExportAttribute() ?? false))
|
.Any(a => a.AttributeClass?.IsGodotExportAttribute() ?? false))
|
||||||
|
@ -198,13 +200,13 @@ namespace Godot.SourceGenerators
|
||||||
|
|
||||||
if (marshalType == MarshalType.GodotObjectOrDerived)
|
if (marshalType == MarshalType.GodotObjectOrDerived)
|
||||||
{
|
{
|
||||||
if (!symbol.InheritsFrom("GodotSharp", "Godot.Node") &&
|
if (!isNode && propertyType.InheritsFrom("GodotSharp", GodotClasses.Node))
|
||||||
propertyType.InheritsFrom("GodotSharp", "Godot.Node"))
|
|
||||||
{
|
{
|
||||||
context.ReportDiagnostic(Diagnostic.Create(
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
Common.OnlyNodesShouldExportNodesRule,
|
Common.OnlyNodesShouldExportNodesRule,
|
||||||
property.Locations.FirstLocationWithSourceTreeOrDefault()
|
property.Locations.FirstLocationWithSourceTreeOrDefault()
|
||||||
));
|
));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,13 +319,13 @@ namespace Godot.SourceGenerators
|
||||||
|
|
||||||
if (marshalType == MarshalType.GodotObjectOrDerived)
|
if (marshalType == MarshalType.GodotObjectOrDerived)
|
||||||
{
|
{
|
||||||
if (!symbol.InheritsFrom("GodotSharp", "Godot.Node") &&
|
if (!isNode && fieldType.InheritsFrom("GodotSharp", GodotClasses.Node))
|
||||||
fieldType.InheritsFrom("GodotSharp", "Godot.Node"))
|
|
||||||
{
|
{
|
||||||
context.ReportDiagnostic(Diagnostic.Create(
|
context.ReportDiagnostic(Diagnostic.Create(
|
||||||
Common.OnlyNodesShouldExportNodesRule,
|
Common.OnlyNodesShouldExportNodesRule,
|
||||||
field.Locations.FirstLocationWithSourceTreeOrDefault()
|
field.Locations.FirstLocationWithSourceTreeOrDefault()
|
||||||
));
|
));
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue