summaryrefslogtreecommitdiff
path: root/modules/gdscript/gdscript_analyzer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_analyzer.cpp')
-rw-r--r--modules/gdscript/gdscript_analyzer.cpp78
1 files changed, 36 insertions, 42 deletions
diff --git a/modules/gdscript/gdscript_analyzer.cpp b/modules/gdscript/gdscript_analyzer.cpp
index 78e437b42a..de0dacece3 100644
--- a/modules/gdscript/gdscript_analyzer.cpp
+++ b/modules/gdscript/gdscript_analyzer.cpp
@@ -42,6 +42,11 @@
#include "gdscript_utility_functions.h"
#include "scene/resources/packed_scene.h"
+#if defined(TOOLS_ENABLED) && !defined(DISABLE_DEPRECATED)
+#define SUGGEST_GODOT4_RENAMES
+#include "editor/renames_map_3_to_4.h"
+#endif
+
#define UNNAMED_ENUM "<anonymous enum>"
#define ENUM_SEPARATOR "::"
@@ -1576,11 +1581,8 @@ void GDScriptAnalyzer::resolve_function_body(GDScriptParser::FunctionNode *p_fun
resolve_suite(p_function->body);
- GDScriptParser::DataType return_type = p_function->body->get_datatype();
-
- if (!p_function->get_datatype().is_hard_type() && return_type.is_set()) {
+ if (!p_function->get_datatype().is_hard_type() && p_function->body->get_datatype().is_set()) {
// Use the suite inferred type if return isn't explicitly set.
- return_type.type_source = GDScriptParser::DataType::INFERRED;
p_function->set_datatype(p_function->body->get_datatype());
} else if (p_function->get_datatype().is_hard_type() && (p_function->get_datatype().kind != GDScriptParser::DataType::BUILTIN || p_function->get_datatype().builtin_type != Variant::NIL)) {
if (!p_function->body->has_return && (p_is_lambda || p_function->identifier->name != GDScriptLanguage::get_singleton()->strings._init)) {
@@ -2604,9 +2606,8 @@ void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_o
p_binary_op->set_datatype(result);
}
-#ifdef TOOLS_ENABLED
-#ifndef DISABLE_DEPRECATED
-const char *GDScriptAnalyzer::get_rename_from_map(const char *map[][2], String key) {
+#ifdef SUGGEST_GODOT4_RENAMES
+const char *get_rename_from_map(const char *map[][2], String key) {
for (int index = 0; map[index][0]; index++) {
if (map[index][0] == key) {
return map[index][1];
@@ -2617,39 +2618,39 @@ const char *GDScriptAnalyzer::get_rename_from_map(const char *map[][2], String k
// Checks if an identifier/function name has been renamed in Godot 4, uses ProjectConverter3To4 for rename map.
// Returns the new name if found, nullptr otherwise.
-const char *GDScriptAnalyzer::check_for_renamed_identifier(String identifier, GDScriptParser::Node::Type type) {
+const char *check_for_renamed_identifier(String identifier, GDScriptParser::Node::Type type) {
switch (type) {
case GDScriptParser::Node::IDENTIFIER: {
// Check properties
- const char *result = get_rename_from_map(ProjectConverter3To4::gdscript_properties_renames, identifier);
+ const char *result = get_rename_from_map(RenamesMap3To4::gdscript_properties_renames, identifier);
if (result) {
return result;
}
// Check enum values
- result = get_rename_from_map(ProjectConverter3To4::enum_renames, identifier);
+ result = get_rename_from_map(RenamesMap3To4::enum_renames, identifier);
if (result) {
return result;
}
// Check color constants
- result = get_rename_from_map(ProjectConverter3To4::color_renames, identifier);
+ result = get_rename_from_map(RenamesMap3To4::color_renames, identifier);
if (result) {
return result;
}
// Check type names
- result = get_rename_from_map(ProjectConverter3To4::class_renames, identifier);
+ result = get_rename_from_map(RenamesMap3To4::class_renames, identifier);
if (result) {
return result;
}
- return get_rename_from_map(ProjectConverter3To4::builtin_types_renames, identifier);
+ return get_rename_from_map(RenamesMap3To4::builtin_types_renames, identifier);
}
case GDScriptParser::Node::CALL: {
- const char *result = get_rename_from_map(ProjectConverter3To4::gdscript_function_renames, identifier);
+ const char *result = get_rename_from_map(RenamesMap3To4::gdscript_function_renames, identifier);
if (result) {
return result;
}
// Built-in Types are mistaken for function calls when the built-in type is not found.
// Check built-in types if function rename not found
- return get_rename_from_map(ProjectConverter3To4::builtin_types_renames, identifier);
+ return get_rename_from_map(RenamesMap3To4::builtin_types_renames, identifier);
}
// Signal references don't get parsed through the GDScriptAnalyzer. No support for signal rename hints.
default:
@@ -2657,8 +2658,7 @@ const char *GDScriptAnalyzer::check_for_renamed_identifier(String identifier, GD
return nullptr;
}
}
-#endif // DISABLE_DEPRECATED
-#endif // TOOLS_ENABLED
+#endif // SUGGEST_GODOT4_RENAMES
void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_await, bool p_is_root) {
bool all_is_constant = true;
@@ -3017,7 +3017,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parent_function->identifier->name), p_call);
} else if (!is_self && base_type.is_meta_type && !is_static) {
base_type.is_meta_type = false; // For `to_string()`.
- push_error(vformat(R"*(Cannot call non-static function "%s()" on a class directly. Make an instance instead.)*", p_call->function_name), p_call);
+ push_error(vformat(R"*(Cannot call non-static function "%s()" on the class "%s" directly. Make an instance instead.)*", p_call->function_name, base_type.to_string()), p_call);
} else if (is_self && !is_static) {
mark_lambda_use_self();
}
@@ -3081,8 +3081,7 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}
if (!found && (is_self || (base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::BUILTIN))) {
String base_name = is_self && !p_call->is_super ? "self" : base_type.to_string();
-#ifdef TOOLS_ENABLED
-#ifndef DISABLE_DEPRECATED
+#ifdef SUGGEST_GODOT4_RENAMES
String rename_hint = String();
if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) {
const char *renamed_function_name = check_for_renamed_identifier(p_call->function_name, p_call->type);
@@ -3091,12 +3090,9 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
}
}
push_error(vformat(R"*(Function "%s()" not found in base %s.%s)*", p_call->function_name, base_name, rename_hint), p_call->is_super ? p_call : p_call->callee);
-#else // !DISABLE_DEPRECATED
- push_error(vformat(R"*(Function "%s()" not found in base %s.)*", p_call->function_name, base_name), p_call->is_super ? p_call : p_call->callee);
-#endif // DISABLE_DEPRECATED
#else
push_error(vformat(R"*(Function "%s()" not found in base %s.)*", p_call->function_name, base_name), p_call->is_super ? p_call : p_call->callee);
-#endif
+#endif // SUGGEST_GODOT4_RENAMES
} else if (!found && (!p_call->is_super && base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::NATIVE && base_type.is_meta_type)) {
push_error(vformat(R"*(Static function "%s()" not found in base "%s".)*", p_call->function_name, base_type.native_type), p_call);
}
@@ -3286,8 +3282,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
p_identifier->reduced_value = result;
p_identifier->set_datatype(type_from_variant(result, p_identifier));
} else if (base.is_hard_type()) {
-#ifdef TOOLS_ENABLED
-#ifndef DISABLE_DEPRECATED
+#ifdef SUGGEST_GODOT4_RENAMES
String rename_hint = String();
if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) {
const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
@@ -3296,12 +3291,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
}
}
push_error(vformat(R"(Cannot find constant "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier);
-#else // !DISABLE_DEPRECATED
- push_error(vformat(R"(Cannot find constant "%s" on base "%s".)", name, base.to_string()), p_identifier);
-#endif // DISABLE_DEPRECATED
#else
push_error(vformat(R"(Cannot find constant "%s" on base "%s".)", name, base.to_string()), p_identifier);
-#endif
+#endif // SUGGEST_GODOT4_RENAMES
}
} else {
switch (base.builtin_type) {
@@ -3330,8 +3322,7 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
}
}
if (base.is_hard_type()) {
-#ifdef TOOLS_ENABLED
-#ifndef DISABLE_DEPRECATED
+#ifdef SUGGEST_GODOT4_RENAMES
String rename_hint = String();
if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) {
const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
@@ -3340,12 +3331,9 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
}
}
push_error(vformat(R"(Cannot find property "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier);
-#else // !DISABLE_DEPRECATED
- push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier);
-#endif // DISABLE_DEPRECATED
#else
push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier);
-#endif
+#endif // SUGGEST_GODOT4_RENAMES
}
}
}
@@ -3685,8 +3673,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
if (GDScriptUtilityFunctions::function_exists(name)) {
push_error(vformat(R"(Built-in function "%s" cannot be used as an identifier.)", name), p_identifier);
} else {
-#ifdef TOOLS_ENABLED
-#ifndef DISABLE_DEPRECATED
+#ifdef SUGGEST_GODOT4_RENAMES
String rename_hint = String();
if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GD4_HINT)).booleanize()) {
const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
@@ -3695,12 +3682,9 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
}
}
push_error(vformat(R"(Identifier "%s" not declared in the current scope.%s)", name, rename_hint), p_identifier);
-#else // !DISABLE_DEPRECATED
- push_error(vformat(R"(Identifier "%s" not declared in the current scope.)", name), p_identifier);
-#endif // DISABLE_DEPRECATED
#else
push_error(vformat(R"(Identifier "%s" not declared in the current scope.)", name), p_identifier);
-#endif
+#endif // SUGGEST_GODOT4_RENAMES
}
GDScriptParser::DataType dummy;
dummy.kind = GDScriptParser::DataType::VARIANT;
@@ -4564,6 +4548,16 @@ bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bo
base_script = base_script->get_base_script();
}
+ // If the base is a script, it might be trying to access members of the Script class itself.
+ if (p_base_type.is_meta_type && !p_is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) {
+ MethodInfo info;
+ StringName script_class = p_base_type.kind == GDScriptParser::DataType::SCRIPT ? p_base_type.script_type->get_class_name() : StringName(GDScript::get_class_static());
+
+ if (ClassDB::get_method_info(script_class, function_name, &info)) {
+ return function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_static, r_vararg);
+ }
+ }
+
if (p_is_constructor) {
// Native types always have a default constructor.
r_return_type = p_base_type;