Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Attempting to use --doctool --gdscript-docs gives error Class "class name" hides a global script class. #84579

Open
Variable-ind opened this issue Nov 7, 2023 · 4 comments

Comments

@Variable-ind
Copy link

Variable-ind commented Nov 7, 2023

Godot version

Godot_v4.2-beta5_linux

System information

Linux Mint 21.2

Issue description

Even though #79497 is assumed to be fixed i am having the same errors on the same reproduction project (after the project converts to Godot_v4.2-beta5)

I tried the process by re-creating the project inside Godot_v4.2-beta5 and the same errors appeared again

test-.3.mp4
Godot Engine v4.2.beta5.official.4c96e9676 - https://godotengine.org
 
SCRIPT ERROR: Parse Error: Class "TestClassWithPreloadScript" hides a global script class.
          at: GDScript::reload (res://./test_class_with_preload_script.gd:1)
ERROR: Failed to load script "res://./test_class_with_preload_script.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClassWithClassName" hides a global script class.
          at: GDScript::reload (res://./test_class_with_class_name.gd:1)
ERROR: Failed to load script "res://./test_class_with_class_name.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClassWithPreload" hides a global script class.
          at: GDScript::reload (res://./test_class_with_preload.gd:1)
ERROR: Failed to load script "res://./test_class_with_preload.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClass" hides a global script class.
          at: GDScript::reload (res://./test_class.gd:1)
ERROR: Failed to load script "res://./test_class.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "MyNode" hides a global script class.
          at: GDScript::reload (res://./my_node.gd:1)
ERROR: Failed to load script "res://./my_node.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)

Steps to reproduce

  1. Download the minimal project given below (this is made by hand entirely inside beta 5)
  2. place the extracted project in same folder as godot executable

Screenshot from 2023-11-07 19-15-25

  1. open the folder "newDocToolsTest" inside the terminal
    Screenshot from 2023-11-07 19-22-10

  2. run the command ../Godot_v4.2-beta5_linux.x86_64 --doctool --gdscript-docs ., No docs will get created in the docs/ folder and errors will appear

Minimal reproduction project

newDocToolsTest.zip

@Variable-ind
Copy link
Author

Variable-ind commented Nov 7, 2023

I tried the minimal reproduction project provided by #79497 with the custom compile of the commit that claimed to fix that issue. As i am using linux so for ease i have added the executable to the $PATH (Also please note that at this point in time the minimal reproduction project is made in Godot 4.1)
This time errors are a bit different (Also 3 files get generated):

Godot Engine v4.2.dev.custom_build - https://godotengine.org
 
SCRIPT ERROR: Parse Error: Could not find type "MyNode" in the current scope.
          at: GDScript::reload (res://./test_class_with_class_name.gd:6)
ERROR: Failed to load script "res://./test_class_with_class_name.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)
ERROR: Unable to open file: res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex.
   at: _load_data (scene/resources/compressed_texture.cpp:41)
ERROR: Failed loading resource: res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex. Make sure resources have been imported by opening the project in the editor at least once.
   at: _load (core/io/resource_loader.cpp:274)
ERROR: Failed loading resource: res://icon.svg. Make sure resources have been imported by opening the project in the editor at least once.
   at: _load (core/io/resource_loader.cpp:274)
SCRIPT ERROR: Parse Error: Could not preload resource file "res://icon.svg".
          at: GDScript::reload (res://./test_class_with_preload.gd:9)
SCRIPT ERROR: Parse Error: Could not resolve type for variable "icon".
          at: GDScript::reload (res://./test_class_with_preload.gd:9)
ERROR: Failed to load script "res://./test_class_with_preload.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)

i then converted it to Godot 4.2 and tried the command again. this time no files get generated and the errors are:

Godot Engine v4.2.dev.custom_build - https://godotengine.org
 
SCRIPT ERROR: Parse Error: Class "TestClassWithPreloadScript" hides a global script class.
          at: GDScript::reload (res://./test_class_with_preload_script.gd:1)
ERROR: Failed to load script "res://./test_class_with_preload_script.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)
SCRIPT ERROR: Parse Error: Class "TestClassWithClassName" hides a global script class.
          at: GDScript::reload (res://./test_class_with_class_name.gd:1)
ERROR: Failed to load script "res://./test_class_with_class_name.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)
SCRIPT ERROR: Parse Error: Class "TestClassWithPreload" hides a global script class.
          at: GDScript::reload (res://./test_class_with_preload.gd:1)
ERROR: Failed to load script "res://./test_class_with_preload.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)
SCRIPT ERROR: Parse Error: Class "TestClass" hides a global script class.
          at: GDScript::reload (res://./test_class.gd:1)
ERROR: Failed to load script "res://./test_class.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)
SCRIPT ERROR: Parse Error: Class "MyNode" hides a global script class.
          at: GDScript::reload (res://./my_node.gd:1)
ERROR: Failed to load script "res://./my_node.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2656)

minimal project of issue #79497:
DocToolsTest.zip

here's a video of me going through the process

test-.2.mp4

@fire fire changed the title attempting to use --doctool --gdscript-docs gives error Class "class name" hides a global script class. Attempting to use --doctool --gdscript-docs gives error Class "class name" hides a global script class. Nov 8, 2023
@dandeliondino
Copy link

dandeliondino commented Nov 10, 2023

I made the original issue/MRP, and I just tested and am able to replicate the findings here with 4.2-beta5, but I am still getting the original errors I reported with 4.1.3 (rather than the "hides a global script class"). The original working script (test_class.gd) still works with 4.1.3, but does not work with 4.2-beta5. (I'm using Windows 11).

This appears to be a regression. It looks like the build artifact for #82116 has expired, or I would test it separately.

4.1.3-stable errors:

SCRIPT ERROR: Parse Error: Could not find type "MyNode" in the current scope.
          at: GDScript::reload (<redacted>/test_class_with_class_name.gd:6)
SCRIPT ERROR: Parse Error: Preload file "res://my_node.gd" does not exist.
          at: GDScript::reload (<redacted>/test_class_with_preload.gd:6)
SCRIPT ERROR: Parse Error: Cannot infer the type of "my_loaded_object" variable because the value doesn't have a set type.
          at: GDScript::reload (<redacted>/test_class_with_preload.gd:6)
SCRIPT ERROR: Parse Error: Preload file "res://icon.svg" does not exist.
          at: GDScript::reload (<redacted>/test_class_with_preload.gd:9)
SCRIPT ERROR: Parse Error: Could not resolve type for variable "icon".
          at: GDScript::reload (<redacted>/test_class_with_preload.gd:9)
SCRIPT ERROR: Parse Error: Preload file "res://my_unnamed_node.gd" does not exist.
          at: GDScript::reload (<redacted>/test_class_with_preload_script.gd:5)
SCRIPT ERROR: Parse Error: Cannot infer the type of "MyUnnamedNode" constant because the value doesn't have a set type.
          at: GDScript::reload (<redacted>/test_class_with_preload_script.gd:5)

4.2-beta5 errors:

SCRIPT ERROR: Parse Error: Class "MyNode" hides a global script class.
          at: GDScript::reload (<redacted>/my_node.gd:1)
ERROR: Failed to load script "<redacted>/my_node.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClass" hides a global script class.
          at: GDScript::reload (<redacted>/test_class.gd:1)
ERROR: Failed to load script "<redacted>/test_class.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClassWithClassName" hides a global script class.
          at: GDScript::reload (<redacted>/test_class_with_class_name.gd:1)
ERROR: Failed to load script "<redacted>/test_class_with_class_name.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClassWithPreload" hides a global script class.
          at: GDScript::reload (<redacted>/test_class_with_preload.gd:1)
ERROR: Failed to load script "<redacted>/test_class_with_preload.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)
SCRIPT ERROR: Parse Error: Class "TestClassWithPreloadScript" hides a global script class.
          at: GDScript::reload (<redacted>/test_class_with_preload_script.gd:1)
ERROR: Failed to load script "<redacted>/test_class_with_preload_script.gd" with error "Parse error".
   at: load (modules/gdscript/gdscript.cpp:2703)

Edit: To clarify, this was using the original MRP from #79497. I did open it in 4.2-beta5 to convert it prior to testing in that version. All the scripts do still appear to be generating documentation correctly inside the script editor in 4.2-beta5 (like they did in 4.1).

@Dragoncraft89
Copy link
Contributor

TL;DR: for a workaround use godot --doctool --gdscript-docs res://.

This is caused by a filename mismatch here:

if (p_class->identifier) {
StringName class_name = p_class->identifier->name;
if (GDScriptParser::get_builtin_type(class_name) < Variant::VARIANT_MAX) {
push_error(vformat(R"(Class "%s" hides a built-in type.)", class_name), p_class->identifier);
} else if (class_exists(class_name)) {
push_error(vformat(R"(Class "%s" hides a native class.)", class_name), p_class->identifier);
} else if (ScriptServer::is_global_class(class_name) && (ScriptServer::get_global_class_path(class_name) != parser->script_path || p_class != parser->head)) {
push_error(vformat(R"(Class "%s" hides a global script class.)", class_name), p_class->identifier);
} else if (ProjectSettings::get_singleton()->has_autoload(class_name) && ProjectSettings::get_singleton()->get_autoload(class_name).is_singleton) {
push_error(vformat(R"(Class "%s" hides an autoload singleton.)", class_name), p_class->identifier);
}
}

The script is somehow loaded twice. Once by the doctool and once sometime previously (No idea how/when/why). If you invoke the doctool like this: godot --doctool --gdscript-docs ., then the path to the script will be: ./path/to/file.gd, which is converted during load to res://./path/to/file.gd.

However, the same file has previously been loaded from res://path/to/file.gd. Therefore, during the second load, the script fails this condition: ScriptServer::get_global_class_path(class_name) != parser->script_path because res://./path/to/file.gd != res://path/to/file.gd

The same problem can be demonstrated from within gdscript. MRP (filename test.gd):

class_name Test

func _ready():
    load("test.gd")

In the above MRP, the file is first loaded from res://test.gd by the engine and then as test.gd by the script.

The good news: I found a workaround for this issue. Try invoking with godot --doctool --gdscript-docs res://. There seems to be some path normalization for res:// paths, which normalizes res://./file.gd to res://file.gd. However for a relative path like ./file.gd, the normalization does not take place before it gets converted to a res:// filepath, which results in res://./file.gd.

The bad news: Properly fixing this could be very challenging. Checking whether two file paths are the same is hard, you normally open them and check their device id and inode (Or whatever the windows equivalent is). Now, considering the filesystem abstraction provided by godot this becomes way worse, as it needs to handle multiple edge cases, for example whether res:// is in the filesystem or loaded from a PCK/ZIP.

@anvilfolk
Copy link
Contributor

anvilfolk commented Aug 16, 2024

Could folks check whether this is working as expected in master? I successfully generated .xml files under a docs subfolder using ../Godot_v4.2-beta5_linux.x86_64 --doctool --gdscript-docs . as in the OP, without the res:// workaround.

However, the executable does not terminate - which I believe may be unintended? Created a fix for this in #95656.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants