Skip to content

Commit 2db6b50

Browse files
matelqclaude
andcommitted
Mono: Add source generator tests for external assembly script paths
Tests ScriptPathAttributeGenerator for multi-assembly scenarios: - ExternalAssemblyInTree: source inside Godot project gets res:// path - ExternalAssemblyOutOfTree: source outside project gets csharp:// path Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 2b2f737 commit 2db6b50

File tree

3 files changed

+89
-0
lines changed

3 files changed

+89
-0
lines changed

modules/mono/editor/Godot.NET.Sdk/Godot.SourceGenerators.Tests/ScriptPathAttributeGeneratorTests.cs

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
using Microsoft.CodeAnalysis;
2+
using Microsoft.CodeAnalysis.CSharp.Testing;
3+
using Microsoft.CodeAnalysis.Testing;
14
using Microsoft.CodeAnalysis.Text;
25
using System;
36
using System.Collections.Generic;
@@ -22,6 +25,29 @@ private static (string, SourceText) MakeAssemblyScriptTypesGeneratedSource(IColl
2225
);
2326
}
2427

28+
/// <summary>
29+
/// Creates a verifier with a custom GodotProjectDir, for testing out-of-tree source paths.
30+
/// </summary>
31+
private static CSharpSourceGeneratorVerifier<ScriptPathAttributeGenerator>.Test MakeVerifierWithCustomProjectDir(
32+
string godotProjectDir, string assemblyName = "TestProject")
33+
{
34+
var verifier = new CSharpSourceGeneratorVerifier<ScriptPathAttributeGenerator>.Test();
35+
36+
verifier.TestState.AnalyzerConfigFiles.Add(("/.globalconfig", $"""
37+
is_global = true
38+
build_property.GodotProjectDir = {godotProjectDir}
39+
"""));
40+
41+
verifier.SolutionTransforms.Add((Solution solution, ProjectId projectId) =>
42+
{
43+
Project project = solution.GetProject(projectId)!
44+
.WithAssemblyName(assemblyName);
45+
return project.Solution;
46+
});
47+
48+
return verifier;
49+
}
50+
2551
[Fact]
2652
public async Task ScriptBoilerplate()
2753
{
@@ -78,4 +104,45 @@ public async Task NamespaceMultipleClassesSameName()
78104
verifier.TestState.GeneratedSources.Add(MakeAssemblyScriptTypesGeneratedSource(new string[] { "global::NamespaceA.SameName", "global::NamespaceB.SameName" }));
79105
await verifier.RunAsync();
80106
}
107+
108+
/// <summary>
109+
/// Tests that an in-tree external assembly script (source inside Godot project dir)
110+
/// gets a normal res:// path.
111+
/// </summary>
112+
[Fact]
113+
public async Task ExternalAssemblyInTree()
114+
{
115+
var verifier = CSharpSourceGeneratorVerifier<ScriptPathAttributeGenerator>.MakeVerifier(
116+
new string[] { "ExternalScript.cs" },
117+
new string[] { "ExternalModule.ExternalScript_ScriptPath.generated.cs" }
118+
);
119+
verifier.TestState.GeneratedSources.Add(
120+
MakeAssemblyScriptTypesGeneratedSource(new string[] { "global::ExternalModule.ExternalScript" }));
121+
await verifier.RunAsync();
122+
}
123+
124+
/// <summary>
125+
/// Tests that an out-of-tree external assembly script (source outside Godot project dir)
126+
/// gets a synthetic csharp:// path instead of an invalid res://../ path.
127+
/// </summary>
128+
[Fact]
129+
public async Task ExternalAssemblyOutOfTree()
130+
{
131+
// Set GodotProjectDir to a subdirectory that won't contain the source file.
132+
// The Roslyn test framework resolves source paths relative to CWD. By setting
133+
// GodotProjectDir to a non-existent subdirectory, the computed relative path
134+
// will start with "../", triggering the csharp:// synthetic path logic.
135+
string deepProjectDir = Path.Combine(Constants.ExecutingAssemblyPath, "nonexistent", "godot_project");
136+
137+
var verifier = MakeVerifierWithCustomProjectDir(deepProjectDir, "ExternalLib");
138+
139+
string source = File.ReadAllText(Path.Combine(Constants.SourceFolderPath, "ExternalScript.cs"));
140+
verifier.TestState.Sources.Add(("ExternalScript.cs", SourceText.From(source)));
141+
142+
// Skip exact source check because SourceFile contains a machine-dependent absolute path.
143+
verifier.TestBehaviors |=
144+
Microsoft.CodeAnalysis.Testing.TestBehaviors.SkipGeneratedSourcesCheck;
145+
146+
await verifier.RunAsync();
147+
}
81148
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Godot;
2+
namespace ExternalModule {
3+
4+
[ScriptPathAttribute("res://ExternalScript.cs")]
5+
partial class ExternalScript
6+
{
7+
}
8+
9+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Godot;
2+
3+
namespace ExternalModule;
4+
5+
public partial class ExternalScript : Node
6+
{
7+
private int _health;
8+
9+
public override void _Ready()
10+
{
11+
_health = 100;
12+
}
13+
}

0 commit comments

Comments
 (0)