summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
Diffstat (limited to 'modules')
-rw-r--r--modules/gdscript/gdscript.cpp26
-rw-r--r--modules/gdscript/gdscript.h2
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp54
-rw-r--r--modules/gdscript/gdscript_compiler.cpp5
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd7
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd2
-rw-r--r--modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd3
-rw-r--r--modules/openxr/editor/openxr_action_map_editor.cpp10
-rw-r--r--modules/openxr/editor/openxr_interaction_profile_editor.cpp2
-rw-r--r--modules/openxr/editor/openxr_select_action_dialog.cpp4
-rw-r--r--modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp4
12 files changed, 70 insertions, 51 deletions
diff --git a/modules/gdscript/gdscript.cpp b/modules/gdscript/gdscript.cpp
index 258f1a80f7..57a29cc81e 100644
--- a/modules/gdscript/gdscript.cpp
+++ b/modules/gdscript/gdscript.cpp
@@ -1111,21 +1111,27 @@ bool GDScript::inherits_script(const Ref<Script> &p_script) const {
GDScript *GDScript::find_class(const String &p_qualified_name) {
String first = p_qualified_name.get_slice("::", 0);
+ Vector<String> class_names;
GDScript *result = nullptr;
+ // Empty initial name means start here.
if (first.is_empty() || first == name) {
+ class_names = p_qualified_name.split("::");
result = this;
- } else if (first == get_root_script()->path) {
+ } else if (p_qualified_name.begins_with(get_root_script()->path)) {
+ // Script path could have a class path separator("::") in it.
+ class_names = p_qualified_name.trim_prefix(get_root_script()->path).split("::");
result = get_root_script();
} else if (HashMap<StringName, Ref<GDScript>>::Iterator E = subclasses.find(first)) {
+ class_names = p_qualified_name.split("::");
result = E->value.ptr();
} else if (_owner != nullptr) {
// Check parent scope.
return _owner->find_class(p_qualified_name);
}
- int name_count = p_qualified_name.get_slice_count("::");
- for (int i = 1; result != nullptr && i < name_count; i++) {
- String current_name = p_qualified_name.get_slice("::", i);
+ // Starts at index 1 because index 0 was handled above.
+ for (int i = 1; result != nullptr && i < class_names.size(); i++) {
+ String current_name = class_names[i];
if (HashMap<StringName, Ref<GDScript>>::Iterator E = result->subclasses.find(current_name)) {
result = E->value.ptr();
} else {
@@ -1137,11 +1143,12 @@ GDScript *GDScript::find_class(const String &p_qualified_name) {
return result;
}
-bool GDScript::is_subclass(const GDScript *p_script) {
+bool GDScript::has_class(const GDScript *p_script) {
String fqn = p_script->fully_qualified_name;
- if (!fqn.is_empty() && fqn != fully_qualified_name && fqn.begins_with(fully_qualified_name)) {
- String fqn_rest = fqn.substr(fully_qualified_name.length());
- return find_class(fqn_rest) == p_script;
+ if (fully_qualified_name.is_empty() && fqn.get_slice("::", 0).is_empty()) {
+ return p_script == this;
+ } else if (fqn.begins_with(fully_qualified_name)) {
+ return p_script == find_class(fqn.trim_prefix(fully_qualified_name));
}
return false;
}
@@ -2592,8 +2599,7 @@ Ref<GDScript> GDScriptLanguage::get_script_by_fully_qualified_name(const String
SelfList<GDScript> *elem = script_list.first();
while (elem) {
GDScript *scr = elem->self();
- scr = scr->find_class(p_name);
- if (scr != nullptr) {
+ if (scr->fully_qualified_name == p_name) {
return scr;
}
elem = elem->next();
diff --git a/modules/gdscript/gdscript.h b/modules/gdscript/gdscript.h
index 7911ea47ec..332d18f720 100644
--- a/modules/gdscript/gdscript.h
+++ b/modules/gdscript/gdscript.h
@@ -187,7 +187,7 @@ public:
bool inherits_script(const Ref<Script> &p_script) const override;
GDScript *find_class(const String &p_qualified_name);
- bool is_subclass(const GDScript *p_script);
+ bool has_class(const GDScript *p_script);
GDScript *get_root_script();
bool is_root_script() const { return _owner == nullptr; }
String get_fully_qualified_name() const { return fully_qualified_name; }
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 30ac1f29b1..3bbe71fb90 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -996,7 +996,9 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
check_class_member_name_conflict(p_class, member.enum_value.identifier->name, member.enum_value.parent_enum);
if (member.enum_value.index > 0) {
- member.enum_value.value = member.enum_value.parent_enum->values[member.enum_value.index - 1].value + 1;
+ const GDScriptParser::EnumNode::Value &prev_value = member.enum_value.parent_enum->values[member.enum_value.index - 1];
+ resolve_class_member(p_class, prev_value.identifier->name, member.enum_value.identifier);
+ member.enum_value.value = prev_value.value + 1;
} else {
member.enum_value.value = 0;
}
@@ -3146,6 +3148,16 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
case GDScriptParser::ClassNode::Member::FUNCTION:
p_identifier->set_datatype(make_callable_type(member.function->info));
break;
+ case GDScriptParser::ClassNode::Member::CLASS:
+ if (p_base != nullptr && p_base->is_constant) {
+ Error err = OK;
+ GDScript *scr = GDScriptCache::get_full_script(base.script_path, err).ptr();
+ ERR_FAIL_COND_MSG(err != OK, "Error while getting subscript full script.");
+ scr = scr->find_class(p_identifier->get_datatype().class_type->fqcn);
+ p_identifier->reduced_value = scr;
+ p_identifier->is_constant = true;
+ }
+ break;
default:
break; // Type already set.
}
@@ -3994,37 +4006,27 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
result.kind = GDScriptParser::DataType::CLASS;
// This might be an inner class, so we want to get the parser for the root.
// But still get the inner class from that tree.
- GDScript *current = gds.ptr();
- List<StringName> class_chain;
- while (current->_owner) {
- // Push to front so it's in reverse.
- class_chain.push_front(current->name);
- current = current->_owner;
- }
-
- Ref<GDScriptParserRef> ref = get_parser_for(current->get_path());
+ String script_path = gds->get_script_path();
+ Ref<GDScriptParserRef> ref = get_parser_for(script_path);
if (ref.is_null()) {
- push_error("Could not find script in path.", p_source);
+ push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
GDScriptParser::DataType error_type;
error_type.kind = GDScriptParser::DataType::VARIANT;
return error_type;
}
- ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
-
- GDScriptParser::ClassNode *found = ref->get_parser()->head;
-
- for (const StringName &E : class_chain) {
- if (!found->has_member(E)) {
- return GDScriptParser::DataType();
- }
-
- if (found->get_member(E).type != GDScriptParser::ClassNode::Member::CLASS) {
- return GDScriptParser::DataType();
+ Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
+ GDScriptParser::ClassNode *found = nullptr;
+ if (err == OK) {
+ found = ref->get_parser()->find_class(gds->fully_qualified_name);
+ if (found != nullptr) {
+ err = resolve_class_inheritance(found, p_source);
}
-
- resolve_class_member(found, E, p_source);
-
- found = found->get_member(E).m_class;
+ }
+ if (err || found == nullptr) {
+ push_error(vformat(R"(Could not resolve script "%s".)", script_path), p_source);
+ GDScriptParser::DataType error_type;
+ error_type.kind = GDScriptParser::DataType::VARIANT;
+ return error_type;
}
result.class_type = found;
diff --git a/modules/gdscript/gdscript_compiler.cpp b/modules/gdscript/gdscript_compiler.cpp
index 4740b9b5a9..50588110c4 100644
--- a/modules/gdscript/gdscript_compiler.cpp
+++ b/modules/gdscript/gdscript_compiler.cpp
@@ -117,8 +117,7 @@ GDScriptDataType GDScriptCompiler::_gdtype_from_datatype(const GDScriptParser::D
result.builtin_type = p_datatype.builtin_type;
result.native_type = p_datatype.native_type;
- String root_name = p_datatype.class_type->fqcn.get_slice("::", 0);
- bool is_local_class = !root_name.is_empty() && root_name == main_script->fully_qualified_name;
+ bool is_local_class = parser->has_class(p_datatype.class_type);
Ref<GDScript> script;
if (is_local_class) {
@@ -2300,7 +2299,7 @@ Error GDScriptCompiler::_populate_class_members(GDScript *p_script, const GDScri
return ERR_COMPILATION_FAILED;
}
- if (base.ptr() == main_script || main_script->is_subclass(base.ptr())) {
+ if (main_script->has_class(base.ptr())) {
Error err = _populate_class_members(base.ptr(), p_class->base_type.class_type, p_keep_state);
if (err) {
return err;
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd
new file mode 100644
index 0000000000..ed5fb18b73
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.gd
@@ -0,0 +1,7 @@
+const External = preload("inner_class_constant_assignment_external.notest.gd")
+const ExternalInnerClass = External.InnerClass
+
+func test():
+ var inst_external: ExternalInnerClass = ExternalInnerClass.new()
+ inst_external.x = 4.0
+ print(inst_external.x)
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out
new file mode 100644
index 0000000000..15666c46ad
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment.out
@@ -0,0 +1,2 @@
+GDTEST_OK
+4
diff --git a/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd
new file mode 100644
index 0000000000..788c99d469
--- /dev/null
+++ b/modules/gdscript/tests/scripts/analyzer/features/inner_class_constant_assignment_external.notest.gd
@@ -0,0 +1,2 @@
+class InnerClass:
+ var x: = 3.0
diff --git a/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd b/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd
index 069e54c528..11349cc916 100644
--- a/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd
+++ b/modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd
@@ -42,7 +42,8 @@ const c2 := EV2
enum {
EV1 = 42,
- EV2 = EV3 + 1
+ UNUSED = EV3,
+ EV2
}
enum {
diff --git a/modules/openxr/editor/openxr_action_map_editor.cpp b/modules/openxr/editor/openxr_action_map_editor.cpp
index a2c33a91c4..844423afc0 100644
--- a/modules/openxr/editor/openxr_action_map_editor.cpp
+++ b/modules/openxr/editor/openxr_action_map_editor.cpp
@@ -57,7 +57,7 @@ void OpenXRActionMapEditor::_notification(int p_what) {
case NOTIFICATION_ENTER_TREE:
case NOTIFICATION_THEME_CHANGED: {
for (int i = 0; i < tabs->get_child_count(); i++) {
- Control *tab = static_cast<Control *>(tabs->get_child(i));
+ Control *tab = Object::cast_to<Control>(tabs->get_child(i));
if (tab) {
tab->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("Tree")));
}
@@ -208,7 +208,7 @@ void OpenXRActionMapEditor::_on_remove_action_set(Object *p_action_set_editor) {
void OpenXRActionMapEditor::_on_action_removed() {
for (int i = 0; i < tabs->get_tab_count(); i++) {
// First tab won't be an interaction profile editor, but being thorough..
- OpenXRInteractionProfileEditorBase *interaction_profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(i));
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
if (interaction_profile_editor) {
}
}
@@ -309,7 +309,7 @@ void OpenXRActionMapEditor::_on_tabs_tab_changed(int p_tab) {
}
void OpenXRActionMapEditor::_on_tab_button_pressed(int p_tab) {
- OpenXRInteractionProfileEditorBase *interaction_profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(p_tab));
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(p_tab));
ERR_FAIL_NULL(interaction_profile_editor);
undo_redo->create_action(TTR("Remove interaction profile"));
@@ -375,9 +375,9 @@ void OpenXRActionMapEditor::_clear_action_map() {
child->queue_free();
}
- for (int i = 0; i < tabs->get_tab_count(); i++) {
+ for (int i = tabs->get_tab_count() - 1; i >= 0; --i) {
// First tab won't be an interaction profile editor, but being thorough..
- OpenXRInteractionProfileEditorBase *interaction_profile_editor = static_cast<OpenXRInteractionProfileEditorBase *>(tabs->get_tab_control(i));
+ OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
if (interaction_profile_editor) {
tabs->remove_child(interaction_profile_editor);
interaction_profile_editor->queue_free();
diff --git a/modules/openxr/editor/openxr_interaction_profile_editor.cpp b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
index 3eca1967f5..ee73f6a5cd 100644
--- a/modules/openxr/editor/openxr_interaction_profile_editor.cpp
+++ b/modules/openxr/editor/openxr_interaction_profile_editor.cpp
@@ -308,7 +308,7 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
void OpenXRInteractionProfileEditor::_theme_changed() {
for (int i = 0; i < main_hb->get_child_count(); i++) {
- Control *panel = static_cast<Control *>(main_hb->get_child(i));
+ Control *panel = Object::cast_to<Control>(main_hb->get_child(i));
if (panel) {
panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
}
diff --git a/modules/openxr/editor/openxr_select_action_dialog.cpp b/modules/openxr/editor/openxr_select_action_dialog.cpp
index 5f018291d5..c4b2ef95c5 100644
--- a/modules/openxr/editor/openxr_select_action_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_action_dialog.cpp
@@ -47,7 +47,7 @@ void OpenXRSelectActionDialog::_notification(int p_what) {
void OpenXRSelectActionDialog::_on_select_action(const String p_action) {
if (selected_action != "") {
NodePath button_path = action_buttons[selected_action];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(true);
}
@@ -57,7 +57,7 @@ void OpenXRSelectActionDialog::_on_select_action(const String p_action) {
if (selected_action != "") {
NodePath button_path = action_buttons[selected_action];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(false);
}
diff --git a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
index 6ce26a62db..b871840cb2 100644
--- a/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
+++ b/modules/openxr/editor/openxr_select_interaction_profile_dialog.cpp
@@ -46,7 +46,7 @@ void OpenXRSelectInteractionProfileDialog::_notification(int p_what) {
void OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile(const String p_interaction_profile) {
if (selected_interaction_profile != "") {
NodePath button_path = ip_buttons[selected_interaction_profile];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(true);
}
@@ -56,7 +56,7 @@ void OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile(const
if (selected_interaction_profile != "") {
NodePath button_path = ip_buttons[selected_interaction_profile];
- Button *button = static_cast<Button *>(get_node(button_path));
+ Button *button = Object::cast_to<Button>(get_node(button_path));
if (button != nullptr) {
button->set_flat(false);
}