Skip to content

Commit

Permalink
Merge pull request #87712 from akien-mga/revert-gdscript-uid-annotati…
Browse files Browse the repository at this point in the history
…ons-for-now

Revert "Add UID support to GDScript files" (for now)
  • Loading branch information
akien-mga committed Jan 29, 2024
2 parents 37e5a71 + 745f8e1 commit 9ab5ced
Show file tree
Hide file tree
Showing 15 changed files with 15 additions and 307 deletions.
1 change: 0 additions & 1 deletion editor/plugins/script_text_editor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ void ScriptTextEditor::set_edited_resource(const Ref<Resource> &p_res) {
ERR_FAIL_COND(p_res.is_null());

script = p_res;
script->connect_changed(callable_mp((ScriptEditorBase *)this, &ScriptEditorBase::reload_text));

code_editor->get_text_editor()->set_text(script->get_source_code());
code_editor->get_text_editor()->clear_undo_history();
Expand Down
10 changes: 1 addition & 9 deletions modules/gdscript/doc_classes/@GDScript.xml
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@
[/codeblock]
[b]Note:[/b] Only the script can have a custom icon. Inner classes are not supported.
[b]Note:[/b] As annotations describe their subject, the [annotation @icon] annotation must be placed before the class definition and inheritance.
[b]Note:[/b] Unlike most other annotations, the argument of the [annotation @icon] annotation must be a string literal (constant expressions are not supported).
[b]Note:[/b] Unlike other annotations, the argument of the [annotation @icon] annotation must be a string literal (constant expressions are not supported).
</description>
</annotation>
<annotation name="@onready">
Expand Down Expand Up @@ -681,14 +681,6 @@
[b]Note:[/b] As annotations describe their subject, the [annotation @tool] annotation must be placed before the class definition and inheritance.
</description>
</annotation>
<annotation name="@uid">
<return type="void" />
<param index="0" name="uid" type="String" />
<description>
Stores information about UID of this script. This annotation is auto-generated when saving the script and must not be modified manually. Only applies to scripts saved as separate files (i.e. not built-in).
[b]Note:[/b] Unlike most other annotations, the argument of the [annotation @uid] annotation must be a string literal (constant expressions are not supported).
</description>
</annotation>
<annotation name="@warning_ignore" qualifiers="vararg">
<return type="void" />
<param index="0" name="warning" type="String" />
Expand Down
122 changes: 11 additions & 111 deletions modules/gdscript/gdscript.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@

#ifdef TOOLS_ENABLED
#include "editor/editor_paths.h"
#include "editor/editor_settings.h"
#endif

#include <stdint.h>
Expand Down Expand Up @@ -1077,36 +1076,6 @@ Ref<GDScript> GDScript::get_base() const {
return base;
}

String GDScript::get_raw_source_code(const String &p_path, bool *r_error) {
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
if (f.is_null()) {
if (r_error) {
*r_error = true;
}
return String();
}
return f->get_as_utf8_string();
}

Vector2i GDScript::get_uid_lines(const String &p_source) {
GDScriptParser parser;
parser.parse(p_source, "", false);
const GDScriptParser::ClassNode *c = parser.get_tree();
if (!c) {
return Vector2i(-1, -1);
}
return c->uid_lines;
}

String GDScript::create_uid_line(const String &p_uid_str) {
#ifdef TOOLS_ENABLED
if (EDITOR_GET("text_editor/completion/use_single_quotes")) {
return vformat(R"(@uid('%s') # %s)", p_uid_str, RTR("Generated automatically, do not modify."));
}
#endif
return vformat(R"(@uid("%s") # %s)", p_uid_str, RTR("Generated automatically, do not modify."));
}

bool GDScript::inherits_script(const Ref<Script> &p_script) const {
Ref<GDScript> gd = p_script;
if (gd.is_null()) {
Expand Down Expand Up @@ -2624,8 +2593,17 @@ bool GDScriptLanguage::handles_global_class_type(const String &p_type) const {
}

String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_base_type, String *r_icon_path) const {
Error err;
Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ, &err);
if (err) {
return String();
}

String source = f->get_as_utf8_string();

GDScriptParser parser;
parser.parse(GDScript::get_raw_source_code(p_path), p_path, false);
err = parser.parse(source, p_path, false);

const GDScriptParser::ClassNode *c = parser.get_tree();
if (!c) {
return String(); // No class parsed.
Expand Down Expand Up @@ -2839,22 +2817,6 @@ String ResourceFormatLoaderGDScript::get_resource_type(const String &p_path) con
return "";
}

ResourceUID::ID ResourceFormatLoaderGDScript::get_resource_uid(const String &p_path) const {
String ext = p_path.get_extension().to_lower();

if (ext != "gd") {
return ResourceUID::INVALID_ID;
}

GDScriptParser parser;
parser.parse(GDScript::get_raw_source_code(p_path), p_path, false);
const GDScriptParser::ClassNode *c = parser.get_tree();
if (!c) {
return ResourceUID::INVALID_ID;
}
return ResourceUID::get_singleton()->text_to_id(c->uid_string);
}

void ResourceFormatLoaderGDScript::get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types) {
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::READ);
ERR_FAIL_COND_MSG(file.is_null(), "Cannot open file '" + p_path + "'.");
Expand All @@ -2879,49 +2841,17 @@ Error ResourceFormatSaverGDScript::save(const Ref<Resource> &p_resource, const S
ERR_FAIL_COND_V(sqscr.is_null(), ERR_INVALID_PARAMETER);

String source = sqscr->get_source_code();
ResourceUID::ID uid = ResourceSaver::get_resource_id_for_path(p_path, !p_resource->is_built_in());

{
bool source_changed = false;
Error err;
Ref<FileAccess> file = FileAccess::open(p_path, FileAccess::WRITE, &err);

ERR_FAIL_COND_V_MSG(err, err, "Cannot save GDScript file '" + p_path + "'.");

if (uid != ResourceUID::INVALID_ID) {
GDScriptParser parser;
parser.parse(source, "", false);
const GDScriptParser::ClassNode *c = parser.get_tree();
if (c && ResourceUID::get_singleton()->text_to_id(c->uid_string) != uid) {
const Vector2i &uid_idx = c->uid_lines;
PackedStringArray lines = source.split("\n");

if (uid_idx.x > -1) {
for (int i = uid_idx.x + 1; i <= uid_idx.y; i++) {
// If UID is written across multiple lines, erase extra lines.
lines.remove_at(uid_idx.x + 1);
}
lines.write[uid_idx.x] = GDScript::create_uid_line(ResourceUID::get_singleton()->id_to_text(uid));
} else {
lines.insert(0, GDScript::create_uid_line(ResourceUID::get_singleton()->id_to_text(uid)));
}
source = String("\n").join(lines);
source_changed = true;
file->store_string(String("\n").join(lines));
} else {
file->store_string(source);
}
}

file->store_string(source);
if (file->get_error() != OK && file->get_error() != ERR_FILE_EOF) {
return ERR_CANT_CREATE;
}

if (source_changed) {
sqscr->set_source_code(source);
sqscr->reload();
sqscr->emit_changed();
}
}

if (ScriptServer::is_reload_scripts_on_save_enabled()) {
Expand All @@ -2940,33 +2870,3 @@ void ResourceFormatSaverGDScript::get_recognized_extensions(const Ref<Resource>
bool ResourceFormatSaverGDScript::recognize(const Ref<Resource> &p_resource) const {
return Object::cast_to<GDScript>(*p_resource) != nullptr;
}

Error ResourceFormatSaverGDScript::set_uid(const String &p_path, ResourceUID::ID p_uid) {
ERR_FAIL_COND_V(p_path.get_extension() != "gd", ERR_INVALID_PARAMETER);
ERR_FAIL_COND_V(p_uid == ResourceUID::INVALID_ID, ERR_INVALID_PARAMETER);

bool error = false;
const String &source_code = GDScript::get_raw_source_code(p_path, &error);
if (error) {
return ERR_CANT_OPEN;
}

Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::WRITE);
ERR_FAIL_COND_V(f.is_null(), ERR_CANT_OPEN);

const Vector2i &uid_idx = GDScript::get_uid_lines(source_code);
PackedStringArray lines = source_code.split("\n");

if (uid_idx.x > -1) {
for (int i = uid_idx.x + 1; i <= uid_idx.y; i++) {
// If UID is written across multiple lines, erase extra lines.
lines.remove_at(uid_idx.x + 1);
}
lines.write[uid_idx.x] = GDScript::create_uid_line(ResourceUID::get_singleton()->id_to_text(p_uid));
} else {
f->store_line(GDScript::create_uid_line(ResourceUID::get_singleton()->id_to_text(p_uid)));
}
f->store_string(String("\n").join(lines));

return OK;
}
6 changes: 0 additions & 6 deletions modules/gdscript/gdscript.h
Original file line number Diff line number Diff line change
Expand Up @@ -262,10 +262,6 @@ class GDScript : public Script {
bool is_tool() const override { return tool; }
Ref<GDScript> get_base() const;

static String get_raw_source_code(const String &p_path, bool *r_error = nullptr);
static Vector2i get_uid_lines(const String &p_source);
static String create_uid_line(const String &p_uid_str);

const HashMap<StringName, MemberInfo> &debug_get_member_indices() const { return member_indices; }
const HashMap<StringName, GDScriptFunction *> &debug_get_member_functions() const; //this is debug only
StringName debug_get_member_by_index(int p_idx) const;
Expand Down Expand Up @@ -620,7 +616,6 @@ class ResourceFormatLoaderGDScript : public ResourceFormatLoader {
virtual void get_recognized_extensions(List<String> *p_extensions) const;
virtual bool handles_type(const String &p_type) const;
virtual String get_resource_type(const String &p_path) const;
virtual ResourceUID::ID get_resource_uid(const String &p_path) const;
virtual void get_dependencies(const String &p_path, List<String> *p_dependencies, bool p_add_types = false);
};

Expand All @@ -629,7 +624,6 @@ class ResourceFormatSaverGDScript : public ResourceFormatSaver {
virtual Error save(const Ref<Resource> &p_resource, const String &p_path, uint32_t p_flags = 0);
virtual void get_recognized_extensions(const Ref<Resource> &p_resource, List<String> *p_extensions) const;
virtual bool recognize(const Ref<Resource> &p_resource) const;
virtual Error set_uid(const String &p_path, ResourceUID::ID p_uid);
};

#endif // GDSCRIPT_H
38 changes: 3 additions & 35 deletions modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ bool GDScriptParser::annotation_exists(const String &p_annotation_name) const {
GDScriptParser::GDScriptParser() {
// Register valid annotations.
if (unlikely(valid_annotations.is_empty())) {
register_annotation(MethodInfo("@uid", PropertyInfo(Variant::STRING, "uid")), AnnotationInfo::SCRIPT, &GDScriptParser::uid_annotation);
register_annotation(MethodInfo("@tool"), AnnotationInfo::SCRIPT, &GDScriptParser::tool_annotation);
register_annotation(MethodInfo("@icon", PropertyInfo(Variant::STRING, "icon_path")), AnnotationInfo::SCRIPT, &GDScriptParser::icon_annotation);
register_annotation(MethodInfo("@static_unload"), AnnotationInfo::SCRIPT, &GDScriptParser::static_unload_annotation);
Expand Down Expand Up @@ -521,8 +520,6 @@ void GDScriptParser::parse_program() {
// `@icon` needs to be applied in the parser. See GH-72444.
if (annotation->name == SNAME("@icon")) {
annotation->apply(this, head, nullptr);
} else if (annotation->name == SNAME("@uid")) {
annotation->apply(this, head, nullptr);
} else {
head->annotations.push_back(annotation);
}
Expand Down Expand Up @@ -3837,18 +3834,18 @@ bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation)
}

// `@icon`'s argument needs to be resolved in the parser. See GH-72444.
if (p_annotation->name == SNAME("@icon") || p_annotation->name == SNAME("@uid")) {
if (p_annotation->name == SNAME("@icon")) {
ExpressionNode *argument = p_annotation->arguments[0];

if (argument->type != Node::LITERAL) {
push_error(vformat(R"(Argument 1 of annotation "%s" must be a string literal.)", p_annotation->name), argument);
push_error(R"(Argument 1 of annotation "@icon" must be a string literal.)", argument);
return false;
}

Variant value = static_cast<LiteralNode *>(argument)->value;

if (value.get_type() != Variant::STRING) {
push_error(vformat(R"(Argument 1 of annotation "%s" must be a string literal.)", p_annotation->name), argument);
push_error(R"(Argument 1 of annotation "@icon" must be a string literal.)", argument);
return false;
}

Expand All @@ -3860,35 +3857,6 @@ bool GDScriptParser::validate_annotation_arguments(AnnotationNode *p_annotation)
return true;
}

bool GDScriptParser::uid_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class) {
ERR_FAIL_COND_V_MSG(p_target->type != Node::CLASS, false, R"("@uid" annotation can only be applied to classes.)");
ERR_FAIL_COND_V(p_annotation->resolved_arguments.is_empty(), false);

#ifdef DEBUG_ENABLED
if (_has_uid) {
push_error(R"("@uid" annotation can only be used once.)", p_annotation);
return false;
}
#endif // DEBUG_ENABLED

// Assign line range early to allow replacing invalid UIDs.
ClassNode *class_node = static_cast<ClassNode *>(p_target);
class_node->uid_lines = Vector2i(p_annotation->start_line - 1, p_annotation->end_line - 1); // Lines start from 1, so need to subtract.

const String &uid_string = p_annotation->resolved_arguments[0];
#ifdef DEBUG_ENABLED
if (ResourceUID::get_singleton()->text_to_id(uid_string) == ResourceUID::INVALID_ID) {
push_error(R"(The annotated UID is invalid.)", p_annotation);
return false;
}
#endif // DEBUG_ENABLED

class_node->uid_string = uid_string;

_has_uid = true;
return true;
}

bool GDScriptParser::tool_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class) {
#ifdef DEBUG_ENABLED
if (_is_tool) {
Expand Down
4 changes: 0 additions & 4 deletions modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -736,8 +736,6 @@ class GDScriptParser {
IdentifierNode *identifier = nullptr;
String icon_path;
String simplified_icon_path;
String uid_string;
Vector2i uid_lines = Vector2i(-1, -1);
Vector<Member> members;
HashMap<StringName, int> members_indices;
ClassNode *outer = nullptr;
Expand Down Expand Up @@ -1320,7 +1318,6 @@ class GDScriptParser {
friend class GDScriptAnalyzer;

bool _is_tool = false;
bool _has_uid = false;
String script_path;
bool for_completion = false;
bool panic_mode = false;
Expand Down Expand Up @@ -1476,7 +1473,6 @@ class GDScriptParser {
static bool register_annotation(const MethodInfo &p_info, uint32_t p_target_kinds, AnnotationAction p_apply, const Vector<Variant> &p_default_arguments = Vector<Variant>(), bool p_is_vararg = false);
bool validate_annotation_arguments(AnnotationNode *p_annotation);
void clear_unused_annotations();
bool uid_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool tool_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool icon_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
bool onready_annotation(const AnnotationNode *p_annotation, Node *p_target, ClassNode *p_class);
Expand Down
5 changes: 0 additions & 5 deletions modules/gdscript/tests/scripts/parser/errors/uid_duplicate.gd

This file was deleted.

This file was deleted.

4 changes: 0 additions & 4 deletions modules/gdscript/tests/scripts/parser/errors/uid_invalid.gd

This file was deleted.

2 changes: 0 additions & 2 deletions modules/gdscript/tests/scripts/parser/errors/uid_invalid.out

This file was deleted.

5 changes: 0 additions & 5 deletions modules/gdscript/tests/scripts/parser/errors/uid_too_late.gd

This file was deleted.

2 changes: 0 additions & 2 deletions modules/gdscript/tests/scripts/parser/errors/uid_too_late.out

This file was deleted.

5 changes: 0 additions & 5 deletions modules/gdscript/tests/scripts/parser/features/uid.gd

This file was deleted.

1 change: 0 additions & 1 deletion modules/gdscript/tests/scripts/parser/features/uid.out

This file was deleted.

Loading

0 comments on commit 9ab5ced

Please sign in to comment.