1/**************************************************************************/
2/* gdscript_analyzer.cpp */
3/**************************************************************************/
4/* This file is part of: */
5/* GODOT ENGINE */
6/* https://godotengine.org */
7/**************************************************************************/
8/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10/* */
11/* Permission is hereby granted, free of charge, to any person obtaining */
12/* a copy of this software and associated documentation files (the */
13/* "Software"), to deal in the Software without restriction, including */
14/* without limitation the rights to use, copy, modify, merge, publish, */
15/* distribute, sublicense, and/or sell copies of the Software, and to */
16/* permit persons to whom the Software is furnished to do so, subject to */
17/* the following conditions: */
18/* */
19/* The above copyright notice and this permission notice shall be */
20/* included in all copies or substantial portions of the Software. */
21/* */
22/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29/**************************************************************************/
30
31#include "gdscript_analyzer.h"
32
33#include "gdscript.h"
34#include "gdscript_utility_functions.h"
35
36#include "core/config/engine.h"
37#include "core/config/project_settings.h"
38#include "core/core_constants.h"
39#include "core/core_string_names.h"
40#include "core/io/file_access.h"
41#include "core/io/resource_loader.h"
42#include "core/object/class_db.h"
43#include "core/object/script_language.h"
44#include "core/templates/hash_map.h"
45#include "scene/resources/packed_scene.h"
46
47#if defined(TOOLS_ENABLED) && !defined(DISABLE_DEPRECATED)
48#define SUGGEST_GODOT4_RENAMES
49#include "editor/renames_map_3_to_4.h"
50#endif
51
52#define UNNAMED_ENUM "<anonymous enum>"
53#define ENUM_SEPARATOR "."
54
55static MethodInfo info_from_utility_func(const StringName &p_function) {
56 ERR_FAIL_COND_V(!Variant::has_utility_function(p_function), MethodInfo());
57
58 MethodInfo info(p_function);
59
60 if (Variant::has_utility_function_return_value(p_function)) {
61 info.return_val.type = Variant::get_utility_function_return_type(p_function);
62 if (info.return_val.type == Variant::NIL) {
63 info.return_val.usage |= PROPERTY_USAGE_NIL_IS_VARIANT;
64 }
65 }
66
67 if (Variant::is_utility_function_vararg(p_function)) {
68 info.flags |= METHOD_FLAG_VARARG;
69 } else {
70 for (int i = 0; i < Variant::get_utility_function_argument_count(p_function); i++) {
71 PropertyInfo pi;
72#ifdef DEBUG_METHODS_ENABLED
73 pi.name = Variant::get_utility_function_argument_name(p_function, i);
74#else
75 pi.name = "arg" + itos(i + 1);
76#endif
77 pi.type = Variant::get_utility_function_argument_type(p_function, i);
78 info.arguments.push_back(pi);
79 }
80 }
81
82 return info;
83}
84
85static GDScriptParser::DataType make_callable_type(const MethodInfo &p_info) {
86 GDScriptParser::DataType type;
87 type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
88 type.kind = GDScriptParser::DataType::BUILTIN;
89 type.builtin_type = Variant::CALLABLE;
90 type.is_constant = true;
91 type.method_info = p_info;
92 return type;
93}
94
95static GDScriptParser::DataType make_signal_type(const MethodInfo &p_info) {
96 GDScriptParser::DataType type;
97 type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
98 type.kind = GDScriptParser::DataType::BUILTIN;
99 type.builtin_type = Variant::SIGNAL;
100 type.is_constant = true;
101 type.method_info = p_info;
102 return type;
103}
104
105static GDScriptParser::DataType make_native_meta_type(const StringName &p_class_name) {
106 GDScriptParser::DataType type;
107 type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
108 type.kind = GDScriptParser::DataType::NATIVE;
109 type.builtin_type = Variant::OBJECT;
110 type.native_type = p_class_name;
111 type.is_constant = true;
112 type.is_meta_type = true;
113 return type;
114}
115
116static GDScriptParser::DataType make_script_meta_type(const Ref<Script> &p_script) {
117 GDScriptParser::DataType type;
118 type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
119 type.kind = GDScriptParser::DataType::SCRIPT;
120 type.builtin_type = Variant::OBJECT;
121 type.native_type = p_script->get_instance_base_type();
122 type.script_type = p_script;
123 type.script_path = p_script->get_path();
124 type.is_constant = true;
125 type.is_meta_type = true;
126 return type;
127}
128
129// In enum types, native_type is used to store the class (native or otherwise) that the enum belongs to.
130// This disambiguates between similarly named enums in base classes or outer classes
131static GDScriptParser::DataType make_enum_type(const StringName &p_enum_name, const String &p_base_name, const bool p_meta = false) {
132 GDScriptParser::DataType type;
133 type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
134 type.kind = GDScriptParser::DataType::ENUM;
135 type.builtin_type = p_meta ? Variant::DICTIONARY : Variant::INT;
136 type.enum_type = p_enum_name;
137 type.is_constant = true;
138 type.is_meta_type = p_meta;
139
140 // For enums, native_type is only used to check compatibility in is_type_compatible()
141 // We can set anything readable here for error messages, as long as it uniquely identifies the type of the enum
142 if (p_base_name.is_empty()) {
143 type.native_type = p_enum_name;
144 } else {
145 type.native_type = p_base_name + ENUM_SEPARATOR + p_enum_name;
146 }
147
148 return type;
149}
150
151static GDScriptParser::DataType make_native_enum_type(const StringName &p_enum_name, const StringName &p_native_class, bool p_meta = true) {
152 // Find out which base class declared the enum, so the name is always the same even when coming from other contexts.
153 StringName native_base = p_native_class;
154 while (true && native_base != StringName()) {
155 if (ClassDB::has_enum(native_base, p_enum_name, true)) {
156 break;
157 }
158 native_base = ClassDB::get_parent_class_nocheck(native_base);
159 }
160
161 GDScriptParser::DataType type = make_enum_type(p_enum_name, native_base, p_meta);
162 if (p_meta) {
163 type.builtin_type = Variant::NIL; // Native enum types are not Dictionaries.
164 }
165
166 List<StringName> enum_values;
167 ClassDB::get_enum_constants(native_base, p_enum_name, &enum_values, true);
168
169 for (const StringName &E : enum_values) {
170 type.enum_values[E] = ClassDB::get_integer_constant(native_base, E);
171 }
172
173 return type;
174}
175
176static GDScriptParser::DataType make_global_enum_type(const StringName &p_enum_name, const StringName &p_base, bool p_meta = true) {
177 GDScriptParser::DataType type = make_enum_type(p_enum_name, p_base, p_meta);
178 if (p_meta) {
179 type.builtin_type = Variant::NIL; // Native enum types are not Dictionaries.
180 type.is_pseudo_type = true;
181 }
182
183 HashMap<StringName, int64_t> enum_values;
184 CoreConstants::get_enum_values(type.native_type, &enum_values);
185 for (const KeyValue<StringName, int64_t> &element : enum_values) {
186 type.enum_values[element.key] = element.value;
187 }
188
189 return type;
190}
191
192static GDScriptParser::DataType make_builtin_meta_type(Variant::Type p_type) {
193 GDScriptParser::DataType type;
194 type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
195 type.kind = GDScriptParser::DataType::BUILTIN;
196 type.builtin_type = p_type;
197 type.is_constant = true;
198 type.is_meta_type = true;
199 return type;
200}
201
202bool GDScriptAnalyzer::has_member_name_conflict_in_script_class(const StringName &p_member_name, const GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_member) {
203 if (p_class->members_indices.has(p_member_name)) {
204 int index = p_class->members_indices[p_member_name];
205 const GDScriptParser::ClassNode::Member *member = &p_class->members[index];
206
207 if (member->type == GDScriptParser::ClassNode::Member::VARIABLE ||
208 member->type == GDScriptParser::ClassNode::Member::CONSTANT ||
209 member->type == GDScriptParser::ClassNode::Member::ENUM ||
210 member->type == GDScriptParser::ClassNode::Member::ENUM_VALUE ||
211 member->type == GDScriptParser::ClassNode::Member::CLASS ||
212 member->type == GDScriptParser::ClassNode::Member::SIGNAL) {
213 return true;
214 }
215 if (p_member->type != GDScriptParser::Node::FUNCTION && member->type == GDScriptParser::ClassNode::Member::FUNCTION) {
216 return true;
217 }
218 }
219
220 return false;
221}
222
223bool GDScriptAnalyzer::has_member_name_conflict_in_native_type(const StringName &p_member_name, const StringName &p_native_type_string) {
224 if (ClassDB::has_signal(p_native_type_string, p_member_name)) {
225 return true;
226 }
227 if (ClassDB::has_property(p_native_type_string, p_member_name)) {
228 return true;
229 }
230 if (ClassDB::has_integer_constant(p_native_type_string, p_member_name)) {
231 return true;
232 }
233 if (p_member_name == CoreStringNames::get_singleton()->_script) {
234 return true;
235 }
236
237 return false;
238}
239
240Error GDScriptAnalyzer::check_native_member_name_conflict(const StringName &p_member_name, const GDScriptParser::Node *p_member_node, const StringName &p_native_type_string) {
241 if (has_member_name_conflict_in_native_type(p_member_name, p_native_type_string)) {
242 push_error(vformat(R"(Member "%s" redefined (original in native class '%s'))", p_member_name, p_native_type_string), p_member_node);
243 return ERR_PARSE_ERROR;
244 }
245
246 if (class_exists(p_member_name)) {
247 push_error(vformat(R"(The member "%s" shadows a native class.)", p_member_name), p_member_node);
248 return ERR_PARSE_ERROR;
249 }
250
251 if (GDScriptParser::get_builtin_type(p_member_name) != Variant::VARIANT_MAX) {
252 push_error(vformat(R"(The member "%s" cannot have the same name as a builtin type.)", p_member_name), p_member_node);
253 return ERR_PARSE_ERROR;
254 }
255
256 return OK;
257}
258
259Error GDScriptAnalyzer::check_class_member_name_conflict(const GDScriptParser::ClassNode *p_class_node, const StringName &p_member_name, const GDScriptParser::Node *p_member_node) {
260 // TODO check outer classes for static members only
261 const GDScriptParser::DataType *current_data_type = &p_class_node->base_type;
262 while (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::CLASS) {
263 GDScriptParser::ClassNode *current_class_node = current_data_type->class_type;
264 if (has_member_name_conflict_in_script_class(p_member_name, current_class_node, p_member_node)) {
265 String parent_class_name = current_class_node->fqcn;
266 if (current_class_node->identifier != nullptr) {
267 parent_class_name = current_class_node->identifier->name;
268 }
269 push_error(vformat(R"(The member "%s" already exists in parent class %s.)", p_member_name, parent_class_name), p_member_node);
270 return ERR_PARSE_ERROR;
271 }
272 current_data_type = &current_class_node->base_type;
273 }
274
275 // No need for native class recursion because Node exposes all Object's properties.
276 if (current_data_type && current_data_type->kind == GDScriptParser::DataType::Kind::NATIVE) {
277 if (current_data_type->native_type != StringName()) {
278 return check_native_member_name_conflict(
279 p_member_name,
280 p_member_node,
281 current_data_type->native_type);
282 }
283 }
284
285 return OK;
286}
287
288void GDScriptAnalyzer::get_class_node_current_scope_classes(GDScriptParser::ClassNode *p_node, List<GDScriptParser::ClassNode *> *p_list) {
289 ERR_FAIL_NULL(p_node);
290 ERR_FAIL_NULL(p_list);
291
292 if (p_list->find(p_node) != nullptr) {
293 return;
294 }
295
296 p_list->push_back(p_node);
297
298 // TODO: Try to solve class inheritance if not yet resolving.
299
300 // Prioritize node base type over its outer class
301 if (p_node->base_type.class_type != nullptr) {
302 get_class_node_current_scope_classes(p_node->base_type.class_type, p_list);
303 }
304
305 if (p_node->outer != nullptr) {
306 get_class_node_current_scope_classes(p_node->outer, p_list);
307 }
308}
309
310Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source) {
311 if (p_source == nullptr && parser->has_class(p_class)) {
312 p_source = p_class;
313 }
314
315 if (p_class->base_type.is_resolving()) {
316 push_error(vformat(R"(Could not resolve class "%s": Cyclic reference.)", type_from_metatype(p_class->get_datatype()).to_string()), p_source);
317 return ERR_PARSE_ERROR;
318 }
319
320 if (!p_class->base_type.has_no_type()) {
321 // Already resolved.
322 return OK;
323 }
324
325 if (!parser->has_class(p_class)) {
326 String script_path = p_class->get_datatype().script_path;
327 Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
328 if (parser_ref.is_null()) {
329 push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
330 return ERR_PARSE_ERROR;
331 }
332
333 Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
334 if (err) {
335 push_error(vformat(R"(Could not parse script "%s": %s.)", script_path, error_names[err]), p_source);
336 return ERR_PARSE_ERROR;
337 }
338
339 ERR_FAIL_COND_V_MSG(!parser_ref->get_parser()->has_class(p_class), ERR_PARSE_ERROR, R"(Parser bug: Mismatched external parser.)");
340
341 GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
342 GDScriptParser *other_parser = parser_ref->get_parser();
343
344 int error_count = other_parser->errors.size();
345 other_analyzer->resolve_class_inheritance(p_class);
346 if (other_parser->errors.size() > error_count) {
347 push_error(vformat(R"(Could not resolve inheritance for class "%s".)", p_class->fqcn), p_source);
348 return ERR_PARSE_ERROR;
349 }
350
351 return OK;
352 }
353
354 GDScriptParser::ClassNode *previous_class = parser->current_class;
355 parser->current_class = p_class;
356
357 if (p_class->identifier) {
358 StringName class_name = p_class->identifier->name;
359 if (GDScriptParser::get_builtin_type(class_name) < Variant::VARIANT_MAX) {
360 push_error(vformat(R"(Class "%s" hides a built-in type.)", class_name), p_class->identifier);
361 } else if (class_exists(class_name)) {
362 push_error(vformat(R"(Class "%s" hides a native class.)", class_name), p_class->identifier);
363 } else if (ScriptServer::is_global_class(class_name) && (ScriptServer::get_global_class_path(class_name) != parser->script_path || p_class != parser->head)) {
364 push_error(vformat(R"(Class "%s" hides a global script class.)", class_name), p_class->identifier);
365 } else if (ProjectSettings::get_singleton()->has_autoload(class_name) && ProjectSettings::get_singleton()->get_autoload(class_name).is_singleton) {
366 push_error(vformat(R"(Class "%s" hides an autoload singleton.)", class_name), p_class->identifier);
367 }
368 }
369
370 GDScriptParser::DataType resolving_datatype;
371 resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
372 p_class->base_type = resolving_datatype;
373
374 // Set datatype for class.
375 GDScriptParser::DataType class_type;
376 class_type.is_constant = true;
377 class_type.is_meta_type = true;
378 class_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
379 class_type.kind = GDScriptParser::DataType::CLASS;
380 class_type.class_type = p_class;
381 class_type.script_path = parser->script_path;
382 class_type.builtin_type = Variant::OBJECT;
383 p_class->set_datatype(class_type);
384
385 GDScriptParser::DataType result;
386 if (!p_class->extends_used) {
387 result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
388 result.kind = GDScriptParser::DataType::NATIVE;
389 result.native_type = SNAME("RefCounted");
390 } else {
391 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
392
393 GDScriptParser::DataType base;
394
395 int extends_index = 0;
396
397 if (!p_class->extends_path.is_empty()) {
398 if (p_class->extends_path.is_relative_path()) {
399 p_class->extends_path = class_type.script_path.get_base_dir().path_join(p_class->extends_path).simplify_path();
400 }
401 Ref<GDScriptParserRef> ext_parser = get_parser_for(p_class->extends_path);
402 if (ext_parser.is_null()) {
403 push_error(vformat(R"(Could not resolve super class path "%s".)", p_class->extends_path), p_class);
404 return ERR_PARSE_ERROR;
405 }
406
407 Error err = ext_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
408 if (err != OK) {
409 push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", p_class->extends_path), p_class);
410 return err;
411 }
412
413 base = ext_parser->get_parser()->head->get_datatype();
414 } else {
415 if (p_class->extends.is_empty()) {
416 push_error("Could not resolve an empty super class path.", p_class);
417 return ERR_PARSE_ERROR;
418 }
419 GDScriptParser::IdentifierNode *id = p_class->extends[extends_index++];
420 const StringName &name = id->name;
421 base.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
422
423 if (ScriptServer::is_global_class(name)) {
424 String base_path = ScriptServer::get_global_class_path(name);
425
426 if (base_path == parser->script_path) {
427 base = parser->head->get_datatype();
428 } else {
429 Ref<GDScriptParserRef> base_parser = get_parser_for(base_path);
430 if (base_parser.is_null()) {
431 push_error(vformat(R"(Could not resolve super class "%s".)", name), id);
432 return ERR_PARSE_ERROR;
433 }
434
435 Error err = base_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
436 if (err != OK) {
437 push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), id);
438 return err;
439 }
440 base = base_parser->get_parser()->head->get_datatype();
441 }
442 } else if (ProjectSettings::get_singleton()->has_autoload(name) && ProjectSettings::get_singleton()->get_autoload(name).is_singleton) {
443 const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(name);
444 if (info.path.get_extension().to_lower() != GDScriptLanguage::get_singleton()->get_extension()) {
445 push_error(vformat(R"(Singleton %s is not a GDScript.)", info.name), id);
446 return ERR_PARSE_ERROR;
447 }
448
449 Ref<GDScriptParserRef> info_parser = get_parser_for(info.path);
450 if (info_parser.is_null()) {
451 push_error(vformat(R"(Could not parse singleton from "%s".)", info.path), id);
452 return ERR_PARSE_ERROR;
453 }
454
455 Error err = info_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
456 if (err != OK) {
457 push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), id);
458 return err;
459 }
460 base = info_parser->get_parser()->head->get_datatype();
461 } else if (class_exists(name)) {
462 base.kind = GDScriptParser::DataType::NATIVE;
463 base.native_type = name;
464 } else {
465 // Look for other classes in script.
466 bool found = false;
467 List<GDScriptParser::ClassNode *> script_classes;
468 get_class_node_current_scope_classes(p_class, &script_classes);
469 for (GDScriptParser::ClassNode *look_class : script_classes) {
470 if (look_class->identifier && look_class->identifier->name == name) {
471 if (!look_class->get_datatype().is_set()) {
472 Error err = resolve_class_inheritance(look_class, id);
473 if (err) {
474 return err;
475 }
476 }
477 base = look_class->get_datatype();
478 found = true;
479 break;
480 }
481 if (look_class->has_member(name)) {
482 resolve_class_member(look_class, name, id);
483 GDScriptParser::ClassNode::Member member = look_class->get_member(name);
484 GDScriptParser::DataType member_datatype = member.get_datatype();
485
486 switch (member.type) {
487 case GDScriptParser::ClassNode::Member::CLASS:
488 break; // OK.
489 case GDScriptParser::ClassNode::Member::CONSTANT:
490 if (member_datatype.kind != GDScriptParser::DataType::SCRIPT && member_datatype.kind != GDScriptParser::DataType::CLASS) {
491 push_error(vformat(R"(Constant "%s" is not a preloaded script or class.)", name), id);
492 return ERR_PARSE_ERROR;
493 }
494 break;
495 default:
496 push_error(vformat(R"(Cannot use %s "%s" in extends chain.)", member.get_type_name(), name), id);
497 return ERR_PARSE_ERROR;
498 }
499
500 base = member_datatype;
501 found = true;
502 break;
503 }
504 }
505
506 if (!found) {
507 push_error(vformat(R"(Could not find base class "%s".)", name), id);
508 return ERR_PARSE_ERROR;
509 }
510 }
511 }
512
513 for (int index = extends_index; index < p_class->extends.size(); index++) {
514 GDScriptParser::IdentifierNode *id = p_class->extends[index];
515
516 if (base.kind != GDScriptParser::DataType::CLASS) {
517 push_error(vformat(R"(Cannot get nested types for extension from non-GDScript type "%s".)", base.to_string()), id);
518 return ERR_PARSE_ERROR;
519 }
520
521 reduce_identifier_from_base(id, &base);
522 GDScriptParser::DataType id_type = id->get_datatype();
523
524 if (!id_type.is_set()) {
525 push_error(vformat(R"(Could not find nested type "%s".)", id->name), id);
526 return ERR_PARSE_ERROR;
527 } else if (id_type.kind != GDScriptParser::DataType::SCRIPT && id_type.kind != GDScriptParser::DataType::CLASS) {
528 push_error(vformat(R"(Identifier "%s" is not a preloaded script or class.)", id->name), id);
529 return ERR_PARSE_ERROR;
530 }
531
532 base = id_type;
533 }
534
535 result = base;
536 }
537
538 if (!result.is_set() || result.has_no_type()) {
539 // TODO: More specific error messages.
540 push_error(vformat(R"(Could not resolve inheritance for class "%s".)", p_class->identifier == nullptr ? "<main>" : p_class->identifier->name), p_class);
541 return ERR_PARSE_ERROR;
542 }
543
544 // Check for cyclic inheritance.
545 const GDScriptParser::ClassNode *base_class = result.class_type;
546 while (base_class) {
547 if (base_class->fqcn == p_class->fqcn) {
548 push_error("Cyclic inheritance.", p_class);
549 return ERR_PARSE_ERROR;
550 }
551 base_class = base_class->base_type.class_type;
552 }
553
554 p_class->base_type = result;
555 class_type.native_type = result.native_type;
556 p_class->set_datatype(class_type);
557
558 parser->current_class = previous_class;
559
560 return OK;
561}
562
563Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_class, bool p_recursive) {
564 Error err = resolve_class_inheritance(p_class);
565 if (err) {
566 return err;
567 }
568
569 if (p_recursive) {
570 for (int i = 0; i < p_class->members.size(); i++) {
571 if (p_class->members[i].type == GDScriptParser::ClassNode::Member::CLASS) {
572 err = resolve_class_inheritance(p_class->members[i].m_class, true);
573 if (err) {
574 return err;
575 }
576 }
577 }
578 }
579
580 return OK;
581}
582
583GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::TypeNode *p_type) {
584 GDScriptParser::DataType bad_type;
585 bad_type.kind = GDScriptParser::DataType::VARIANT;
586 bad_type.type_source = GDScriptParser::DataType::INFERRED;
587
588 if (p_type == nullptr) {
589 return bad_type;
590 }
591
592 if (p_type->get_datatype().is_resolving()) {
593 push_error(R"(Could not resolve datatype: Cyclic reference.)", p_type);
594 return bad_type;
595 }
596
597 if (!p_type->get_datatype().has_no_type()) {
598 return p_type->get_datatype();
599 }
600
601 GDScriptParser::DataType resolving_datatype;
602 resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
603 p_type->set_datatype(resolving_datatype);
604
605 GDScriptParser::DataType result;
606 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
607
608 if (p_type->type_chain.is_empty()) {
609 // void.
610 result.kind = GDScriptParser::DataType::BUILTIN;
611 result.builtin_type = Variant::NIL;
612 p_type->set_datatype(result);
613 return result;
614 }
615
616 const GDScriptParser::IdentifierNode *first_id = p_type->type_chain[0];
617 StringName first = first_id->name;
618 bool type_found = false;
619
620 if (first_id->suite && first_id->suite->has_local(first)) {
621 const GDScriptParser::SuiteNode::Local &local = first_id->suite->get_local(first);
622 if (local.type == GDScriptParser::SuiteNode::Local::CONSTANT) {
623 result = local.get_datatype();
624 if (!result.is_set()) {
625 // Don't try to resolve it as the constant can be declared below.
626 push_error(vformat(R"(Local constant "%s" is not resolved at this point.)", first), first_id);
627 return bad_type;
628 }
629 if (result.is_meta_type) {
630 type_found = true;
631 } else if (Ref<Script>(local.constant->initializer->reduced_value).is_valid()) {
632 Ref<GDScript> gdscript = local.constant->initializer->reduced_value;
633 if (gdscript.is_valid()) {
634 Ref<GDScriptParserRef> ref = get_parser_for(gdscript->get_script_path());
635 if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
636 push_error(vformat(R"(Could not parse script from "%s".)", gdscript->get_script_path()), first_id);
637 return bad_type;
638 }
639 result = ref->get_parser()->head->get_datatype();
640 } else {
641 result = make_script_meta_type(local.constant->initializer->reduced_value);
642 }
643 type_found = true;
644 } else {
645 push_error(vformat(R"(Local constant "%s" is not a valid type.)", first), first_id);
646 return bad_type;
647 }
648 } else {
649 push_error(vformat(R"(Local %s "%s" cannot be used as a type.)", local.get_name(), first), first_id);
650 return bad_type;
651 }
652 }
653
654 if (!type_found) {
655 if (first == SNAME("Variant")) {
656 if (p_type->type_chain.size() == 2) {
657 // May be nested enum.
658 StringName enum_name = p_type->type_chain[1]->name;
659 StringName qualified_name = String(first) + ENUM_SEPARATOR + String(p_type->type_chain[1]->name);
660 if (CoreConstants::is_global_enum(qualified_name)) {
661 result = make_global_enum_type(enum_name, first, true);
662 return result;
663 } else {
664 push_error(vformat(R"(Name "%s" is not a nested type of "Variant".)", enum_name), p_type->type_chain[1]);
665 return bad_type;
666 }
667 } else if (p_type->type_chain.size() > 2) {
668 push_error(R"(Variant only contains enum types, which do not have nested types.)", p_type->type_chain[2]);
669 return bad_type;
670 }
671 result.kind = GDScriptParser::DataType::VARIANT;
672 } else if (first == SNAME("Object")) {
673 // Object is treated like a native type, not a built-in.
674 result.kind = GDScriptParser::DataType::NATIVE;
675 result.builtin_type = Variant::OBJECT;
676 result.native_type = SNAME("Object");
677 } else if (GDScriptParser::get_builtin_type(first) < Variant::VARIANT_MAX) {
678 // Built-in types.
679 if (p_type->type_chain.size() > 1) {
680 push_error(R"(Built-in types don't contain nested types.)", p_type->type_chain[1]);
681 return bad_type;
682 }
683 result.kind = GDScriptParser::DataType::BUILTIN;
684 result.builtin_type = GDScriptParser::get_builtin_type(first);
685
686 if (result.builtin_type == Variant::ARRAY) {
687 GDScriptParser::DataType container_type = type_from_metatype(resolve_datatype(p_type->container_type));
688 if (container_type.kind != GDScriptParser::DataType::VARIANT) {
689 container_type.is_constant = false;
690 result.set_container_element_type(container_type);
691 }
692 }
693 } else if (class_exists(first)) {
694 // Native engine classes.
695 result.kind = GDScriptParser::DataType::NATIVE;
696 result.builtin_type = Variant::OBJECT;
697 result.native_type = first;
698 } else if (ScriptServer::is_global_class(first)) {
699 if (parser->script_path == ScriptServer::get_global_class_path(first)) {
700 result = parser->head->get_datatype();
701 } else {
702 String path = ScriptServer::get_global_class_path(first);
703 String ext = path.get_extension();
704 if (ext == GDScriptLanguage::get_singleton()->get_extension()) {
705 Ref<GDScriptParserRef> ref = get_parser_for(path);
706 if (!ref.is_valid() || ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
707 push_error(vformat(R"(Could not parse global class "%s" from "%s".)", first, ScriptServer::get_global_class_path(first)), p_type);
708 return bad_type;
709 }
710 result = ref->get_parser()->head->get_datatype();
711 } else {
712 result = make_script_meta_type(ResourceLoader::load(path, "Script"));
713 }
714 }
715 } else if (ProjectSettings::get_singleton()->has_autoload(first) && ProjectSettings::get_singleton()->get_autoload(first).is_singleton) {
716 const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(first);
717 Ref<GDScriptParserRef> ref = get_parser_for(autoload.path);
718 if (ref.is_null()) {
719 push_error(vformat(R"(The referenced autoload "%s" (from "%s") could not be loaded.)", first, autoload.path), p_type);
720 return bad_type;
721 }
722 if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
723 push_error(vformat(R"(Could not parse singleton "%s" from "%s".)", first, autoload.path), p_type);
724 return bad_type;
725 }
726 result = ref->get_parser()->head->get_datatype();
727 } else if (ClassDB::has_enum(parser->current_class->base_type.native_type, first)) {
728 // Native enum in current class.
729 result = make_native_enum_type(first, parser->current_class->base_type.native_type);
730 } else if (CoreConstants::is_global_enum(first)) {
731 if (p_type->type_chain.size() > 1) {
732 push_error(R"(Enums cannot contain nested types.)", p_type->type_chain[1]);
733 return bad_type;
734 }
735 result = make_global_enum_type(first, StringName());
736 } else {
737 // Classes in current scope.
738 List<GDScriptParser::ClassNode *> script_classes;
739 bool found = false;
740 get_class_node_current_scope_classes(parser->current_class, &script_classes);
741 for (GDScriptParser::ClassNode *script_class : script_classes) {
742 if (found) {
743 break;
744 }
745
746 if (script_class->identifier && script_class->identifier->name == first) {
747 result = script_class->get_datatype();
748 break;
749 }
750 if (script_class->members_indices.has(first)) {
751 resolve_class_member(script_class, first, p_type);
752
753 GDScriptParser::ClassNode::Member member = script_class->get_member(first);
754 switch (member.type) {
755 case GDScriptParser::ClassNode::Member::CLASS:
756 result = member.get_datatype();
757 found = true;
758 break;
759 case GDScriptParser::ClassNode::Member::ENUM:
760 result = member.get_datatype();
761 found = true;
762 break;
763 case GDScriptParser::ClassNode::Member::CONSTANT:
764 if (member.get_datatype().is_meta_type) {
765 result = member.get_datatype();
766 found = true;
767 break;
768 } else if (Ref<Script>(member.constant->initializer->reduced_value).is_valid()) {
769 Ref<GDScript> gdscript = member.constant->initializer->reduced_value;
770 if (gdscript.is_valid()) {
771 Ref<GDScriptParserRef> ref = get_parser_for(gdscript->get_script_path());
772 if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
773 push_error(vformat(R"(Could not parse script from "%s".)", gdscript->get_script_path()), p_type);
774 return bad_type;
775 }
776 result = ref->get_parser()->head->get_datatype();
777 } else {
778 result = make_script_meta_type(member.constant->initializer->reduced_value);
779 }
780 found = true;
781 break;
782 }
783 [[fallthrough]];
784 default:
785 push_error(vformat(R"("%s" is a %s but does not contain a type.)", first, member.get_type_name()), p_type);
786 return bad_type;
787 }
788 }
789 }
790 }
791 }
792
793 if (!result.is_set()) {
794 push_error(vformat(R"(Could not find type "%s" in the current scope.)", first), p_type);
795 return bad_type;
796 }
797
798 if (p_type->type_chain.size() > 1) {
799 if (result.kind == GDScriptParser::DataType::CLASS) {
800 for (int i = 1; i < p_type->type_chain.size(); i++) {
801 GDScriptParser::DataType base = result;
802 reduce_identifier_from_base(p_type->type_chain[i], &base);
803 result = p_type->type_chain[i]->get_datatype();
804 if (!result.is_set()) {
805 push_error(vformat(R"(Could not find type "%s" under base "%s".)", p_type->type_chain[i]->name, base.to_string()), p_type->type_chain[1]);
806 return bad_type;
807 } else if (!result.is_meta_type) {
808 push_error(vformat(R"(Member "%s" under base "%s" is not a valid type.)", p_type->type_chain[i]->name, base.to_string()), p_type->type_chain[1]);
809 return bad_type;
810 }
811 }
812 } else if (result.kind == GDScriptParser::DataType::NATIVE) {
813 // Only enums allowed for native.
814 if (ClassDB::has_enum(result.native_type, p_type->type_chain[1]->name)) {
815 if (p_type->type_chain.size() > 2) {
816 push_error(R"(Enums cannot contain nested types.)", p_type->type_chain[2]);
817 return bad_type;
818 } else {
819 result = make_native_enum_type(p_type->type_chain[1]->name, result.native_type);
820 }
821 } else {
822 push_error(vformat(R"(Could not find type "%s" in "%s".)", p_type->type_chain[1]->name, first), p_type->type_chain[1]);
823 return bad_type;
824 }
825 } else {
826 push_error(vformat(R"(Could not find nested type "%s" under base "%s".)", p_type->type_chain[1]->name, result.to_string()), p_type->type_chain[1]);
827 return bad_type;
828 }
829 }
830
831 if (result.builtin_type != Variant::ARRAY && p_type->container_type != nullptr) {
832 push_error("Only arrays can specify the collection element type.", p_type);
833 }
834
835 p_type->set_datatype(result);
836 return result;
837}
838
839void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, StringName p_name, const GDScriptParser::Node *p_source) {
840 ERR_FAIL_COND(!p_class->has_member(p_name));
841 resolve_class_member(p_class, p_class->members_indices[p_name], p_source);
842}
843
844void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class, int p_index, const GDScriptParser::Node *p_source) {
845 ERR_FAIL_INDEX(p_index, p_class->members.size());
846
847 GDScriptParser::ClassNode::Member &member = p_class->members.write[p_index];
848 if (p_source == nullptr && parser->has_class(p_class)) {
849 p_source = member.get_source_node();
850 }
851
852 if (member.get_datatype().is_resolving()) {
853 push_error(vformat(R"(Could not resolve member "%s": Cyclic reference.)", member.get_name()), p_source);
854 return;
855 }
856
857 if (member.get_datatype().is_set()) {
858 return;
859 }
860
861 if (!parser->has_class(p_class)) {
862 String script_path = p_class->get_datatype().script_path;
863 Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
864 if (parser_ref.is_null()) {
865 push_error(vformat(R"(Could not find script "%s" (While resolving "%s").)", script_path, member.get_name()), p_source);
866 return;
867 }
868
869 Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
870 if (err) {
871 push_error(vformat(R"(Could not resolve script "%s": %s (While resolving "%s").)", script_path, error_names[err], member.get_name()), p_source);
872 return;
873 }
874
875 ERR_FAIL_COND_MSG(!parser_ref->get_parser()->has_class(p_class), R"(Parser bug: Mismatched external parser.)");
876
877 GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
878 GDScriptParser *other_parser = parser_ref->get_parser();
879
880 int error_count = other_parser->errors.size();
881 other_analyzer->resolve_class_member(p_class, p_index);
882 if (other_parser->errors.size() > error_count) {
883 push_error(vformat(R"(Could not resolve member "%s".)", member.get_name()), p_source);
884 }
885
886 return;
887 }
888
889 // If it's already resolving, that's ok.
890 if (!p_class->base_type.is_resolving()) {
891 Error err = resolve_class_inheritance(p_class);
892 if (err) {
893 return;
894 }
895 }
896
897 GDScriptParser::ClassNode *previous_class = parser->current_class;
898 parser->current_class = p_class;
899
900 GDScriptParser::DataType resolving_datatype;
901 resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
902
903 {
904#ifdef DEBUG_ENABLED
905 HashSet<GDScriptWarning::Code> previously_ignored_warnings = parser->ignored_warnings;
906 GDScriptParser::Node *member_node = member.get_source_node();
907 if (member_node && member_node->type != GDScriptParser::Node::ANNOTATION) {
908 // Apply @warning_ignore annotations before resolving member.
909 for (GDScriptParser::AnnotationNode *&E : member_node->annotations) {
910 if (E->name == SNAME("@warning_ignore")) {
911 resolve_annotation(E);
912 E->apply(parser, member.variable);
913 }
914 }
915 for (GDScriptWarning::Code ignored_warning : member_node->ignored_warnings) {
916 parser->ignored_warnings.insert(ignored_warning);
917 }
918 }
919#endif
920 switch (member.type) {
921 case GDScriptParser::ClassNode::Member::VARIABLE: {
922 bool previous_static_context = static_context;
923 static_context = member.variable->is_static;
924
925 check_class_member_name_conflict(p_class, member.variable->identifier->name, member.variable);
926
927 member.variable->set_datatype(resolving_datatype);
928 resolve_variable(member.variable, false);
929 resolve_pending_lambda_bodies();
930
931 // Apply annotations.
932 for (GDScriptParser::AnnotationNode *&E : member.variable->annotations) {
933 if (E->name != SNAME("@warning_ignore")) {
934 resolve_annotation(E);
935 E->apply(parser, member.variable);
936 }
937 }
938
939 static_context = previous_static_context;
940
941#ifdef DEBUG_ENABLED
942 if (member.variable->exported && member.variable->onready) {
943 parser->push_warning(member.variable, GDScriptWarning::ONREADY_WITH_EXPORT);
944 }
945 if (member.variable->initializer) {
946 // Check if it is call to get_node() on self (using shorthand $ or not), so we can check if @onready is needed.
947 // This could be improved by traversing the expression fully and checking the presence of get_node at any level.
948 if (!member.variable->is_static && !member.variable->onready && member.variable->initializer && (member.variable->initializer->type == GDScriptParser::Node::GET_NODE || member.variable->initializer->type == GDScriptParser::Node::CALL || member.variable->initializer->type == GDScriptParser::Node::CAST)) {
949 GDScriptParser::Node *expr = member.variable->initializer;
950 if (expr->type == GDScriptParser::Node::CAST) {
951 expr = static_cast<GDScriptParser::CastNode *>(expr)->operand;
952 }
953 bool is_get_node = expr->type == GDScriptParser::Node::GET_NODE;
954 bool is_using_shorthand = is_get_node;
955 if (!is_get_node && expr->type == GDScriptParser::Node::CALL) {
956 is_using_shorthand = false;
957 GDScriptParser::CallNode *call = static_cast<GDScriptParser::CallNode *>(expr);
958 if (call->function_name == SNAME("get_node")) {
959 switch (call->get_callee_type()) {
960 case GDScriptParser::Node::IDENTIFIER: {
961 is_get_node = true;
962 } break;
963 case GDScriptParser::Node::SUBSCRIPT: {
964 GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(call->callee);
965 is_get_node = subscript->is_attribute && subscript->base->type == GDScriptParser::Node::SELF;
966 } break;
967 default:
968 break;
969 }
970 }
971 }
972 if (is_get_node) {
973 parser->push_warning(member.variable, GDScriptWarning::GET_NODE_DEFAULT_WITHOUT_ONREADY, is_using_shorthand ? "$" : "get_node()");
974 }
975 }
976 }
977#endif
978 } break;
979 case GDScriptParser::ClassNode::Member::CONSTANT: {
980 check_class_member_name_conflict(p_class, member.constant->identifier->name, member.constant);
981 member.constant->set_datatype(resolving_datatype);
982 resolve_constant(member.constant, false);
983
984 // Apply annotations.
985 for (GDScriptParser::AnnotationNode *&E : member.constant->annotations) {
986 resolve_annotation(E);
987 E->apply(parser, member.constant);
988 }
989 } break;
990 case GDScriptParser::ClassNode::Member::SIGNAL: {
991 check_class_member_name_conflict(p_class, member.signal->identifier->name, member.signal);
992
993 member.signal->set_datatype(resolving_datatype);
994
995 // This is the _only_ way to declare a signal. Therefore, we can generate its
996 // MethodInfo inline so it's a tiny bit more efficient.
997 MethodInfo mi = MethodInfo(member.signal->identifier->name);
998
999 for (int j = 0; j < member.signal->parameters.size(); j++) {
1000 GDScriptParser::ParameterNode *param = member.signal->parameters[j];
1001 GDScriptParser::DataType param_type = type_from_metatype(resolve_datatype(param->datatype_specifier));
1002 param->set_datatype(param_type);
1003#ifdef DEBUG_ENABLED
1004 if (param->datatype_specifier == nullptr) {
1005 parser->push_warning(param, GDScriptWarning::UNTYPED_DECLARATION, "Parameter", param->identifier->name);
1006 }
1007#endif
1008 mi.arguments.push_back(param_type.to_property_info(param->identifier->name));
1009 // Signals do not support parameter default values.
1010 }
1011 member.signal->set_datatype(make_signal_type(mi));
1012 member.signal->method_info = mi;
1013
1014 // Apply annotations.
1015 for (GDScriptParser::AnnotationNode *&E : member.signal->annotations) {
1016 resolve_annotation(E);
1017 E->apply(parser, member.signal);
1018 }
1019 } break;
1020 case GDScriptParser::ClassNode::Member::ENUM: {
1021 check_class_member_name_conflict(p_class, member.m_enum->identifier->name, member.m_enum);
1022
1023 member.m_enum->set_datatype(resolving_datatype);
1024 GDScriptParser::DataType enum_type = make_enum_type(member.m_enum->identifier->name, p_class->fqcn, true);
1025
1026 const GDScriptParser::EnumNode *prev_enum = current_enum;
1027 current_enum = member.m_enum;
1028
1029 Dictionary dictionary;
1030 for (int j = 0; j < member.m_enum->values.size(); j++) {
1031 GDScriptParser::EnumNode::Value &element = member.m_enum->values.write[j];
1032
1033 if (element.custom_value) {
1034 reduce_expression(element.custom_value);
1035 if (!element.custom_value->is_constant) {
1036 push_error(R"(Enum values must be constant.)", element.custom_value);
1037 } else if (element.custom_value->reduced_value.get_type() != Variant::INT) {
1038 push_error(R"(Enum values must be integers.)", element.custom_value);
1039 } else {
1040 element.value = element.custom_value->reduced_value;
1041 element.resolved = true;
1042 }
1043 } else {
1044 if (element.index > 0) {
1045 element.value = element.parent_enum->values[element.index - 1].value + 1;
1046 } else {
1047 element.value = 0;
1048 }
1049 element.resolved = true;
1050 }
1051
1052 enum_type.enum_values[element.identifier->name] = element.value;
1053 dictionary[String(element.identifier->name)] = element.value;
1054 }
1055
1056 current_enum = prev_enum;
1057
1058 dictionary.make_read_only();
1059 member.m_enum->set_datatype(enum_type);
1060 member.m_enum->dictionary = dictionary;
1061
1062 // Apply annotations.
1063 for (GDScriptParser::AnnotationNode *&E : member.m_enum->annotations) {
1064 resolve_annotation(E);
1065 E->apply(parser, member.m_enum);
1066 }
1067 } break;
1068 case GDScriptParser::ClassNode::Member::FUNCTION:
1069 for (GDScriptParser::AnnotationNode *&E : member.function->annotations) {
1070 resolve_annotation(E);
1071 E->apply(parser, member.function);
1072 }
1073 resolve_function_signature(member.function, p_source);
1074 break;
1075 case GDScriptParser::ClassNode::Member::ENUM_VALUE: {
1076 member.enum_value.identifier->set_datatype(resolving_datatype);
1077
1078 if (member.enum_value.custom_value) {
1079 check_class_member_name_conflict(p_class, member.enum_value.identifier->name, member.enum_value.custom_value);
1080
1081 const GDScriptParser::EnumNode *prev_enum = current_enum;
1082 current_enum = member.enum_value.parent_enum;
1083 reduce_expression(member.enum_value.custom_value);
1084 current_enum = prev_enum;
1085
1086 if (!member.enum_value.custom_value->is_constant) {
1087 push_error(R"(Enum values must be constant.)", member.enum_value.custom_value);
1088 } else if (member.enum_value.custom_value->reduced_value.get_type() != Variant::INT) {
1089 push_error(R"(Enum values must be integers.)", member.enum_value.custom_value);
1090 } else {
1091 member.enum_value.value = member.enum_value.custom_value->reduced_value;
1092 member.enum_value.resolved = true;
1093 }
1094 } else {
1095 check_class_member_name_conflict(p_class, member.enum_value.identifier->name, member.enum_value.parent_enum);
1096
1097 if (member.enum_value.index > 0) {
1098 const GDScriptParser::EnumNode::Value &prev_value = member.enum_value.parent_enum->values[member.enum_value.index - 1];
1099 resolve_class_member(p_class, prev_value.identifier->name, member.enum_value.identifier);
1100 member.enum_value.value = prev_value.value + 1;
1101 } else {
1102 member.enum_value.value = 0;
1103 }
1104 member.enum_value.resolved = true;
1105 }
1106
1107 // Also update the original references.
1108 member.enum_value.parent_enum->values.set(member.enum_value.index, member.enum_value);
1109
1110 member.enum_value.identifier->set_datatype(make_enum_type(UNNAMED_ENUM, p_class->fqcn, false));
1111 } break;
1112 case GDScriptParser::ClassNode::Member::CLASS:
1113 check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class);
1114 // If it's already resolving, that's ok.
1115 if (!member.m_class->base_type.is_resolving()) {
1116 resolve_class_inheritance(member.m_class, p_source);
1117 }
1118 break;
1119 case GDScriptParser::ClassNode::Member::GROUP:
1120 // No-op, but needed to silence warnings.
1121 break;
1122 case GDScriptParser::ClassNode::Member::UNDEFINED:
1123 ERR_PRINT("Trying to resolve undefined member.");
1124 break;
1125 }
1126#ifdef DEBUG_ENABLED
1127 parser->ignored_warnings = previously_ignored_warnings;
1128#endif
1129 }
1130
1131 parser->current_class = previous_class;
1132}
1133
1134void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source) {
1135 if (p_source == nullptr && parser->has_class(p_class)) {
1136 p_source = p_class;
1137 }
1138
1139#ifdef DEBUG_ENABLED
1140 bool has_static_data = p_class->has_static_data;
1141#endif
1142
1143 if (!p_class->resolved_interface) {
1144 if (!parser->has_class(p_class)) {
1145 String script_path = p_class->get_datatype().script_path;
1146 Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
1147 if (parser_ref.is_null()) {
1148 push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
1149 return;
1150 }
1151
1152 Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
1153 if (err) {
1154 push_error(vformat(R"(Could not resolve script "%s": %s.)", script_path, error_names[err]), p_source);
1155 return;
1156 }
1157
1158 ERR_FAIL_COND_MSG(!parser_ref->get_parser()->has_class(p_class), R"(Parser bug: Mismatched external parser.)");
1159
1160 GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
1161 GDScriptParser *other_parser = parser_ref->get_parser();
1162
1163 int error_count = other_parser->errors.size();
1164 other_analyzer->resolve_class_interface(p_class);
1165 if (other_parser->errors.size() > error_count) {
1166 push_error(vformat(R"(Could not resolve class "%s".)", p_class->fqcn), p_source);
1167 }
1168
1169 return;
1170 }
1171 p_class->resolved_interface = true;
1172
1173 if (resolve_class_inheritance(p_class) != OK) {
1174 return;
1175 }
1176
1177 GDScriptParser::DataType base_type = p_class->base_type;
1178 if (base_type.kind == GDScriptParser::DataType::CLASS) {
1179 GDScriptParser::ClassNode *base_class = base_type.class_type;
1180 resolve_class_interface(base_class, p_class);
1181 }
1182
1183 for (int i = 0; i < p_class->members.size(); i++) {
1184 resolve_class_member(p_class, i);
1185
1186#ifdef DEBUG_ENABLED
1187 if (!has_static_data) {
1188 GDScriptParser::ClassNode::Member member = p_class->members[i];
1189 if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
1190 has_static_data = member.m_class->has_static_data;
1191 }
1192 }
1193#endif
1194 }
1195
1196#ifdef DEBUG_ENABLED
1197 if (!has_static_data && p_class->annotated_static_unload) {
1198 GDScriptParser::Node *static_unload = nullptr;
1199 for (GDScriptParser::AnnotationNode *node : p_class->annotations) {
1200 if (node->name == "@static_unload") {
1201 static_unload = node;
1202 break;
1203 }
1204 }
1205 parser->push_warning(static_unload ? static_unload : p_class, GDScriptWarning::REDUNDANT_STATIC_UNLOAD);
1206 }
1207#endif
1208 }
1209}
1210
1211void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_class, bool p_recursive) {
1212 resolve_class_interface(p_class);
1213
1214 if (p_recursive) {
1215 for (int i = 0; i < p_class->members.size(); i++) {
1216 GDScriptParser::ClassNode::Member member = p_class->members[i];
1217 if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
1218 resolve_class_interface(member.m_class, true);
1219 }
1220 }
1221 }
1222}
1223
1224void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class, const GDScriptParser::Node *p_source) {
1225 if (p_source == nullptr && parser->has_class(p_class)) {
1226 p_source = p_class;
1227 }
1228
1229 if (p_class->resolved_body) {
1230 return;
1231 }
1232
1233 if (!parser->has_class(p_class)) {
1234 String script_path = p_class->get_datatype().script_path;
1235 Ref<GDScriptParserRef> parser_ref = get_parser_for(script_path);
1236 if (parser_ref.is_null()) {
1237 push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
1238 return;
1239 }
1240
1241 Error err = parser_ref->raise_status(GDScriptParserRef::PARSED);
1242 if (err) {
1243 push_error(vformat(R"(Could not resolve script "%s": %s.)", script_path, error_names[err]), p_source);
1244 return;
1245 }
1246
1247 ERR_FAIL_COND_MSG(!parser_ref->get_parser()->has_class(p_class), R"(Parser bug: Mismatched external parser.)");
1248
1249 GDScriptAnalyzer *other_analyzer = parser_ref->get_analyzer();
1250 GDScriptParser *other_parser = parser_ref->get_parser();
1251
1252 int error_count = other_parser->errors.size();
1253 other_analyzer->resolve_class_body(p_class);
1254 if (other_parser->errors.size() > error_count) {
1255 push_error(vformat(R"(Could not resolve class "%s".)", p_class->fqcn), p_source);
1256 }
1257
1258 return;
1259 }
1260
1261 p_class->resolved_body = true;
1262
1263 GDScriptParser::ClassNode *previous_class = parser->current_class;
1264 parser->current_class = p_class;
1265
1266 resolve_class_interface(p_class, p_source);
1267
1268 GDScriptParser::DataType base_type = p_class->base_type;
1269 if (base_type.kind == GDScriptParser::DataType::CLASS) {
1270 GDScriptParser::ClassNode *base_class = base_type.class_type;
1271 resolve_class_body(base_class, p_class);
1272 }
1273
1274 // Do functions, properties, and groups now.
1275 for (int i = 0; i < p_class->members.size(); i++) {
1276 GDScriptParser::ClassNode::Member member = p_class->members[i];
1277 if (member.type == GDScriptParser::ClassNode::Member::FUNCTION) {
1278 // Apply annotations.
1279 for (GDScriptParser::AnnotationNode *&E : member.function->annotations) {
1280 resolve_annotation(E);
1281 E->apply(parser, member.function);
1282 }
1283 resolve_function_body(member.function);
1284 } else if (member.type == GDScriptParser::ClassNode::Member::VARIABLE && member.variable->property != GDScriptParser::VariableNode::PROP_NONE) {
1285 if (member.variable->property == GDScriptParser::VariableNode::PROP_INLINE) {
1286 if (member.variable->getter != nullptr) {
1287 member.variable->getter->return_type = member.variable->datatype_specifier;
1288 member.variable->getter->set_datatype(member.get_datatype());
1289
1290 resolve_function_body(member.variable->getter);
1291 }
1292 if (member.variable->setter != nullptr) {
1293 ERR_CONTINUE(member.variable->setter->parameters.is_empty());
1294 member.variable->setter->parameters[0]->datatype_specifier = member.variable->datatype_specifier;
1295 member.variable->setter->parameters[0]->set_datatype(member.get_datatype());
1296
1297 resolve_function_body(member.variable->setter);
1298 }
1299 }
1300 } else if (member.type == GDScriptParser::ClassNode::Member::GROUP) {
1301 // Apply annotation (`@export_{category,group,subgroup}`).
1302 resolve_annotation(member.annotation);
1303 member.annotation->apply(parser, nullptr);
1304 }
1305 }
1306
1307 // Check unused variables and datatypes of property getters and setters.
1308 for (int i = 0; i < p_class->members.size(); i++) {
1309 GDScriptParser::ClassNode::Member member = p_class->members[i];
1310 if (member.type == GDScriptParser::ClassNode::Member::VARIABLE) {
1311#ifdef DEBUG_ENABLED
1312 HashSet<GDScriptWarning::Code> previously_ignored_warnings = parser->ignored_warnings;
1313 for (GDScriptWarning::Code ignored_warning : member.variable->ignored_warnings) {
1314 parser->ignored_warnings.insert(ignored_warning);
1315 }
1316 if (member.variable->usages == 0 && String(member.variable->identifier->name).begins_with("_")) {
1317 parser->push_warning(member.variable->identifier, GDScriptWarning::UNUSED_PRIVATE_CLASS_VARIABLE, member.variable->identifier->name);
1318 }
1319#endif
1320
1321 if (member.variable->property == GDScriptParser::VariableNode::PROP_SETGET) {
1322 GDScriptParser::FunctionNode *getter_function = nullptr;
1323 GDScriptParser::FunctionNode *setter_function = nullptr;
1324
1325 bool has_valid_getter = false;
1326 bool has_valid_setter = false;
1327
1328 if (member.variable->getter_pointer != nullptr) {
1329 if (p_class->has_function(member.variable->getter_pointer->name)) {
1330 getter_function = p_class->get_member(member.variable->getter_pointer->name).function;
1331 }
1332
1333 if (getter_function == nullptr) {
1334 push_error(vformat(R"(Getter "%s" not found.)", member.variable->getter_pointer->name), member.variable);
1335 } else {
1336 GDScriptParser::DataType return_datatype = getter_function->datatype;
1337 if (getter_function->return_type != nullptr) {
1338 return_datatype = getter_function->return_type->datatype;
1339 return_datatype.is_meta_type = false;
1340 }
1341
1342 if (getter_function->parameters.size() != 0 || return_datatype.has_no_type()) {
1343 push_error(vformat(R"(Function "%s" cannot be used as getter because of its signature.)", getter_function->identifier->name), member.variable);
1344 } else if (!is_type_compatible(member.variable->datatype, return_datatype, true)) {
1345 push_error(vformat(R"(Function with return type "%s" cannot be used as getter for a property of type "%s".)", return_datatype.to_string(), member.variable->datatype.to_string()), member.variable);
1346
1347 } else {
1348 has_valid_getter = true;
1349#ifdef DEBUG_ENABLED
1350 if (member.variable->datatype.builtin_type == Variant::INT && return_datatype.builtin_type == Variant::FLOAT) {
1351 parser->push_warning(member.variable, GDScriptWarning::NARROWING_CONVERSION);
1352 }
1353#endif
1354 }
1355 }
1356 }
1357
1358 if (member.variable->setter_pointer != nullptr) {
1359 if (p_class->has_function(member.variable->setter_pointer->name)) {
1360 setter_function = p_class->get_member(member.variable->setter_pointer->name).function;
1361 }
1362
1363 if (setter_function == nullptr) {
1364 push_error(vformat(R"(Setter "%s" not found.)", member.variable->setter_pointer->name), member.variable);
1365
1366 } else if (setter_function->parameters.size() != 1) {
1367 push_error(vformat(R"(Function "%s" cannot be used as setter because of its signature.)", setter_function->identifier->name), member.variable);
1368
1369 } else if (!is_type_compatible(member.variable->datatype, setter_function->parameters[0]->datatype, true)) {
1370 push_error(vformat(R"(Function with argument type "%s" cannot be used as setter for a property of type "%s".)", setter_function->parameters[0]->datatype.to_string(), member.variable->datatype.to_string()), member.variable);
1371
1372 } else {
1373 has_valid_setter = true;
1374
1375#ifdef DEBUG_ENABLED
1376 if (member.variable->datatype.builtin_type == Variant::FLOAT && setter_function->parameters[0]->datatype.builtin_type == Variant::INT) {
1377 parser->push_warning(member.variable, GDScriptWarning::NARROWING_CONVERSION);
1378 }
1379#endif
1380 }
1381 }
1382
1383 if (member.variable->datatype.is_variant() && has_valid_getter && has_valid_setter) {
1384 if (!is_type_compatible(getter_function->datatype, setter_function->parameters[0]->datatype, true)) {
1385 push_error(vformat(R"(Getter with type "%s" cannot be used along with setter of type "%s".)", getter_function->datatype.to_string(), setter_function->parameters[0]->datatype.to_string()), member.variable);
1386 }
1387 }
1388 }
1389
1390#ifdef DEBUG_ENABLED
1391 parser->ignored_warnings = previously_ignored_warnings;
1392#endif // DEBUG_ENABLED
1393 }
1394 }
1395
1396 if (!pending_body_resolution_lambdas.is_empty()) {
1397 ERR_PRINT("GDScript bug (please report): Not all pending lambda bodies were resolved in time.");
1398 resolve_pending_lambda_bodies();
1399 }
1400
1401 parser->current_class = previous_class;
1402}
1403
1404void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class, bool p_recursive) {
1405 resolve_class_body(p_class);
1406
1407 if (p_recursive) {
1408 for (int i = 0; i < p_class->members.size(); i++) {
1409 GDScriptParser::ClassNode::Member member = p_class->members[i];
1410 if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
1411 resolve_class_body(member.m_class, true);
1412 }
1413 }
1414 }
1415}
1416
1417void GDScriptAnalyzer::resolve_node(GDScriptParser::Node *p_node, bool p_is_root) {
1418 ERR_FAIL_COND_MSG(p_node == nullptr, "Trying to resolve type of a null node.");
1419
1420 switch (p_node->type) {
1421 case GDScriptParser::Node::NONE:
1422 break; // Unreachable.
1423 case GDScriptParser::Node::CLASS:
1424 if (OK == resolve_class_inheritance(static_cast<GDScriptParser::ClassNode *>(p_node), true)) {
1425 resolve_class_interface(static_cast<GDScriptParser::ClassNode *>(p_node), true);
1426 resolve_class_body(static_cast<GDScriptParser::ClassNode *>(p_node), true);
1427 }
1428 break;
1429 case GDScriptParser::Node::CONSTANT:
1430 resolve_constant(static_cast<GDScriptParser::ConstantNode *>(p_node), true);
1431 break;
1432 case GDScriptParser::Node::FOR:
1433 resolve_for(static_cast<GDScriptParser::ForNode *>(p_node));
1434 break;
1435 case GDScriptParser::Node::IF:
1436 resolve_if(static_cast<GDScriptParser::IfNode *>(p_node));
1437 break;
1438 case GDScriptParser::Node::SUITE:
1439 resolve_suite(static_cast<GDScriptParser::SuiteNode *>(p_node));
1440 break;
1441 case GDScriptParser::Node::VARIABLE:
1442 resolve_variable(static_cast<GDScriptParser::VariableNode *>(p_node), true);
1443 break;
1444 case GDScriptParser::Node::WHILE:
1445 resolve_while(static_cast<GDScriptParser::WhileNode *>(p_node));
1446 break;
1447 case GDScriptParser::Node::ANNOTATION:
1448 resolve_annotation(static_cast<GDScriptParser::AnnotationNode *>(p_node));
1449 break;
1450 case GDScriptParser::Node::ASSERT:
1451 resolve_assert(static_cast<GDScriptParser::AssertNode *>(p_node));
1452 break;
1453 case GDScriptParser::Node::MATCH:
1454 resolve_match(static_cast<GDScriptParser::MatchNode *>(p_node));
1455 break;
1456 case GDScriptParser::Node::MATCH_BRANCH:
1457 resolve_match_branch(static_cast<GDScriptParser::MatchBranchNode *>(p_node), nullptr);
1458 break;
1459 case GDScriptParser::Node::PARAMETER:
1460 resolve_parameter(static_cast<GDScriptParser::ParameterNode *>(p_node));
1461 break;
1462 case GDScriptParser::Node::PATTERN:
1463 resolve_match_pattern(static_cast<GDScriptParser::PatternNode *>(p_node), nullptr);
1464 break;
1465 case GDScriptParser::Node::RETURN:
1466 resolve_return(static_cast<GDScriptParser::ReturnNode *>(p_node));
1467 break;
1468 case GDScriptParser::Node::TYPE:
1469 resolve_datatype(static_cast<GDScriptParser::TypeNode *>(p_node));
1470 break;
1471 // Resolving expression is the same as reducing them.
1472 case GDScriptParser::Node::ARRAY:
1473 case GDScriptParser::Node::ASSIGNMENT:
1474 case GDScriptParser::Node::AWAIT:
1475 case GDScriptParser::Node::BINARY_OPERATOR:
1476 case GDScriptParser::Node::CALL:
1477 case GDScriptParser::Node::CAST:
1478 case GDScriptParser::Node::DICTIONARY:
1479 case GDScriptParser::Node::GET_NODE:
1480 case GDScriptParser::Node::IDENTIFIER:
1481 case GDScriptParser::Node::LAMBDA:
1482 case GDScriptParser::Node::LITERAL:
1483 case GDScriptParser::Node::PRELOAD:
1484 case GDScriptParser::Node::SELF:
1485 case GDScriptParser::Node::SUBSCRIPT:
1486 case GDScriptParser::Node::TERNARY_OPERATOR:
1487 case GDScriptParser::Node::TYPE_TEST:
1488 case GDScriptParser::Node::UNARY_OPERATOR:
1489 reduce_expression(static_cast<GDScriptParser::ExpressionNode *>(p_node), p_is_root);
1490 break;
1491 case GDScriptParser::Node::BREAK:
1492 case GDScriptParser::Node::BREAKPOINT:
1493 case GDScriptParser::Node::CONTINUE:
1494 case GDScriptParser::Node::ENUM:
1495 case GDScriptParser::Node::FUNCTION:
1496 case GDScriptParser::Node::PASS:
1497 case GDScriptParser::Node::SIGNAL:
1498 // Nothing to do.
1499 break;
1500 }
1501}
1502
1503void GDScriptAnalyzer::resolve_annotation(GDScriptParser::AnnotationNode *p_annotation) {
1504 ERR_FAIL_COND_MSG(!parser->valid_annotations.has(p_annotation->name), vformat(R"(Annotation "%s" not found to validate.)", p_annotation->name));
1505
1506 if (p_annotation->is_resolved) {
1507 return;
1508 }
1509 p_annotation->is_resolved = true;
1510
1511 const MethodInfo &annotation_info = parser->valid_annotations[p_annotation->name].info;
1512
1513 const List<PropertyInfo>::Element *E = annotation_info.arguments.front();
1514 for (int i = 0; i < p_annotation->arguments.size(); i++) {
1515 GDScriptParser::ExpressionNode *argument = p_annotation->arguments[i];
1516 const PropertyInfo &argument_info = E->get();
1517
1518 if (E->next() != nullptr) {
1519 E = E->next();
1520 }
1521
1522 reduce_expression(argument);
1523
1524 if (!argument->is_constant) {
1525 push_error(vformat(R"(Argument %d of annotation "%s" isn't a constant expression.)", i + 1, p_annotation->name), argument);
1526 return;
1527 }
1528
1529 Variant value = argument->reduced_value;
1530
1531 if (value.get_type() != argument_info.type) {
1532#ifdef DEBUG_ENABLED
1533 if (argument_info.type == Variant::INT && value.get_type() == Variant::FLOAT) {
1534 parser->push_warning(argument, GDScriptWarning::NARROWING_CONVERSION);
1535 }
1536#endif
1537
1538 if (!Variant::can_convert_strict(value.get_type(), argument_info.type)) {
1539 push_error(vformat(R"(Invalid argument for annotation "%s": argument %d should be "%s" but is "%s".)", p_annotation->name, i + 1, Variant::get_type_name(argument_info.type), argument->get_datatype().to_string()), argument);
1540 return;
1541 }
1542
1543 Variant converted_to;
1544 const Variant *converted_from = &value;
1545 Callable::CallError call_error;
1546 Variant::construct(argument_info.type, converted_to, &converted_from, 1, call_error);
1547
1548 if (call_error.error != Callable::CallError::CALL_OK) {
1549 push_error(vformat(R"(Cannot convert argument %d of annotation "%s" from "%s" to "%s".)", i + 1, p_annotation->name, Variant::get_type_name(value.get_type()), Variant::get_type_name(argument_info.type)), argument);
1550 return;
1551 }
1552
1553 value = converted_to;
1554 }
1555
1556 p_annotation->resolved_arguments.push_back(value);
1557 }
1558}
1559
1560void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *p_function, const GDScriptParser::Node *p_source, bool p_is_lambda) {
1561 if (p_source == nullptr) {
1562 p_source = p_function;
1563 }
1564
1565 StringName function_name = p_function->identifier != nullptr ? p_function->identifier->name : StringName();
1566
1567 if (p_function->get_datatype().is_resolving()) {
1568 push_error(vformat(R"(Could not resolve function "%s": Cyclic reference.)", function_name), p_source);
1569 return;
1570 }
1571
1572 if (p_function->resolved_signature) {
1573 return;
1574 }
1575 p_function->resolved_signature = true;
1576
1577#ifdef DEBUG_ENABLED
1578 HashSet<GDScriptWarning::Code> previously_ignored_warnings = parser->ignored_warnings;
1579 for (GDScriptWarning::Code ignored_warning : p_function->ignored_warnings) {
1580 parser->ignored_warnings.insert(ignored_warning);
1581 }
1582#endif
1583
1584 GDScriptParser::FunctionNode *previous_function = parser->current_function;
1585 parser->current_function = p_function;
1586 bool previous_static_context = static_context;
1587 static_context = p_function->is_static;
1588
1589 GDScriptParser::DataType prev_datatype = p_function->get_datatype();
1590
1591 GDScriptParser::DataType resolving_datatype;
1592 resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
1593 p_function->set_datatype(resolving_datatype);
1594
1595#ifdef TOOLS_ENABLED
1596 int default_value_count = 0;
1597#endif // TOOLS_ENABLED
1598
1599#ifdef DEBUG_ENABLED
1600 String function_visible_name = function_name;
1601 if (function_name == StringName()) {
1602 function_visible_name = p_is_lambda ? "<anonymous lambda>" : "<unknown function>";
1603 }
1604#endif
1605
1606 for (int i = 0; i < p_function->parameters.size(); i++) {
1607 resolve_parameter(p_function->parameters[i]);
1608#ifdef DEBUG_ENABLED
1609 if (p_function->parameters[i]->usages == 0 && !String(p_function->parameters[i]->identifier->name).begins_with("_")) {
1610 parser->push_warning(p_function->parameters[i]->identifier, GDScriptWarning::UNUSED_PARAMETER, function_visible_name, p_function->parameters[i]->identifier->name);
1611 }
1612 is_shadowing(p_function->parameters[i]->identifier, "function parameter", true);
1613#endif // DEBUG_ENABLED
1614
1615 if (p_function->parameters[i]->initializer) {
1616#ifdef TOOLS_ENABLED
1617 default_value_count++;
1618#endif // TOOLS_ENABLED
1619
1620 if (p_function->parameters[i]->initializer->is_constant) {
1621 p_function->default_arg_values.push_back(p_function->parameters[i]->initializer->reduced_value);
1622 } else {
1623 p_function->default_arg_values.push_back(Variant()); // Prevent shift.
1624 }
1625 }
1626 }
1627
1628 if (!p_is_lambda && function_name == GDScriptLanguage::get_singleton()->strings._init) {
1629 // Constructor.
1630 GDScriptParser::DataType return_type = parser->current_class->get_datatype();
1631 return_type.is_meta_type = false;
1632 p_function->set_datatype(return_type);
1633 if (p_function->return_type) {
1634 GDScriptParser::DataType declared_return = resolve_datatype(p_function->return_type);
1635 if (declared_return.kind != GDScriptParser::DataType::BUILTIN || declared_return.builtin_type != Variant::NIL) {
1636 push_error("Constructor cannot have an explicit return type.", p_function->return_type);
1637 }
1638 }
1639 } else if (!p_is_lambda && function_name == GDScriptLanguage::get_singleton()->strings._static_init) {
1640 // Static constructor.
1641 GDScriptParser::DataType return_type;
1642 return_type.kind = GDScriptParser::DataType::BUILTIN;
1643 return_type.builtin_type = Variant::NIL;
1644 p_function->set_datatype(return_type);
1645 if (p_function->return_type) {
1646 GDScriptParser::DataType declared_return = resolve_datatype(p_function->return_type);
1647 if (declared_return.kind != GDScriptParser::DataType::BUILTIN || declared_return.builtin_type != Variant::NIL) {
1648 push_error("Static constructor cannot have an explicit return type.", p_function->return_type);
1649 }
1650 }
1651 } else {
1652 if (p_function->return_type != nullptr) {
1653 p_function->set_datatype(type_from_metatype(resolve_datatype(p_function->return_type)));
1654 } else {
1655 // In case the function is not typed, we can safely assume it's a Variant, so it's okay to mark as "inferred" here.
1656 // It's not "undetected" to not mix up with unknown functions.
1657 GDScriptParser::DataType return_type;
1658 return_type.type_source = GDScriptParser::DataType::INFERRED;
1659 return_type.kind = GDScriptParser::DataType::VARIANT;
1660 p_function->set_datatype(return_type);
1661 }
1662
1663#ifdef TOOLS_ENABLED
1664 // Check if the function signature matches the parent. If not it's an error since it breaks polymorphism.
1665 // Not for the constructor which can vary in signature.
1666 GDScriptParser::DataType base_type = parser->current_class->base_type;
1667 base_type.is_meta_type = false;
1668 GDScriptParser::DataType parent_return_type;
1669 List<GDScriptParser::DataType> parameters_types;
1670 int default_par_count = 0;
1671 BitField<MethodFlags> method_flags;
1672 StringName native_base;
1673 if (!p_is_lambda && get_function_signature(p_function, false, base_type, function_name, parent_return_type, parameters_types, default_par_count, method_flags, &native_base)) {
1674 bool valid = p_function->is_static == method_flags.has_flag(METHOD_FLAG_STATIC);
1675 valid = valid && parent_return_type == p_function->get_datatype();
1676
1677 int par_count_diff = p_function->parameters.size() - parameters_types.size();
1678 valid = valid && par_count_diff >= 0;
1679 valid = valid && default_value_count >= default_par_count + par_count_diff;
1680
1681 int i = 0;
1682 for (const GDScriptParser::DataType &par_type : parameters_types) {
1683 valid = valid && par_type == p_function->parameters[i++]->get_datatype();
1684 }
1685
1686 if (!valid) {
1687 // Compute parent signature as a string to show in the error message.
1688 String parent_signature = String(function_name) + "(";
1689 int j = 0;
1690 for (const GDScriptParser::DataType &par_type : parameters_types) {
1691 if (j > 0) {
1692 parent_signature += ", ";
1693 }
1694 String parameter = par_type.to_string();
1695 if (parameter == "null") {
1696 parameter = "Variant";
1697 }
1698 parent_signature += parameter;
1699 if (j >= parameters_types.size() - default_par_count) {
1700 parent_signature += " = <default>";
1701 }
1702
1703 j++;
1704 }
1705 parent_signature += ") -> ";
1706
1707 const String return_type = parent_return_type.is_hard_type() ? parent_return_type.to_string() : "Variant";
1708 if (return_type == "null") {
1709 parent_signature += "void";
1710 } else {
1711 parent_signature += return_type;
1712 }
1713
1714 push_error(vformat(R"(The function signature doesn't match the parent. Parent signature is "%s".)", parent_signature), p_function);
1715 }
1716#ifdef DEBUG_ENABLED
1717 if (native_base != StringName()) {
1718 parser->push_warning(p_function, GDScriptWarning::NATIVE_METHOD_OVERRIDE, function_name, native_base);
1719 }
1720#endif
1721 }
1722#endif // TOOLS_ENABLED
1723 }
1724
1725#ifdef DEBUG_ENABLED
1726 if (p_function->return_type == nullptr) {
1727 parser->push_warning(p_function, GDScriptWarning::UNTYPED_DECLARATION, "Function", function_visible_name);
1728 }
1729#endif
1730
1731 if (p_function->get_datatype().is_resolving()) {
1732 p_function->set_datatype(prev_datatype);
1733 }
1734
1735#ifdef DEBUG_ENABLED
1736 parser->ignored_warnings = previously_ignored_warnings;
1737#endif
1738 parser->current_function = previous_function;
1739 static_context = previous_static_context;
1740}
1741
1742void GDScriptAnalyzer::resolve_function_body(GDScriptParser::FunctionNode *p_function, bool p_is_lambda) {
1743 if (p_function->resolved_body) {
1744 return;
1745 }
1746 p_function->resolved_body = true;
1747
1748#ifdef DEBUG_ENABLED
1749 HashSet<GDScriptWarning::Code> previously_ignored_warnings = parser->ignored_warnings;
1750 for (GDScriptWarning::Code ignored_warning : p_function->ignored_warnings) {
1751 parser->ignored_warnings.insert(ignored_warning);
1752 }
1753#endif
1754
1755 GDScriptParser::FunctionNode *previous_function = parser->current_function;
1756 parser->current_function = p_function;
1757
1758 bool previous_static_context = static_context;
1759 static_context = p_function->is_static;
1760
1761 resolve_suite(p_function->body);
1762
1763 if (!p_function->get_datatype().is_hard_type() && p_function->body->get_datatype().is_set()) {
1764 // Use the suite inferred type if return isn't explicitly set.
1765 p_function->set_datatype(p_function->body->get_datatype());
1766 } 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)) {
1767 if (!p_function->body->has_return && (p_is_lambda || p_function->identifier->name != GDScriptLanguage::get_singleton()->strings._init)) {
1768 push_error(R"(Not all code paths return a value.)", p_function);
1769 }
1770 }
1771
1772#ifdef DEBUG_ENABLED
1773 parser->ignored_warnings = previously_ignored_warnings;
1774#endif
1775 parser->current_function = previous_function;
1776 static_context = previous_static_context;
1777}
1778
1779void GDScriptAnalyzer::decide_suite_type(GDScriptParser::Node *p_suite, GDScriptParser::Node *p_statement) {
1780 if (p_statement == nullptr) {
1781 return;
1782 }
1783 switch (p_statement->type) {
1784 case GDScriptParser::Node::IF:
1785 case GDScriptParser::Node::FOR:
1786 case GDScriptParser::Node::MATCH:
1787 case GDScriptParser::Node::PATTERN:
1788 case GDScriptParser::Node::RETURN:
1789 case GDScriptParser::Node::WHILE:
1790 // Use return or nested suite type as this suite type.
1791 if (p_suite->get_datatype().is_set() && (p_suite->get_datatype() != p_statement->get_datatype())) {
1792 // Mixed types.
1793 // TODO: This could use the common supertype instead.
1794 p_suite->datatype.kind = GDScriptParser::DataType::VARIANT;
1795 p_suite->datatype.type_source = GDScriptParser::DataType::UNDETECTED;
1796 } else {
1797 p_suite->set_datatype(p_statement->get_datatype());
1798 p_suite->datatype.type_source = GDScriptParser::DataType::INFERRED;
1799 }
1800 break;
1801 default:
1802 break;
1803 }
1804}
1805
1806void GDScriptAnalyzer::resolve_suite(GDScriptParser::SuiteNode *p_suite) {
1807 for (int i = 0; i < p_suite->statements.size(); i++) {
1808 GDScriptParser::Node *stmt = p_suite->statements[i];
1809 // Apply annotations.
1810 for (GDScriptParser::AnnotationNode *&E : stmt->annotations) {
1811 resolve_annotation(E);
1812 E->apply(parser, stmt);
1813 }
1814
1815#ifdef DEBUG_ENABLED
1816 HashSet<GDScriptWarning::Code> previously_ignored_warnings = parser->ignored_warnings;
1817 for (GDScriptWarning::Code ignored_warning : stmt->ignored_warnings) {
1818 parser->ignored_warnings.insert(ignored_warning);
1819 }
1820#endif // DEBUG_ENABLED
1821
1822 resolve_node(stmt);
1823 resolve_pending_lambda_bodies();
1824
1825#ifdef DEBUG_ENABLED
1826 parser->ignored_warnings = previously_ignored_warnings;
1827#endif // DEBUG_ENABLED
1828
1829 decide_suite_type(p_suite, stmt);
1830 }
1831}
1832
1833void GDScriptAnalyzer::resolve_assignable(GDScriptParser::AssignableNode *p_assignable, const char *p_kind) {
1834 GDScriptParser::DataType type;
1835 type.kind = GDScriptParser::DataType::VARIANT;
1836
1837 bool is_constant = p_assignable->type == GDScriptParser::Node::CONSTANT;
1838
1839#ifdef DEBUG_ENABLED
1840 if (p_assignable->identifier != nullptr && p_assignable->identifier->suite != nullptr && p_assignable->identifier->suite->parent_block != nullptr) {
1841 if (p_assignable->identifier->suite->parent_block->has_local(p_assignable->identifier->name)) {
1842 const GDScriptParser::SuiteNode::Local &local = p_assignable->identifier->suite->parent_block->get_local(p_assignable->identifier->name);
1843 parser->push_warning(p_assignable->identifier, GDScriptWarning::CONFUSABLE_LOCAL_DECLARATION, local.get_name(), p_assignable->identifier->name);
1844 }
1845 }
1846#endif
1847
1848 GDScriptParser::DataType specified_type;
1849 bool has_specified_type = p_assignable->datatype_specifier != nullptr;
1850 if (has_specified_type) {
1851 specified_type = type_from_metatype(resolve_datatype(p_assignable->datatype_specifier));
1852 type = specified_type;
1853 }
1854
1855 if (p_assignable->initializer != nullptr) {
1856 reduce_expression(p_assignable->initializer);
1857
1858 if (p_assignable->initializer->type == GDScriptParser::Node::ARRAY) {
1859 GDScriptParser::ArrayNode *array = static_cast<GDScriptParser::ArrayNode *>(p_assignable->initializer);
1860 if (has_specified_type && specified_type.has_container_element_type()) {
1861 update_array_literal_element_type(array, specified_type.get_container_element_type());
1862 }
1863 }
1864
1865 if (is_constant && !p_assignable->initializer->is_constant) {
1866 bool is_initializer_value_reduced = false;
1867 Variant initializer_value = make_expression_reduced_value(p_assignable->initializer, is_initializer_value_reduced);
1868 if (is_initializer_value_reduced) {
1869 p_assignable->initializer->is_constant = true;
1870 p_assignable->initializer->reduced_value = initializer_value;
1871 } else {
1872 push_error(vformat(R"(Assigned value for %s "%s" isn't a constant expression.)", p_kind, p_assignable->identifier->name), p_assignable->initializer);
1873 }
1874 }
1875
1876 if (has_specified_type && p_assignable->initializer->is_constant) {
1877 update_const_expression_builtin_type(p_assignable->initializer, specified_type, "assign");
1878 }
1879 GDScriptParser::DataType initializer_type = p_assignable->initializer->get_datatype();
1880
1881 if (p_assignable->infer_datatype) {
1882 if (!initializer_type.is_set() || initializer_type.has_no_type() || !initializer_type.is_hard_type()) {
1883 push_error(vformat(R"(Cannot infer the type of "%s" %s because the value doesn't have a set type.)", p_assignable->identifier->name, p_kind), p_assignable->initializer);
1884 } else if (initializer_type.kind == GDScriptParser::DataType::BUILTIN && initializer_type.builtin_type == Variant::NIL && !is_constant) {
1885 push_error(vformat(R"(Cannot infer the type of "%s" %s because the value is "null".)", p_assignable->identifier->name, p_kind), p_assignable->initializer);
1886 }
1887#ifdef DEBUG_ENABLED
1888 if (initializer_type.is_hard_type() && initializer_type.is_variant()) {
1889 parser->push_warning(p_assignable, GDScriptWarning::INFERENCE_ON_VARIANT, p_kind);
1890 }
1891#endif
1892 } else {
1893 if (!initializer_type.is_set()) {
1894 push_error(vformat(R"(Could not resolve type for %s "%s".)", p_kind, p_assignable->identifier->name), p_assignable->initializer);
1895 }
1896 }
1897
1898 if (!has_specified_type) {
1899 type = initializer_type;
1900
1901 if (!type.is_set() || (type.is_hard_type() && type.kind == GDScriptParser::DataType::BUILTIN && type.builtin_type == Variant::NIL && !is_constant)) {
1902 type.kind = GDScriptParser::DataType::VARIANT;
1903 }
1904
1905 if (p_assignable->infer_datatype || is_constant) {
1906 type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
1907 } else {
1908 type.type_source = GDScriptParser::DataType::INFERRED;
1909 }
1910 } else if (!specified_type.is_variant()) {
1911 if (initializer_type.is_variant() || !initializer_type.is_hard_type()) {
1912 mark_node_unsafe(p_assignable->initializer);
1913 p_assignable->use_conversion_assign = true;
1914 if (!initializer_type.is_variant() && !is_type_compatible(specified_type, initializer_type, true, p_assignable->initializer)) {
1915 downgrade_node_type_source(p_assignable->initializer);
1916 }
1917 } else if (!is_type_compatible(specified_type, initializer_type, true, p_assignable->initializer)) {
1918 if (!is_constant && is_type_compatible(initializer_type, specified_type)) {
1919 mark_node_unsafe(p_assignable->initializer);
1920 p_assignable->use_conversion_assign = true;
1921 } else {
1922 push_error(vformat(R"(Cannot assign a value of type %s to %s "%s" with specified type %s.)", initializer_type.to_string(), p_kind, p_assignable->identifier->name, specified_type.to_string()), p_assignable->initializer);
1923 }
1924 } else if (specified_type.has_container_element_type() && !initializer_type.has_container_element_type()) {
1925 mark_node_unsafe(p_assignable->initializer);
1926#ifdef DEBUG_ENABLED
1927 } else if (specified_type.builtin_type == Variant::INT && initializer_type.builtin_type == Variant::FLOAT) {
1928 parser->push_warning(p_assignable->initializer, GDScriptWarning::NARROWING_CONVERSION);
1929#endif
1930 }
1931 }
1932 }
1933
1934#ifdef DEBUG_ENABLED
1935 if (!has_specified_type && !p_assignable->infer_datatype && !is_constant) {
1936 const bool is_parameter = p_assignable->type == GDScriptParser::Node::PARAMETER;
1937 parser->push_warning(p_assignable, GDScriptWarning::UNTYPED_DECLARATION, is_parameter ? "Parameter" : "Variable", p_assignable->identifier->name);
1938 }
1939#endif
1940
1941 type.is_constant = is_constant;
1942 type.is_read_only = false;
1943 p_assignable->set_datatype(type);
1944}
1945
1946void GDScriptAnalyzer::resolve_variable(GDScriptParser::VariableNode *p_variable, bool p_is_local) {
1947 static constexpr const char *kind = "variable";
1948 resolve_assignable(p_variable, kind);
1949
1950#ifdef DEBUG_ENABLED
1951 if (p_is_local) {
1952 if (p_variable->usages == 0 && !String(p_variable->identifier->name).begins_with("_")) {
1953 parser->push_warning(p_variable, GDScriptWarning::UNUSED_VARIABLE, p_variable->identifier->name);
1954 } else if (p_variable->assignments == 0) {
1955 parser->push_warning(p_variable, GDScriptWarning::UNASSIGNED_VARIABLE, p_variable->identifier->name);
1956 }
1957 }
1958 is_shadowing(p_variable->identifier, kind, p_is_local);
1959#endif
1960}
1961
1962void GDScriptAnalyzer::resolve_constant(GDScriptParser::ConstantNode *p_constant, bool p_is_local) {
1963 static constexpr const char *kind = "constant";
1964 resolve_assignable(p_constant, kind);
1965
1966#ifdef DEBUG_ENABLED
1967 if (p_is_local) {
1968 if (p_constant->usages == 0) {
1969 parser->push_warning(p_constant, GDScriptWarning::UNUSED_LOCAL_CONSTANT, p_constant->identifier->name);
1970 }
1971 }
1972 is_shadowing(p_constant->identifier, kind, p_is_local);
1973#endif
1974}
1975
1976void GDScriptAnalyzer::resolve_parameter(GDScriptParser::ParameterNode *p_parameter) {
1977 static constexpr const char *kind = "parameter";
1978 resolve_assignable(p_parameter, kind);
1979}
1980
1981void GDScriptAnalyzer::resolve_if(GDScriptParser::IfNode *p_if) {
1982 reduce_expression(p_if->condition);
1983
1984 resolve_suite(p_if->true_block);
1985 p_if->set_datatype(p_if->true_block->get_datatype());
1986
1987 if (p_if->false_block != nullptr) {
1988 resolve_suite(p_if->false_block);
1989 decide_suite_type(p_if, p_if->false_block);
1990 }
1991}
1992
1993void GDScriptAnalyzer::resolve_for(GDScriptParser::ForNode *p_for) {
1994 bool list_resolved = false;
1995
1996 // Optimize constant range() call to not allocate an array.
1997 // Use int, Vector2i, Vector3i instead, which also can be used as range iterators.
1998 if (p_for->list && p_for->list->type == GDScriptParser::Node::CALL) {
1999 GDScriptParser::CallNode *call = static_cast<GDScriptParser::CallNode *>(p_for->list);
2000 GDScriptParser::Node::Type callee_type = call->get_callee_type();
2001 if (callee_type == GDScriptParser::Node::IDENTIFIER) {
2002 GDScriptParser::IdentifierNode *callee = static_cast<GDScriptParser::IdentifierNode *>(call->callee);
2003 if (callee->name == "range") {
2004 list_resolved = true;
2005 if (call->arguments.size() < 1) {
2006 push_error(R"*(Invalid call for "range()" function. Expected at least 1 argument, none given.)*", call->callee);
2007 } else if (call->arguments.size() > 3) {
2008 push_error(vformat(R"*(Invalid call for "range()" function. Expected at most 3 arguments, %d given.)*", call->arguments.size()), call->callee);
2009 } else {
2010 // Now we can optimize it.
2011 bool can_reduce = true;
2012 Vector<Variant> args;
2013 args.resize(call->arguments.size());
2014 for (int i = 0; i < call->arguments.size(); i++) {
2015 GDScriptParser::ExpressionNode *argument = call->arguments[i];
2016 reduce_expression(argument);
2017
2018 if (argument->is_constant) {
2019 if (argument->reduced_value.get_type() != Variant::INT && argument->reduced_value.get_type() != Variant::FLOAT) {
2020 can_reduce = false;
2021 push_error(vformat(R"*(Invalid argument for "range()" call. Argument %d should be int or float but "%s" was given.)*", i + 1, Variant::get_type_name(argument->reduced_value.get_type())), argument);
2022 }
2023 if (can_reduce) {
2024 args.write[i] = argument->reduced_value;
2025 }
2026 } else {
2027 can_reduce = false;
2028 GDScriptParser::DataType argument_type = argument->get_datatype();
2029 if (argument_type.is_variant() || !argument_type.is_hard_type()) {
2030 mark_node_unsafe(argument);
2031 }
2032 if (!argument_type.is_variant() && (argument_type.builtin_type != Variant::INT && argument_type.builtin_type != Variant::FLOAT)) {
2033 if (!argument_type.is_hard_type()) {
2034 downgrade_node_type_source(argument);
2035 } else {
2036 push_error(vformat(R"*(Invalid argument for "range()" call. Argument %d should be int or float but "%s" was given.)*", i + 1, argument_type.to_string()), argument);
2037 }
2038 }
2039 }
2040 }
2041
2042 Variant reduced;
2043
2044 if (can_reduce) {
2045 switch (args.size()) {
2046 case 1:
2047 reduced = (int32_t)args[0];
2048 break;
2049 case 2:
2050 reduced = Vector2i(args[0], args[1]);
2051 break;
2052 case 3:
2053 reduced = Vector3i(args[0], args[1], args[2]);
2054 break;
2055 }
2056 p_for->list->is_constant = true;
2057 p_for->list->reduced_value = reduced;
2058 }
2059 }
2060
2061 if (p_for->list->is_constant) {
2062 p_for->list->set_datatype(type_from_variant(p_for->list->reduced_value, p_for->list));
2063 } else {
2064 GDScriptParser::DataType list_type;
2065 list_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2066 list_type.kind = GDScriptParser::DataType::BUILTIN;
2067 list_type.builtin_type = Variant::ARRAY;
2068 p_for->list->set_datatype(list_type);
2069 }
2070 }
2071 }
2072 }
2073
2074 GDScriptParser::DataType variable_type;
2075 String list_visible_type = "<unresolved type>";
2076 if (list_resolved) {
2077 variable_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
2078 variable_type.kind = GDScriptParser::DataType::BUILTIN;
2079 variable_type.builtin_type = Variant::INT;
2080 list_visible_type = "Array[int]"; // NOTE: `range()` has `Array` return type.
2081 } else if (p_for->list) {
2082 resolve_node(p_for->list, false);
2083 GDScriptParser::DataType list_type = p_for->list->get_datatype();
2084 list_visible_type = list_type.to_string();
2085 if (!list_type.is_hard_type()) {
2086 mark_node_unsafe(p_for->list);
2087 }
2088 if (list_type.is_variant()) {
2089 variable_type.kind = GDScriptParser::DataType::VARIANT;
2090 mark_node_unsafe(p_for->list);
2091 } else if (list_type.has_container_element_type()) {
2092 variable_type = list_type.get_container_element_type();
2093 variable_type.type_source = list_type.type_source;
2094 } else if (list_type.is_typed_container_type()) {
2095 variable_type = list_type.get_typed_container_type();
2096 variable_type.type_source = list_type.type_source;
2097 } else if (list_type.builtin_type == Variant::INT || list_type.builtin_type == Variant::FLOAT || list_type.builtin_type == Variant::STRING) {
2098 variable_type.type_source = list_type.type_source;
2099 variable_type.kind = GDScriptParser::DataType::BUILTIN;
2100 variable_type.builtin_type = list_type.builtin_type;
2101 } else if (list_type.builtin_type == Variant::VECTOR2I || list_type.builtin_type == Variant::VECTOR3I) {
2102 variable_type.type_source = list_type.type_source;
2103 variable_type.kind = GDScriptParser::DataType::BUILTIN;
2104 variable_type.builtin_type = Variant::INT;
2105 } else if (list_type.builtin_type == Variant::VECTOR2 || list_type.builtin_type == Variant::VECTOR3) {
2106 variable_type.type_source = list_type.type_source;
2107 variable_type.kind = GDScriptParser::DataType::BUILTIN;
2108 variable_type.builtin_type = Variant::FLOAT;
2109 } else if (list_type.builtin_type == Variant::OBJECT) {
2110 GDScriptParser::DataType return_type;
2111 List<GDScriptParser::DataType> par_types;
2112 int default_arg_count = 0;
2113 BitField<MethodFlags> method_flags;
2114 if (get_function_signature(p_for->list, false, list_type, CoreStringNames::get_singleton()->_iter_get, return_type, par_types, default_arg_count, method_flags)) {
2115 variable_type = return_type;
2116 variable_type.type_source = list_type.type_source;
2117 } else if (!list_type.is_hard_type()) {
2118 variable_type.kind = GDScriptParser::DataType::VARIANT;
2119 } else {
2120 push_error(vformat(R"(Unable to iterate on object of type "%s".)", list_type.to_string()), p_for->list);
2121 }
2122 } else if (list_type.builtin_type == Variant::ARRAY || list_type.builtin_type == Variant::DICTIONARY || !list_type.is_hard_type()) {
2123 variable_type.kind = GDScriptParser::DataType::VARIANT;
2124 } else {
2125 push_error(vformat(R"(Unable to iterate on value of type "%s".)", list_type.to_string()), p_for->list);
2126 }
2127 }
2128
2129 if (p_for->variable) {
2130 if (p_for->datatype_specifier) {
2131 GDScriptParser::DataType specified_type = type_from_metatype(resolve_datatype(p_for->datatype_specifier));
2132 if (!specified_type.is_variant()) {
2133 if (variable_type.is_variant() || !variable_type.is_hard_type()) {
2134 mark_node_unsafe(p_for->variable);
2135 p_for->use_conversion_assign = true;
2136 } else if (!is_type_compatible(specified_type, variable_type, true, p_for->variable)) {
2137 if (is_type_compatible(variable_type, specified_type)) {
2138 mark_node_unsafe(p_for->variable);
2139 p_for->use_conversion_assign = true;
2140 } else {
2141 push_error(vformat(R"(Unable to iterate on value of type "%s" with variable of type "%s".)", list_visible_type, specified_type.to_string()), p_for->datatype_specifier);
2142 }
2143 } else if (!is_type_compatible(specified_type, variable_type)) {
2144 p_for->use_conversion_assign = true;
2145 }
2146 }
2147 p_for->variable->set_datatype(specified_type);
2148 } else {
2149 p_for->variable->set_datatype(variable_type);
2150#ifdef DEBUG_ENABLED
2151 if (!variable_type.is_hard_type()) {
2152 parser->push_warning(p_for->variable, GDScriptWarning::UNTYPED_DECLARATION, R"("for" iterator variable)", p_for->variable->name);
2153 }
2154#endif
2155 }
2156 }
2157
2158 resolve_suite(p_for->loop);
2159 p_for->set_datatype(p_for->loop->get_datatype());
2160#ifdef DEBUG_ENABLED
2161 if (p_for->variable) {
2162 is_shadowing(p_for->variable, R"("for" iterator variable)", true);
2163 }
2164#endif
2165}
2166
2167void GDScriptAnalyzer::resolve_while(GDScriptParser::WhileNode *p_while) {
2168 resolve_node(p_while->condition, false);
2169
2170 resolve_suite(p_while->loop);
2171 p_while->set_datatype(p_while->loop->get_datatype());
2172}
2173
2174void GDScriptAnalyzer::resolve_assert(GDScriptParser::AssertNode *p_assert) {
2175 reduce_expression(p_assert->condition);
2176 if (p_assert->message != nullptr) {
2177 reduce_expression(p_assert->message);
2178 if (!p_assert->message->get_datatype().has_no_type() && (p_assert->message->get_datatype().kind != GDScriptParser::DataType::BUILTIN || p_assert->message->get_datatype().builtin_type != Variant::STRING)) {
2179 push_error(R"(Expected string for assert error message.)", p_assert->message);
2180 }
2181 }
2182
2183 p_assert->set_datatype(p_assert->condition->get_datatype());
2184
2185#ifdef DEBUG_ENABLED
2186 if (p_assert->condition->is_constant) {
2187 if (p_assert->condition->reduced_value.booleanize()) {
2188 parser->push_warning(p_assert->condition, GDScriptWarning::ASSERT_ALWAYS_TRUE);
2189 } else if (!(p_assert->condition->type == GDScriptParser::Node::LITERAL && static_cast<GDScriptParser::LiteralNode *>(p_assert->condition)->value.get_type() == Variant::BOOL)) {
2190 parser->push_warning(p_assert->condition, GDScriptWarning::ASSERT_ALWAYS_FALSE);
2191 }
2192 }
2193#endif
2194}
2195
2196void GDScriptAnalyzer::resolve_match(GDScriptParser::MatchNode *p_match) {
2197 reduce_expression(p_match->test);
2198
2199 for (int i = 0; i < p_match->branches.size(); i++) {
2200 resolve_match_branch(p_match->branches[i], p_match->test);
2201
2202 decide_suite_type(p_match, p_match->branches[i]);
2203 }
2204}
2205
2206void GDScriptAnalyzer::resolve_match_branch(GDScriptParser::MatchBranchNode *p_match_branch, GDScriptParser::ExpressionNode *p_match_test) {
2207 for (int i = 0; i < p_match_branch->patterns.size(); i++) {
2208 resolve_match_pattern(p_match_branch->patterns[i], p_match_test);
2209 }
2210
2211 resolve_suite(p_match_branch->block);
2212
2213 decide_suite_type(p_match_branch, p_match_branch->block);
2214}
2215
2216void GDScriptAnalyzer::resolve_match_pattern(GDScriptParser::PatternNode *p_match_pattern, GDScriptParser::ExpressionNode *p_match_test) {
2217 if (p_match_pattern == nullptr) {
2218 return;
2219 }
2220
2221 GDScriptParser::DataType result;
2222
2223 switch (p_match_pattern->pattern_type) {
2224 case GDScriptParser::PatternNode::PT_LITERAL:
2225 if (p_match_pattern->literal) {
2226 reduce_literal(p_match_pattern->literal);
2227 result = p_match_pattern->literal->get_datatype();
2228 }
2229 break;
2230 case GDScriptParser::PatternNode::PT_EXPRESSION:
2231 if (p_match_pattern->expression) {
2232 GDScriptParser::ExpressionNode *expr = p_match_pattern->expression;
2233 reduce_expression(expr);
2234 result = expr->get_datatype();
2235 if (!expr->is_constant) {
2236 while (expr && expr->type == GDScriptParser::Node::SUBSCRIPT) {
2237 GDScriptParser::SubscriptNode *sub = static_cast<GDScriptParser::SubscriptNode *>(expr);
2238 if (!sub->is_attribute) {
2239 expr = nullptr;
2240 } else {
2241 expr = sub->base;
2242 }
2243 }
2244 if (!expr || expr->type != GDScriptParser::Node::IDENTIFIER) {
2245 push_error(R"(Expression in match pattern must be a constant expression, an identifier, or an attribute access ("A.B").)", expr);
2246 }
2247 }
2248 }
2249 break;
2250 case GDScriptParser::PatternNode::PT_BIND:
2251 if (p_match_test != nullptr) {
2252 result = p_match_test->get_datatype();
2253 } else {
2254 result.kind = GDScriptParser::DataType::VARIANT;
2255 }
2256 p_match_pattern->bind->set_datatype(result);
2257#ifdef DEBUG_ENABLED
2258 is_shadowing(p_match_pattern->bind, "pattern bind", true);
2259 if (p_match_pattern->bind->usages == 0 && !String(p_match_pattern->bind->name).begins_with("_")) {
2260 parser->push_warning(p_match_pattern->bind, GDScriptWarning::UNUSED_VARIABLE, p_match_pattern->bind->name);
2261 }
2262#endif
2263 break;
2264 case GDScriptParser::PatternNode::PT_ARRAY:
2265 for (int i = 0; i < p_match_pattern->array.size(); i++) {
2266 resolve_match_pattern(p_match_pattern->array[i], nullptr);
2267 decide_suite_type(p_match_pattern, p_match_pattern->array[i]);
2268 }
2269 result = p_match_pattern->get_datatype();
2270 break;
2271 case GDScriptParser::PatternNode::PT_DICTIONARY:
2272 for (int i = 0; i < p_match_pattern->dictionary.size(); i++) {
2273 if (p_match_pattern->dictionary[i].key) {
2274 reduce_expression(p_match_pattern->dictionary[i].key);
2275 if (!p_match_pattern->dictionary[i].key->is_constant) {
2276 push_error(R"(Expression in dictionary pattern key must be a constant.)", p_match_pattern->dictionary[i].key);
2277 }
2278 }
2279
2280 if (p_match_pattern->dictionary[i].value_pattern) {
2281 resolve_match_pattern(p_match_pattern->dictionary[i].value_pattern, nullptr);
2282 decide_suite_type(p_match_pattern, p_match_pattern->dictionary[i].value_pattern);
2283 }
2284 }
2285 result = p_match_pattern->get_datatype();
2286 break;
2287 case GDScriptParser::PatternNode::PT_WILDCARD:
2288 case GDScriptParser::PatternNode::PT_REST:
2289 result.kind = GDScriptParser::DataType::VARIANT;
2290 break;
2291 }
2292
2293 p_match_pattern->set_datatype(result);
2294}
2295
2296void GDScriptAnalyzer::resolve_return(GDScriptParser::ReturnNode *p_return) {
2297 GDScriptParser::DataType result;
2298
2299 GDScriptParser::DataType expected_type;
2300 bool has_expected_type = parser->current_function != nullptr;
2301 if (has_expected_type) {
2302 expected_type = parser->current_function->get_datatype();
2303 }
2304
2305 if (p_return->return_value != nullptr) {
2306 bool is_void_function = has_expected_type && expected_type.is_hard_type() && expected_type.kind == GDScriptParser::DataType::BUILTIN && expected_type.builtin_type == Variant::NIL;
2307 bool is_call = p_return->return_value->type == GDScriptParser::Node::CALL;
2308 if (is_void_function && is_call) {
2309 // Pretend the call is a root expression to allow those that are "void".
2310 reduce_call(static_cast<GDScriptParser::CallNode *>(p_return->return_value), false, true);
2311 } else {
2312 reduce_expression(p_return->return_value);
2313 }
2314 if (is_void_function) {
2315 p_return->void_return = true;
2316 const GDScriptParser::DataType &return_type = p_return->return_value->datatype;
2317 if (is_call && !return_type.is_hard_type()) {
2318 String function_name = parser->current_function->identifier ? parser->current_function->identifier->name.operator String() : String("<anonymous function>");
2319 String called_function_name = static_cast<GDScriptParser::CallNode *>(p_return->return_value)->function_name.operator String();
2320#ifdef DEBUG_ENABLED
2321 parser->push_warning(p_return, GDScriptWarning::UNSAFE_VOID_RETURN, function_name, called_function_name);
2322#endif
2323 mark_node_unsafe(p_return);
2324 } else if (!is_call) {
2325 push_error("A void function cannot return a value.", p_return);
2326 }
2327 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2328 result.kind = GDScriptParser::DataType::BUILTIN;
2329 result.builtin_type = Variant::NIL;
2330 result.is_constant = true;
2331 } else {
2332 if (p_return->return_value->type == GDScriptParser::Node::ARRAY && has_expected_type && expected_type.has_container_element_type()) {
2333 update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_return->return_value), expected_type.get_container_element_type());
2334 }
2335 if (has_expected_type && expected_type.is_hard_type() && p_return->return_value->is_constant) {
2336 update_const_expression_builtin_type(p_return->return_value, expected_type, "return");
2337 }
2338 result = p_return->return_value->get_datatype();
2339 }
2340 } else {
2341 // Return type is null by default.
2342 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2343 result.kind = GDScriptParser::DataType::BUILTIN;
2344 result.builtin_type = Variant::NIL;
2345 result.is_constant = true;
2346 }
2347
2348 if (has_expected_type && !expected_type.is_variant()) {
2349 if (result.is_variant() || !result.is_hard_type()) {
2350 mark_node_unsafe(p_return);
2351 if (!is_type_compatible(expected_type, result, true, p_return)) {
2352 downgrade_node_type_source(p_return);
2353 }
2354 } else if (!is_type_compatible(expected_type, result, true, p_return)) {
2355 mark_node_unsafe(p_return);
2356 if (!is_type_compatible(result, expected_type)) {
2357 push_error(vformat(R"(Cannot return value of type "%s" because the function return type is "%s".)", result.to_string(), expected_type.to_string()), p_return);
2358 }
2359#ifdef DEBUG_ENABLED
2360 } else if (expected_type.builtin_type == Variant::INT && result.builtin_type == Variant::FLOAT) {
2361 parser->push_warning(p_return, GDScriptWarning::NARROWING_CONVERSION);
2362#endif
2363 }
2364 }
2365
2366 p_return->set_datatype(result);
2367}
2368
2369void GDScriptAnalyzer::reduce_expression(GDScriptParser::ExpressionNode *p_expression, bool p_is_root) {
2370 // This one makes some magic happen.
2371
2372 if (p_expression == nullptr) {
2373 return;
2374 }
2375
2376 if (p_expression->reduced) {
2377 // Don't do this more than once.
2378 return;
2379 }
2380
2381 p_expression->reduced = true;
2382
2383 switch (p_expression->type) {
2384 case GDScriptParser::Node::ARRAY:
2385 reduce_array(static_cast<GDScriptParser::ArrayNode *>(p_expression));
2386 break;
2387 case GDScriptParser::Node::ASSIGNMENT:
2388 reduce_assignment(static_cast<GDScriptParser::AssignmentNode *>(p_expression));
2389 break;
2390 case GDScriptParser::Node::AWAIT:
2391 reduce_await(static_cast<GDScriptParser::AwaitNode *>(p_expression));
2392 break;
2393 case GDScriptParser::Node::BINARY_OPERATOR:
2394 reduce_binary_op(static_cast<GDScriptParser::BinaryOpNode *>(p_expression));
2395 break;
2396 case GDScriptParser::Node::CALL:
2397 reduce_call(static_cast<GDScriptParser::CallNode *>(p_expression), false, p_is_root);
2398 break;
2399 case GDScriptParser::Node::CAST:
2400 reduce_cast(static_cast<GDScriptParser::CastNode *>(p_expression));
2401 break;
2402 case GDScriptParser::Node::DICTIONARY:
2403 reduce_dictionary(static_cast<GDScriptParser::DictionaryNode *>(p_expression));
2404 break;
2405 case GDScriptParser::Node::GET_NODE:
2406 reduce_get_node(static_cast<GDScriptParser::GetNodeNode *>(p_expression));
2407 break;
2408 case GDScriptParser::Node::IDENTIFIER:
2409 reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_expression));
2410 break;
2411 case GDScriptParser::Node::LAMBDA:
2412 reduce_lambda(static_cast<GDScriptParser::LambdaNode *>(p_expression));
2413 break;
2414 case GDScriptParser::Node::LITERAL:
2415 reduce_literal(static_cast<GDScriptParser::LiteralNode *>(p_expression));
2416 break;
2417 case GDScriptParser::Node::PRELOAD:
2418 reduce_preload(static_cast<GDScriptParser::PreloadNode *>(p_expression));
2419 break;
2420 case GDScriptParser::Node::SELF:
2421 reduce_self(static_cast<GDScriptParser::SelfNode *>(p_expression));
2422 break;
2423 case GDScriptParser::Node::SUBSCRIPT:
2424 reduce_subscript(static_cast<GDScriptParser::SubscriptNode *>(p_expression));
2425 break;
2426 case GDScriptParser::Node::TERNARY_OPERATOR:
2427 reduce_ternary_op(static_cast<GDScriptParser::TernaryOpNode *>(p_expression), p_is_root);
2428 break;
2429 case GDScriptParser::Node::TYPE_TEST:
2430 reduce_type_test(static_cast<GDScriptParser::TypeTestNode *>(p_expression));
2431 break;
2432 case GDScriptParser::Node::UNARY_OPERATOR:
2433 reduce_unary_op(static_cast<GDScriptParser::UnaryOpNode *>(p_expression));
2434 break;
2435 // Non-expressions. Here only to make sure new nodes aren't forgotten.
2436 case GDScriptParser::Node::NONE:
2437 case GDScriptParser::Node::ANNOTATION:
2438 case GDScriptParser::Node::ASSERT:
2439 case GDScriptParser::Node::BREAK:
2440 case GDScriptParser::Node::BREAKPOINT:
2441 case GDScriptParser::Node::CLASS:
2442 case GDScriptParser::Node::CONSTANT:
2443 case GDScriptParser::Node::CONTINUE:
2444 case GDScriptParser::Node::ENUM:
2445 case GDScriptParser::Node::FOR:
2446 case GDScriptParser::Node::FUNCTION:
2447 case GDScriptParser::Node::IF:
2448 case GDScriptParser::Node::MATCH:
2449 case GDScriptParser::Node::MATCH_BRANCH:
2450 case GDScriptParser::Node::PARAMETER:
2451 case GDScriptParser::Node::PASS:
2452 case GDScriptParser::Node::PATTERN:
2453 case GDScriptParser::Node::RETURN:
2454 case GDScriptParser::Node::SIGNAL:
2455 case GDScriptParser::Node::SUITE:
2456 case GDScriptParser::Node::TYPE:
2457 case GDScriptParser::Node::VARIABLE:
2458 case GDScriptParser::Node::WHILE:
2459 ERR_FAIL_MSG("Reaching unreachable case");
2460 }
2461}
2462
2463void GDScriptAnalyzer::reduce_array(GDScriptParser::ArrayNode *p_array) {
2464 for (int i = 0; i < p_array->elements.size(); i++) {
2465 GDScriptParser::ExpressionNode *element = p_array->elements[i];
2466 reduce_expression(element);
2467 }
2468
2469 // It's array in any case.
2470 GDScriptParser::DataType arr_type;
2471 arr_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2472 arr_type.kind = GDScriptParser::DataType::BUILTIN;
2473 arr_type.builtin_type = Variant::ARRAY;
2474 arr_type.is_constant = true;
2475
2476 p_array->set_datatype(arr_type);
2477}
2478
2479#ifdef DEBUG_ENABLED
2480static bool enum_has_value(const GDScriptParser::DataType p_type, int64_t p_value) {
2481 for (const KeyValue<StringName, int64_t> &E : p_type.enum_values) {
2482 if (E.value == p_value) {
2483 return true;
2484 }
2485 }
2486 return false;
2487}
2488#endif
2489
2490void GDScriptAnalyzer::update_const_expression_builtin_type(GDScriptParser::ExpressionNode *p_expression, const GDScriptParser::DataType &p_type, const char *p_usage, bool p_is_cast) {
2491 if (p_expression->get_datatype() == p_type) {
2492 return;
2493 }
2494 if (p_type.kind != GDScriptParser::DataType::BUILTIN && p_type.kind != GDScriptParser::DataType::ENUM) {
2495 return;
2496 }
2497
2498 GDScriptParser::DataType expression_type = p_expression->get_datatype();
2499 bool is_enum_cast = p_is_cast && p_type.kind == GDScriptParser::DataType::ENUM && p_type.is_meta_type == false && expression_type.builtin_type == Variant::INT;
2500 if (!is_enum_cast && !is_type_compatible(p_type, expression_type, true, p_expression)) {
2501 push_error(vformat(R"(Cannot %s a value of type "%s" as "%s".)", p_usage, expression_type.to_string(), p_type.to_string()), p_expression);
2502 return;
2503 }
2504
2505 GDScriptParser::DataType value_type = type_from_variant(p_expression->reduced_value, p_expression);
2506 if (expression_type.is_variant() && !is_enum_cast && !is_type_compatible(p_type, value_type, true, p_expression)) {
2507 push_error(vformat(R"(Cannot %s a value of type "%s" as "%s".)", p_usage, value_type.to_string(), p_type.to_string()), p_expression);
2508 return;
2509 }
2510
2511#ifdef DEBUG_ENABLED
2512 if (p_type.kind == GDScriptParser::DataType::ENUM && value_type.builtin_type == Variant::INT && !enum_has_value(p_type, p_expression->reduced_value)) {
2513 parser->push_warning(p_expression, GDScriptWarning::INT_AS_ENUM_WITHOUT_MATCH, p_usage, p_expression->reduced_value.stringify(), p_type.to_string());
2514 }
2515#endif
2516
2517 if (value_type.builtin_type == p_type.builtin_type) {
2518 p_expression->set_datatype(p_type);
2519 return;
2520 }
2521
2522 Variant converted_to;
2523 const Variant *converted_from = &p_expression->reduced_value;
2524 Callable::CallError call_error;
2525 Variant::construct(p_type.builtin_type, converted_to, &converted_from, 1, call_error);
2526 if (call_error.error) {
2527 push_error(vformat(R"(Failed to convert a value of type "%s" to "%s".)", value_type.to_string(), p_type.to_string()), p_expression);
2528 return;
2529 }
2530
2531#ifdef DEBUG_ENABLED
2532 if (p_type.builtin_type == Variant::INT && value_type.builtin_type == Variant::FLOAT) {
2533 parser->push_warning(p_expression, GDScriptWarning::NARROWING_CONVERSION);
2534 }
2535#endif
2536
2537 p_expression->reduced_value = converted_to;
2538 p_expression->set_datatype(p_type);
2539}
2540
2541// When an array literal is stored (or passed as function argument) to a typed context, we then assume the array is typed.
2542// This function determines which type is that (if any).
2543void GDScriptAnalyzer::update_array_literal_element_type(GDScriptParser::ArrayNode *p_array, const GDScriptParser::DataType &p_element_type) {
2544 for (int i = 0; i < p_array->elements.size(); i++) {
2545 GDScriptParser::ExpressionNode *element_node = p_array->elements[i];
2546 if (element_node->is_constant) {
2547 update_const_expression_builtin_type(element_node, p_element_type, "include");
2548 }
2549 const GDScriptParser::DataType &element_type = element_node->get_datatype();
2550 if (element_type.has_no_type() || element_type.is_variant() || !element_type.is_hard_type()) {
2551 mark_node_unsafe(element_node);
2552 continue;
2553 }
2554 if (!is_type_compatible(p_element_type, element_type, true, p_array)) {
2555 if (is_type_compatible(element_type, p_element_type)) {
2556 mark_node_unsafe(element_node);
2557 continue;
2558 }
2559 push_error(vformat(R"(Cannot have an element of type "%s" in an array of type "Array[%s]".)", element_type.to_string(), p_element_type.to_string()), element_node);
2560 return;
2561 }
2562 }
2563
2564 GDScriptParser::DataType array_type = p_array->get_datatype();
2565 array_type.set_container_element_type(p_element_type);
2566 p_array->set_datatype(array_type);
2567}
2568
2569void GDScriptAnalyzer::reduce_assignment(GDScriptParser::AssignmentNode *p_assignment) {
2570 reduce_expression(p_assignment->assignee);
2571 reduce_expression(p_assignment->assigned_value);
2572
2573 if (p_assignment->assigned_value == nullptr || p_assignment->assignee == nullptr) {
2574 return;
2575 }
2576
2577 GDScriptParser::DataType assignee_type = p_assignment->assignee->get_datatype();
2578
2579 if (assignee_type.is_constant) {
2580 push_error("Cannot assign a new value to a constant.", p_assignment->assignee);
2581 return;
2582 } else if (p_assignment->assignee->type == GDScriptParser::Node::SUBSCRIPT && static_cast<GDScriptParser::SubscriptNode *>(p_assignment->assignee)->base->is_constant) {
2583 const GDScriptParser::DataType &base_type = static_cast<GDScriptParser::SubscriptNode *>(p_assignment->assignee)->base->datatype;
2584 if (base_type.kind != GDScriptParser::DataType::SCRIPT && base_type.kind != GDScriptParser::DataType::CLASS) { // Static variables.
2585 push_error("Cannot assign a new value to a constant.", p_assignment->assignee);
2586 return;
2587 }
2588 } else if (assignee_type.is_read_only) {
2589 push_error("Cannot assign a new value to a read-only property.", p_assignment->assignee);
2590 return;
2591 } else if (p_assignment->assignee->type == GDScriptParser::Node::SUBSCRIPT) {
2592 GDScriptParser::SubscriptNode *sub = static_cast<GDScriptParser::SubscriptNode *>(p_assignment->assignee);
2593 while (sub) {
2594 const GDScriptParser::DataType &base_type = sub->base->datatype;
2595 if (base_type.is_hard_type() && base_type.is_read_only) {
2596 if (base_type.kind == GDScriptParser::DataType::BUILTIN && !Variant::is_type_shared(base_type.builtin_type)) {
2597 push_error("Cannot assign a new value to a read-only property.", p_assignment->assignee);
2598 return;
2599 }
2600 } else {
2601 break;
2602 }
2603 if (sub->base->type == GDScriptParser::Node::SUBSCRIPT) {
2604 sub = static_cast<GDScriptParser::SubscriptNode *>(sub->base);
2605 } else {
2606 sub = nullptr;
2607 }
2608 }
2609 }
2610
2611 // Check if assigned value is an array literal, so we can make it a typed array too if appropriate.
2612 if (p_assignment->assigned_value->type == GDScriptParser::Node::ARRAY && assignee_type.has_container_element_type()) {
2613 update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_assignment->assigned_value), assignee_type.get_container_element_type());
2614 }
2615
2616 if (p_assignment->operation == GDScriptParser::AssignmentNode::OP_NONE && assignee_type.is_hard_type() && p_assignment->assigned_value->is_constant) {
2617 update_const_expression_builtin_type(p_assignment->assigned_value, assignee_type, "assign");
2618 }
2619
2620 GDScriptParser::DataType assigned_value_type = p_assignment->assigned_value->get_datatype();
2621
2622 bool assignee_is_variant = assignee_type.is_variant();
2623 bool assignee_is_hard = assignee_type.is_hard_type();
2624 bool assigned_is_variant = assigned_value_type.is_variant();
2625 bool assigned_is_hard = assigned_value_type.is_hard_type();
2626 bool compatible = true;
2627 bool downgrades_assignee = false;
2628 bool downgrades_assigned = false;
2629 GDScriptParser::DataType op_type = assigned_value_type;
2630 if (p_assignment->operation != GDScriptParser::AssignmentNode::OP_NONE && !op_type.is_variant()) {
2631 op_type = get_operation_type(p_assignment->variant_op, assignee_type, assigned_value_type, compatible, p_assignment->assigned_value);
2632
2633 if (assignee_is_variant) {
2634 // variant assignee
2635 mark_node_unsafe(p_assignment);
2636 } else if (!compatible) {
2637 // incompatible hard types and non-variant assignee
2638 mark_node_unsafe(p_assignment);
2639 if (assigned_is_variant) {
2640 // incompatible hard non-variant assignee and hard variant assigned
2641 p_assignment->use_conversion_assign = true;
2642 } else {
2643 // incompatible hard non-variant types
2644 push_error(vformat(R"(Invalid operands "%s" and "%s" for assignment operator.)", assignee_type.to_string(), assigned_value_type.to_string()), p_assignment);
2645 }
2646 } else if (op_type.type_source == GDScriptParser::DataType::UNDETECTED && !assigned_is_variant) {
2647 // incompatible non-variant types (at least one weak)
2648 downgrades_assignee = !assignee_is_hard;
2649 downgrades_assigned = !assigned_is_hard;
2650 }
2651 }
2652 p_assignment->set_datatype(op_type);
2653
2654 if (assignee_is_variant) {
2655 if (!assignee_is_hard) {
2656 // weak variant assignee
2657 mark_node_unsafe(p_assignment);
2658 }
2659 } else {
2660 if (assignee_is_hard && !assigned_is_hard) {
2661 // hard non-variant assignee and weak assigned
2662 mark_node_unsafe(p_assignment);
2663 p_assignment->use_conversion_assign = true;
2664 downgrades_assigned = downgrades_assigned || (!assigned_is_variant && !is_type_compatible(assignee_type, op_type, true, p_assignment->assigned_value));
2665 } else if (compatible) {
2666 if (op_type.is_variant()) {
2667 // non-variant assignee and variant result
2668 mark_node_unsafe(p_assignment);
2669 if (assignee_is_hard) {
2670 // hard non-variant assignee and variant result
2671 p_assignment->use_conversion_assign = true;
2672 } else {
2673 // weak non-variant assignee and variant result
2674 downgrades_assignee = true;
2675 }
2676 } else if (!is_type_compatible(assignee_type, op_type, assignee_is_hard, p_assignment->assigned_value)) {
2677 // non-variant assignee and incompatible result
2678 mark_node_unsafe(p_assignment);
2679 if (assignee_is_hard) {
2680 if (is_type_compatible(op_type, assignee_type)) {
2681 // hard non-variant assignee and maybe compatible result
2682 p_assignment->use_conversion_assign = true;
2683 } else {
2684 // hard non-variant assignee and incompatible result
2685 push_error(vformat(R"(Value of type "%s" cannot be assigned to a variable of type "%s".)", assigned_value_type.to_string(), assignee_type.to_string()), p_assignment->assigned_value);
2686 }
2687 } else {
2688 // weak non-variant assignee and incompatible result
2689 downgrades_assignee = true;
2690 }
2691 } else if (assignee_type.has_container_element_type() && !op_type.has_container_element_type()) {
2692 // typed array assignee and untyped array result
2693 mark_node_unsafe(p_assignment);
2694 }
2695 }
2696 }
2697
2698 if (downgrades_assignee) {
2699 downgrade_node_type_source(p_assignment->assignee);
2700 }
2701 if (downgrades_assigned) {
2702 downgrade_node_type_source(p_assignment->assigned_value);
2703 }
2704
2705#ifdef DEBUG_ENABLED
2706 if (assignee_type.is_hard_type() && assignee_type.builtin_type == Variant::INT && assigned_value_type.builtin_type == Variant::FLOAT) {
2707 parser->push_warning(p_assignment->assigned_value, GDScriptWarning::NARROWING_CONVERSION);
2708 }
2709#endif
2710}
2711
2712void GDScriptAnalyzer::reduce_await(GDScriptParser::AwaitNode *p_await) {
2713 if (p_await->to_await == nullptr) {
2714 GDScriptParser::DataType await_type;
2715 await_type.kind = GDScriptParser::DataType::VARIANT;
2716 p_await->set_datatype(await_type);
2717 return;
2718 }
2719
2720 if (p_await->to_await->type == GDScriptParser::Node::CALL) {
2721 reduce_call(static_cast<GDScriptParser::CallNode *>(p_await->to_await), true);
2722 } else {
2723 reduce_expression(p_await->to_await);
2724 }
2725
2726 GDScriptParser::DataType await_type = p_await->to_await->get_datatype();
2727 // We cannot infer the type of the result of waiting for a signal.
2728 if (await_type.is_hard_type() && await_type.kind == GDScriptParser::DataType::BUILTIN && await_type.builtin_type == Variant::SIGNAL) {
2729 await_type.kind = GDScriptParser::DataType::VARIANT;
2730 await_type.type_source = GDScriptParser::DataType::UNDETECTED;
2731 } else if (p_await->to_await->is_constant) {
2732 p_await->is_constant = p_await->to_await->is_constant;
2733 p_await->reduced_value = p_await->to_await->reduced_value;
2734 }
2735 await_type.is_coroutine = false;
2736 p_await->set_datatype(await_type);
2737
2738#ifdef DEBUG_ENABLED
2739 GDScriptParser::DataType to_await_type = p_await->to_await->get_datatype();
2740 if (!to_await_type.is_coroutine && !to_await_type.is_variant() && to_await_type.builtin_type != Variant::SIGNAL) {
2741 parser->push_warning(p_await, GDScriptWarning::REDUNDANT_AWAIT);
2742 }
2743#endif
2744}
2745
2746void GDScriptAnalyzer::reduce_binary_op(GDScriptParser::BinaryOpNode *p_binary_op) {
2747 reduce_expression(p_binary_op->left_operand);
2748 reduce_expression(p_binary_op->right_operand);
2749
2750 GDScriptParser::DataType left_type;
2751 if (p_binary_op->left_operand) {
2752 left_type = p_binary_op->left_operand->get_datatype();
2753 }
2754 GDScriptParser::DataType right_type;
2755 if (p_binary_op->right_operand) {
2756 right_type = p_binary_op->right_operand->get_datatype();
2757 }
2758
2759 if (!left_type.is_set() || !right_type.is_set()) {
2760 return;
2761 }
2762
2763#ifdef DEBUG_ENABLED
2764 if (p_binary_op->variant_op == Variant::OP_DIVIDE && left_type.builtin_type == Variant::INT && right_type.builtin_type == Variant::INT) {
2765 parser->push_warning(p_binary_op, GDScriptWarning::INTEGER_DIVISION);
2766 }
2767#endif
2768
2769 if (p_binary_op->left_operand->is_constant && p_binary_op->right_operand->is_constant) {
2770 p_binary_op->is_constant = true;
2771 if (p_binary_op->variant_op < Variant::OP_MAX) {
2772 bool valid = false;
2773 Variant::evaluate(p_binary_op->variant_op, p_binary_op->left_operand->reduced_value, p_binary_op->right_operand->reduced_value, p_binary_op->reduced_value, valid);
2774 if (!valid) {
2775 if (p_binary_op->reduced_value.get_type() == Variant::STRING) {
2776 push_error(vformat(R"(%s in operator %s.)", p_binary_op->reduced_value, Variant::get_operator_name(p_binary_op->variant_op)), p_binary_op);
2777 } else {
2778 push_error(vformat(R"(Invalid operands to operator %s, %s and %s.)",
2779 Variant::get_operator_name(p_binary_op->variant_op),
2780 Variant::get_type_name(p_binary_op->left_operand->reduced_value.get_type()),
2781 Variant::get_type_name(p_binary_op->right_operand->reduced_value.get_type())),
2782 p_binary_op);
2783 }
2784 }
2785 } else {
2786 ERR_PRINT("Parser bug: unknown binary operation.");
2787 }
2788 p_binary_op->set_datatype(type_from_variant(p_binary_op->reduced_value, p_binary_op));
2789
2790 return;
2791 }
2792
2793 GDScriptParser::DataType result;
2794
2795 if ((p_binary_op->variant_op == Variant::OP_EQUAL || p_binary_op->variant_op == Variant::OP_NOT_EQUAL) &&
2796 ((left_type.kind == GDScriptParser::DataType::BUILTIN && left_type.builtin_type == Variant::NIL) || (right_type.kind == GDScriptParser::DataType::BUILTIN && right_type.builtin_type == Variant::NIL))) {
2797 // "==" and "!=" operators always return a boolean when comparing to null.
2798 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2799 result.kind = GDScriptParser::DataType::BUILTIN;
2800 result.builtin_type = Variant::BOOL;
2801 } else if (left_type.is_variant() || right_type.is_variant()) {
2802 // Cannot infer type because one operand can be anything.
2803 result.kind = GDScriptParser::DataType::VARIANT;
2804 mark_node_unsafe(p_binary_op);
2805 } else if (p_binary_op->variant_op < Variant::OP_MAX) {
2806 bool valid = false;
2807 result = get_operation_type(p_binary_op->variant_op, left_type, right_type, valid, p_binary_op);
2808 if (!valid) {
2809 push_error(vformat(R"(Invalid operands "%s" and "%s" for "%s" operator.)", left_type.to_string(), right_type.to_string(), Variant::get_operator_name(p_binary_op->variant_op)), p_binary_op);
2810 } else if (!result.is_hard_type()) {
2811 mark_node_unsafe(p_binary_op);
2812 }
2813 } else {
2814 ERR_PRINT("Parser bug: unknown binary operation.");
2815 }
2816
2817 p_binary_op->set_datatype(result);
2818}
2819
2820#ifdef SUGGEST_GODOT4_RENAMES
2821const char *get_rename_from_map(const char *map[][2], String key) {
2822 for (int index = 0; map[index][0]; index++) {
2823 if (map[index][0] == key) {
2824 return map[index][1];
2825 }
2826 }
2827 return nullptr;
2828}
2829
2830// Checks if an identifier/function name has been renamed in Godot 4, uses ProjectConverter3To4 for rename map.
2831// Returns the new name if found, nullptr otherwise.
2832const char *check_for_renamed_identifier(String identifier, GDScriptParser::Node::Type type) {
2833 switch (type) {
2834 case GDScriptParser::Node::IDENTIFIER: {
2835 // Check properties
2836 const char *result = get_rename_from_map(RenamesMap3To4::gdscript_properties_renames, identifier);
2837 if (result) {
2838 return result;
2839 }
2840 // Check enum values
2841 result = get_rename_from_map(RenamesMap3To4::enum_renames, identifier);
2842 if (result) {
2843 return result;
2844 }
2845 // Check color constants
2846 result = get_rename_from_map(RenamesMap3To4::color_renames, identifier);
2847 if (result) {
2848 return result;
2849 }
2850 // Check type names
2851 result = get_rename_from_map(RenamesMap3To4::class_renames, identifier);
2852 if (result) {
2853 return result;
2854 }
2855 return get_rename_from_map(RenamesMap3To4::builtin_types_renames, identifier);
2856 }
2857 case GDScriptParser::Node::CALL: {
2858 const char *result = get_rename_from_map(RenamesMap3To4::gdscript_function_renames, identifier);
2859 if (result) {
2860 return result;
2861 }
2862 // Built-in Types are mistaken for function calls when the built-in type is not found.
2863 // Check built-in types if function rename not found
2864 return get_rename_from_map(RenamesMap3To4::builtin_types_renames, identifier);
2865 }
2866 // Signal references don't get parsed through the GDScriptAnalyzer. No support for signal rename hints.
2867 default:
2868 // No rename found, return null
2869 return nullptr;
2870 }
2871}
2872#endif // SUGGEST_GODOT4_RENAMES
2873
2874void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_await, bool p_is_root) {
2875 bool all_is_constant = true;
2876 HashMap<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing.
2877 for (int i = 0; i < p_call->arguments.size(); i++) {
2878 reduce_expression(p_call->arguments[i]);
2879 if (p_call->arguments[i]->type == GDScriptParser::Node::ARRAY) {
2880 arrays[i] = static_cast<GDScriptParser::ArrayNode *>(p_call->arguments[i]);
2881 }
2882 all_is_constant = all_is_constant && p_call->arguments[i]->is_constant;
2883 }
2884
2885 GDScriptParser::Node::Type callee_type = p_call->get_callee_type();
2886 GDScriptParser::DataType call_type;
2887
2888 if (!p_call->is_super && callee_type == GDScriptParser::Node::IDENTIFIER) {
2889 // Call to name directly.
2890 StringName function_name = p_call->function_name;
2891 Variant::Type builtin_type = GDScriptParser::get_builtin_type(function_name);
2892
2893 if (builtin_type < Variant::VARIANT_MAX) {
2894 // Is a builtin constructor.
2895 call_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
2896 call_type.kind = GDScriptParser::DataType::BUILTIN;
2897 call_type.builtin_type = builtin_type;
2898
2899 if (builtin_type == Variant::OBJECT) {
2900 call_type.kind = GDScriptParser::DataType::NATIVE;
2901 call_type.native_type = function_name; // "Object".
2902 }
2903
2904 bool safe_to_fold = true;
2905 switch (builtin_type) {
2906 // Those are stored by reference so not suited for compile-time construction.
2907 // Because in this case they would be the same reference in all constructed values.
2908 case Variant::OBJECT:
2909 case Variant::DICTIONARY:
2910 case Variant::ARRAY:
2911 case Variant::PACKED_BYTE_ARRAY:
2912 case Variant::PACKED_INT32_ARRAY:
2913 case Variant::PACKED_INT64_ARRAY:
2914 case Variant::PACKED_FLOAT32_ARRAY:
2915 case Variant::PACKED_FLOAT64_ARRAY:
2916 case Variant::PACKED_STRING_ARRAY:
2917 case Variant::PACKED_VECTOR2_ARRAY:
2918 case Variant::PACKED_VECTOR3_ARRAY:
2919 case Variant::PACKED_COLOR_ARRAY:
2920 safe_to_fold = false;
2921 break;
2922 default:
2923 break;
2924 }
2925
2926 if (all_is_constant && safe_to_fold) {
2927 // Construct here.
2928 Vector<const Variant *> args;
2929 for (int i = 0; i < p_call->arguments.size(); i++) {
2930 args.push_back(&(p_call->arguments[i]->reduced_value));
2931 }
2932
2933 Callable::CallError err;
2934 Variant value;
2935 Variant::construct(builtin_type, value, (const Variant **)args.ptr(), args.size(), err);
2936
2937 switch (err.error) {
2938 case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
2939 push_error(vformat(R"(Invalid argument for %s constructor: argument %d should be "%s" but is "%s".)", Variant::get_type_name(builtin_type), err.argument + 1,
2940 Variant::get_type_name(Variant::Type(err.expected)), p_call->arguments[err.argument]->get_datatype().to_string()),
2941 p_call->arguments[err.argument]);
2942 break;
2943 case Callable::CallError::CALL_ERROR_INVALID_METHOD: {
2944 String signature = Variant::get_type_name(builtin_type) + "(";
2945 for (int i = 0; i < p_call->arguments.size(); i++) {
2946 if (i > 0) {
2947 signature += ", ";
2948 }
2949 signature += p_call->arguments[i]->get_datatype().to_string();
2950 }
2951 signature += ")";
2952 push_error(vformat(R"(No constructor of "%s" matches the signature "%s".)", Variant::get_type_name(builtin_type), signature), p_call->callee);
2953 } break;
2954 case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
2955 push_error(vformat(R"(Too many arguments for %s constructor. Received %d but expected %d.)", Variant::get_type_name(builtin_type), p_call->arguments.size(), err.expected), p_call);
2956 break;
2957 case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
2958 push_error(vformat(R"(Too few arguments for %s constructor. Received %d but expected %d.)", Variant::get_type_name(builtin_type), p_call->arguments.size(), err.expected), p_call);
2959 break;
2960 case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
2961 case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
2962 break; // Can't happen in a builtin constructor.
2963 case Callable::CallError::CALL_OK:
2964 p_call->is_constant = true;
2965 p_call->reduced_value = value;
2966 break;
2967 }
2968 } else {
2969 // TODO: Check constructors without constants.
2970
2971 // If there's one argument, try to use copy constructor (those aren't explicitly defined).
2972 if (p_call->arguments.size() == 1) {
2973 GDScriptParser::DataType arg_type = p_call->arguments[0]->get_datatype();
2974 if (arg_type.is_variant()) {
2975 mark_node_unsafe(p_call->arguments[0]);
2976 } else {
2977 if (arg_type.kind == GDScriptParser::DataType::BUILTIN && arg_type.builtin_type == builtin_type) {
2978 // Okay.
2979 p_call->set_datatype(call_type);
2980 return;
2981 }
2982 }
2983 }
2984 List<MethodInfo> constructors;
2985 Variant::get_constructor_list(builtin_type, &constructors);
2986 bool match = false;
2987
2988 for (const MethodInfo &info : constructors) {
2989 if (p_call->arguments.size() < info.arguments.size() - info.default_arguments.size()) {
2990 continue;
2991 }
2992 if (p_call->arguments.size() > info.arguments.size()) {
2993 continue;
2994 }
2995
2996 bool types_match = true;
2997
2998 for (int i = 0; i < p_call->arguments.size(); i++) {
2999 GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
3000
3001 if (!is_type_compatible(par_type, p_call->arguments[i]->get_datatype(), true)) {
3002 types_match = false;
3003 break;
3004#ifdef DEBUG_ENABLED
3005 } else {
3006 if (par_type.builtin_type == Variant::INT && p_call->arguments[i]->get_datatype().builtin_type == Variant::FLOAT && builtin_type != Variant::INT) {
3007 parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, p_call->function_name);
3008 }
3009#endif
3010 }
3011 }
3012
3013 if (types_match) {
3014 for (int i = 0; i < p_call->arguments.size(); i++) {
3015 if (p_call->arguments[i]->is_constant) {
3016 update_const_expression_builtin_type(p_call->arguments[i], type_from_property(info.arguments[i], true), "pass");
3017 }
3018 }
3019 match = true;
3020 call_type = type_from_property(info.return_val);
3021 break;
3022 }
3023 }
3024
3025 if (!match) {
3026 String signature = Variant::get_type_name(builtin_type) + "(";
3027 for (int i = 0; i < p_call->arguments.size(); i++) {
3028 if (i > 0) {
3029 signature += ", ";
3030 }
3031 signature += p_call->arguments[i]->get_datatype().to_string();
3032 }
3033 signature += ")";
3034 push_error(vformat(R"(No constructor of "%s" matches the signature "%s".)", Variant::get_type_name(builtin_type), signature), p_call);
3035 }
3036 }
3037 p_call->set_datatype(call_type);
3038 return;
3039 } else if (GDScriptUtilityFunctions::function_exists(function_name)) {
3040 MethodInfo function_info = GDScriptUtilityFunctions::get_function_info(function_name);
3041
3042 if (!p_is_root && !p_is_await && function_info.return_val.type == Variant::NIL && ((function_info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) == 0)) {
3043 push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
3044 }
3045
3046 if (all_is_constant && GDScriptUtilityFunctions::is_function_constant(function_name)) {
3047 // Can call on compilation.
3048 Vector<const Variant *> args;
3049 for (int i = 0; i < p_call->arguments.size(); i++) {
3050 args.push_back(&(p_call->arguments[i]->reduced_value));
3051 }
3052
3053 Variant value;
3054 Callable::CallError err;
3055 GDScriptUtilityFunctions::get_function(function_name)(&value, (const Variant **)args.ptr(), args.size(), err);
3056
3057 switch (err.error) {
3058 case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
3059 PropertyInfo wrong_arg = function_info.arguments[err.argument];
3060 push_error(vformat(R"*(Invalid argument for "%s()" function: argument %d should be "%s" but is "%s".)*", function_name, err.argument + 1,
3061 type_from_property(wrong_arg, true).to_string(), p_call->arguments[err.argument]->get_datatype().to_string()),
3062 p_call->arguments[err.argument]);
3063 } break;
3064 case Callable::CallError::CALL_ERROR_INVALID_METHOD:
3065 push_error(vformat(R"(Invalid call for function "%s".)", function_name), p_call);
3066 break;
3067 case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
3068 push_error(vformat(R"*(Too many arguments for "%s()" call. Expected at most %d but received %d.)*", function_name, err.expected, p_call->arguments.size()), p_call);
3069 break;
3070 case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
3071 push_error(vformat(R"*(Too few arguments for "%s()" call. Expected at least %d but received %d.)*", function_name, err.expected, p_call->arguments.size()), p_call);
3072 break;
3073 case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
3074 case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
3075 break; // Can't happen in a builtin constructor.
3076 case Callable::CallError::CALL_OK:
3077 p_call->is_constant = true;
3078 p_call->reduced_value = value;
3079 break;
3080 }
3081 } else {
3082 validate_call_arg(function_info, p_call);
3083 }
3084 p_call->set_datatype(type_from_property(function_info.return_val));
3085 return;
3086 } else if (Variant::has_utility_function(function_name)) {
3087 MethodInfo function_info = info_from_utility_func(function_name);
3088
3089 if (!p_is_root && !p_is_await && function_info.return_val.type == Variant::NIL && ((function_info.return_val.usage & PROPERTY_USAGE_NIL_IS_VARIANT) == 0)) {
3090 push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
3091 }
3092
3093 if (all_is_constant && Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH) {
3094 // Can call on compilation.
3095 Vector<const Variant *> args;
3096 for (int i = 0; i < p_call->arguments.size(); i++) {
3097 args.push_back(&(p_call->arguments[i]->reduced_value));
3098 }
3099
3100 Variant value;
3101 Callable::CallError err;
3102 Variant::call_utility_function(function_name, &value, (const Variant **)args.ptr(), args.size(), err);
3103
3104 switch (err.error) {
3105 case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT: {
3106 String expected_type_name;
3107 if (err.argument < function_info.arguments.size()) {
3108 expected_type_name = type_from_property(function_info.arguments[err.argument], true).to_string();
3109 } else {
3110 expected_type_name = Variant::get_type_name((Variant::Type)err.expected);
3111 }
3112
3113 push_error(vformat(R"*(Invalid argument for "%s()" function: argument %d should be "%s" but is "%s".)*", function_name, err.argument + 1,
3114 expected_type_name, p_call->arguments[err.argument]->get_datatype().to_string()),
3115 p_call->arguments[err.argument]);
3116 } break;
3117 case Callable::CallError::CALL_ERROR_INVALID_METHOD:
3118 push_error(vformat(R"(Invalid call for function "%s".)", function_name), p_call);
3119 break;
3120 case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
3121 push_error(vformat(R"*(Too many arguments for "%s()" call. Expected at most %d but received %d.)*", function_name, err.expected, p_call->arguments.size()), p_call);
3122 break;
3123 case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
3124 push_error(vformat(R"*(Too few arguments for "%s()" call. Expected at least %d but received %d.)*", function_name, err.expected, p_call->arguments.size()), p_call);
3125 break;
3126 case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
3127 case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
3128 break; // Can't happen in a builtin constructor.
3129 case Callable::CallError::CALL_OK:
3130 p_call->is_constant = true;
3131 p_call->reduced_value = value;
3132 break;
3133 }
3134 } else {
3135 validate_call_arg(function_info, p_call);
3136 }
3137 p_call->set_datatype(type_from_property(function_info.return_val));
3138 return;
3139 }
3140 }
3141
3142 GDScriptParser::DataType base_type;
3143 call_type.kind = GDScriptParser::DataType::VARIANT;
3144 bool is_self = false;
3145
3146 if (p_call->is_super) {
3147 base_type = parser->current_class->base_type;
3148 base_type.is_meta_type = false;
3149 is_self = true;
3150
3151 if (p_call->callee == nullptr && current_lambda != nullptr) {
3152 push_error("Cannot use `super()` inside a lambda.", p_call);
3153 }
3154 } else if (callee_type == GDScriptParser::Node::IDENTIFIER) {
3155 base_type = parser->current_class->get_datatype();
3156 base_type.is_meta_type = false;
3157 is_self = true;
3158 } else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
3159 GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee);
3160 if (subscript->base == nullptr) {
3161 // Invalid syntax, error already set on parser.
3162 p_call->set_datatype(call_type);
3163 mark_node_unsafe(p_call);
3164 return;
3165 }
3166 if (!subscript->is_attribute) {
3167 // Invalid call. Error already sent in parser.
3168 // TODO: Could check if Callable here.
3169 p_call->set_datatype(call_type);
3170 mark_node_unsafe(p_call);
3171 return;
3172 }
3173 if (subscript->attribute == nullptr) {
3174 // Invalid call. Error already sent in parser.
3175 p_call->set_datatype(call_type);
3176 mark_node_unsafe(p_call);
3177 return;
3178 }
3179
3180 GDScriptParser::IdentifierNode *base_id = nullptr;
3181 if (subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
3182 base_id = static_cast<GDScriptParser::IdentifierNode *>(subscript->base);
3183 }
3184 if (base_id && GDScriptParser::get_builtin_type(base_id->name) < Variant::VARIANT_MAX) {
3185 base_type = make_builtin_meta_type(GDScriptParser::get_builtin_type(base_id->name));
3186 } else {
3187 reduce_expression(subscript->base);
3188 base_type = subscript->base->get_datatype();
3189 is_self = subscript->base->type == GDScriptParser::Node::SELF;
3190 }
3191 } else {
3192 // Invalid call. Error already sent in parser.
3193 // TODO: Could check if Callable here too.
3194 p_call->set_datatype(call_type);
3195 mark_node_unsafe(p_call);
3196 return;
3197 }
3198
3199 int default_arg_count = 0;
3200 BitField<MethodFlags> method_flags;
3201 GDScriptParser::DataType return_type;
3202 List<GDScriptParser::DataType> par_types;
3203
3204 bool is_constructor = (base_type.is_meta_type || (p_call->callee && p_call->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_call->function_name == SNAME("new");
3205
3206 if (get_function_signature(p_call, is_constructor, base_type, p_call->function_name, return_type, par_types, default_arg_count, method_flags)) {
3207 // If the function require typed arrays we must make literals be typed.
3208 for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) {
3209 int index = E.key;
3210 if (index < par_types.size() && par_types[index].has_container_element_type()) {
3211 update_array_literal_element_type(E.value, par_types[index].get_container_element_type());
3212 }
3213 }
3214 validate_call_arg(par_types, default_arg_count, method_flags.has_flag(METHOD_FLAG_VARARG), p_call);
3215
3216 if (base_type.kind == GDScriptParser::DataType::ENUM && base_type.is_meta_type) {
3217 // Enum type is treated as a dictionary value for function calls.
3218 base_type.is_meta_type = false;
3219 }
3220
3221 if (is_self && static_context && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
3222 if (parser->current_function) {
3223 // Get the parent function above any lambda.
3224 GDScriptParser::FunctionNode *parent_function = parser->current_function;
3225 while (parent_function->source_lambda) {
3226 parent_function = parent_function->source_lambda->parent_function;
3227 }
3228 push_error(vformat(R"*(Cannot call non-static function "%s()" from static function "%s()".)*", p_call->function_name, parent_function->identifier->name), p_call);
3229 } else {
3230 push_error(vformat(R"*(Cannot call non-static function "%s()" for static variable initializer.)*", p_call->function_name), p_call);
3231 }
3232 } else if (!is_self && base_type.is_meta_type && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
3233 base_type.is_meta_type = false; // For `to_string()`.
3234 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);
3235 } else if (is_self && !method_flags.has_flag(METHOD_FLAG_STATIC)) {
3236 mark_lambda_use_self();
3237 }
3238
3239 if (!p_is_root && !p_is_await && return_type.is_hard_type() && return_type.kind == GDScriptParser::DataType::BUILTIN && return_type.builtin_type == Variant::NIL) {
3240 push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", p_call->function_name), p_call);
3241 }
3242
3243#ifdef DEBUG_ENABLED
3244 if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL &&
3245 !(p_call->is_super && p_call->function_name == GDScriptLanguage::get_singleton()->strings._init)) {
3246 parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
3247 }
3248
3249 if (method_flags.has_flag(METHOD_FLAG_STATIC) && !is_constructor && !base_type.is_meta_type && !(is_self && static_context)) {
3250 String caller_type = String(base_type.native_type);
3251
3252 if (caller_type.is_empty()) {
3253 caller_type = base_type.to_string();
3254 }
3255
3256 parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, caller_type);
3257 }
3258#endif // DEBUG_ENABLED
3259
3260 call_type = return_type;
3261 } else {
3262 bool found = false;
3263
3264 // Enums do not have functions other than the built-in dictionary ones.
3265 if (base_type.kind == GDScriptParser::DataType::ENUM && base_type.is_meta_type) {
3266 if (base_type.builtin_type == Variant::DICTIONARY) {
3267 push_error(vformat(R"*(Enums only have Dictionary built-in methods. Function "%s()" does not exist for enum "%s".)*", p_call->function_name, base_type.enum_type), p_call->callee);
3268 } else {
3269 push_error(vformat(R"*(The native enum "%s" does not behave like Dictionary and does not have methods of its own.)*", base_type.enum_type), p_call->callee);
3270 }
3271 } else if (!p_call->is_super && callee_type != GDScriptParser::Node::NONE) { // Check if the name exists as something else.
3272 GDScriptParser::IdentifierNode *callee_id;
3273 if (callee_type == GDScriptParser::Node::IDENTIFIER) {
3274 callee_id = static_cast<GDScriptParser::IdentifierNode *>(p_call->callee);
3275 } else {
3276 // Can only be attribute.
3277 callee_id = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee)->attribute;
3278 }
3279 if (callee_id) {
3280 reduce_identifier_from_base(callee_id, &base_type);
3281 GDScriptParser::DataType callee_datatype = callee_id->get_datatype();
3282 if (callee_datatype.is_set() && !callee_datatype.is_variant()) {
3283 found = true;
3284 if (callee_datatype.builtin_type == Variant::CALLABLE) {
3285 push_error(vformat(R"*(Name "%s" is a Callable. You can call it with "%s.call()" instead.)*", p_call->function_name, p_call->function_name), p_call->callee);
3286 } else {
3287 push_error(vformat(R"*(Name "%s" called as a function but is a "%s".)*", p_call->function_name, callee_datatype.to_string()), p_call->callee);
3288 }
3289#ifdef DEBUG_ENABLED
3290 } else if (!is_self && !(base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::BUILTIN)) {
3291 parser->push_warning(p_call, GDScriptWarning::UNSAFE_METHOD_ACCESS, p_call->function_name, base_type.to_string());
3292 mark_node_unsafe(p_call);
3293#endif
3294 }
3295 }
3296 }
3297 if (!found && (is_self || (base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::BUILTIN))) {
3298 String base_name = is_self && !p_call->is_super ? "self" : base_type.to_string();
3299#ifdef SUGGEST_GODOT4_RENAMES
3300 String rename_hint = String();
3301 if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GODOT_4_HINT)).booleanize()) {
3302 const char *renamed_function_name = check_for_renamed_identifier(p_call->function_name, p_call->type);
3303 if (renamed_function_name) {
3304 rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", String(renamed_function_name) + "()");
3305 }
3306 }
3307 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);
3308#else
3309 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);
3310#endif // SUGGEST_GODOT4_RENAMES
3311 } else if (!found && (!p_call->is_super && base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::NATIVE && base_type.is_meta_type)) {
3312 push_error(vformat(R"*(Static function "%s()" not found in base "%s".)*", p_call->function_name, base_type.native_type), p_call);
3313 }
3314 }
3315
3316 if (call_type.is_coroutine && !p_is_await && !p_is_root) {
3317 push_error(vformat(R"*(Function "%s()" is a coroutine, so it must be called with "await".)*", p_call->function_name), p_call);
3318 }
3319
3320 p_call->set_datatype(call_type);
3321}
3322
3323void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
3324 reduce_expression(p_cast->operand);
3325
3326 GDScriptParser::DataType cast_type = type_from_metatype(resolve_datatype(p_cast->cast_type));
3327
3328 if (!cast_type.is_set()) {
3329 mark_node_unsafe(p_cast);
3330 return;
3331 }
3332
3333 p_cast->set_datatype(cast_type);
3334 if (p_cast->operand->is_constant) {
3335 update_const_expression_builtin_type(p_cast->operand, cast_type, "cast", true);
3336 if (cast_type.is_variant() || p_cast->operand->get_datatype() == cast_type) {
3337 p_cast->is_constant = true;
3338 p_cast->reduced_value = p_cast->operand->reduced_value;
3339 }
3340 }
3341
3342 if (p_cast->operand->type == GDScriptParser::Node::ARRAY && cast_type.has_container_element_type()) {
3343 update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_cast->operand), cast_type.get_container_element_type());
3344 }
3345
3346 if (!cast_type.is_variant()) {
3347 GDScriptParser::DataType op_type = p_cast->operand->get_datatype();
3348 if (op_type.is_variant() || !op_type.is_hard_type()) {
3349 mark_node_unsafe(p_cast);
3350#ifdef DEBUG_ENABLED
3351 if (op_type.is_variant() && !op_type.is_hard_type()) {
3352 parser->push_warning(p_cast, GDScriptWarning::UNSAFE_CAST, cast_type.to_string());
3353 }
3354#endif
3355 } else {
3356 bool valid = false;
3357 if (op_type.builtin_type == Variant::INT && cast_type.kind == GDScriptParser::DataType::ENUM) {
3358 mark_node_unsafe(p_cast);
3359 valid = true;
3360 } else if (op_type.kind == GDScriptParser::DataType::BUILTIN && cast_type.kind == GDScriptParser::DataType::BUILTIN) {
3361 valid = Variant::can_convert(op_type.builtin_type, cast_type.builtin_type);
3362 } else if (op_type.kind != GDScriptParser::DataType::BUILTIN && cast_type.kind != GDScriptParser::DataType::BUILTIN) {
3363 valid = is_type_compatible(cast_type, op_type) || is_type_compatible(op_type, cast_type);
3364 }
3365
3366 if (!valid) {
3367 push_error(vformat(R"(Invalid cast. Cannot convert from "%s" to "%s".)", op_type.to_string(), cast_type.to_string()), p_cast->cast_type);
3368 }
3369 }
3370 }
3371}
3372
3373void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
3374 HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, StringLikeVariantComparator> elements;
3375
3376 for (int i = 0; i < p_dictionary->elements.size(); i++) {
3377 const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
3378 if (p_dictionary->style == GDScriptParser::DictionaryNode::PYTHON_DICT) {
3379 reduce_expression(element.key);
3380 }
3381 reduce_expression(element.value);
3382
3383 if (element.key->is_constant) {
3384 if (elements.has(element.key->reduced_value)) {
3385 push_error(vformat(R"(Key "%s" was already used in this dictionary (at line %d).)", element.key->reduced_value, elements[element.key->reduced_value]->start_line), element.key);
3386 } else {
3387 elements[element.key->reduced_value] = element.value;
3388 }
3389 }
3390 }
3391
3392 // It's dictionary in any case.
3393 GDScriptParser::DataType dict_type;
3394 dict_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3395 dict_type.kind = GDScriptParser::DataType::BUILTIN;
3396 dict_type.builtin_type = Variant::DICTIONARY;
3397 dict_type.is_constant = true;
3398
3399 p_dictionary->set_datatype(dict_type);
3400}
3401
3402void GDScriptAnalyzer::reduce_get_node(GDScriptParser::GetNodeNode *p_get_node) {
3403 GDScriptParser::DataType result;
3404 result.kind = GDScriptParser::DataType::VARIANT;
3405
3406 if (!ClassDB::is_parent_class(parser->current_class->base_type.native_type, SNAME("Node"))) {
3407 push_error(vformat(R"*(Cannot use shorthand "get_node()" notation ("%c") on a class that isn't a node.)*", p_get_node->use_dollar ? '$' : '%'), p_get_node);
3408 p_get_node->set_datatype(result);
3409 return;
3410 }
3411
3412 if (static_context) {
3413 push_error(vformat(R"*(Cannot use shorthand "get_node()" notation ("%c") in a static function.)*", p_get_node->use_dollar ? '$' : '%'), p_get_node);
3414 p_get_node->set_datatype(result);
3415 return;
3416 }
3417
3418 mark_lambda_use_self();
3419
3420 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3421 result.kind = GDScriptParser::DataType::NATIVE;
3422 result.builtin_type = Variant::OBJECT;
3423 result.native_type = SNAME("Node");
3424 p_get_node->set_datatype(result);
3425}
3426
3427GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const StringName &p_class_name, const GDScriptParser::Node *p_source) {
3428 GDScriptParser::DataType type;
3429
3430 String path = ScriptServer::get_global_class_path(p_class_name);
3431 String ext = path.get_extension();
3432 if (ext == GDScriptLanguage::get_singleton()->get_extension()) {
3433 Ref<GDScriptParserRef> ref = get_parser_for(path);
3434 if (ref.is_null()) {
3435 push_error(vformat(R"(Could not find script for class "%s".)", p_class_name), p_source);
3436 type.type_source = GDScriptParser::DataType::UNDETECTED;
3437 type.kind = GDScriptParser::DataType::VARIANT;
3438 return type;
3439 }
3440
3441 Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
3442 if (err) {
3443 push_error(vformat(R"(Could not resolve class "%s", because of a parser error.)", p_class_name), p_source);
3444 type.type_source = GDScriptParser::DataType::UNDETECTED;
3445 type.kind = GDScriptParser::DataType::VARIANT;
3446 return type;
3447 }
3448
3449 return ref->get_parser()->head->get_datatype();
3450 } else {
3451 return make_script_meta_type(ResourceLoader::load(path, "Script"));
3452 }
3453}
3454
3455void GDScriptAnalyzer::reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype) {
3456 ERR_FAIL_NULL(p_identifier);
3457
3458 p_identifier->set_datatype(p_identifier_datatype);
3459 Error err = OK;
3460 Ref<GDScript> scr = GDScriptCache::get_shallow_script(p_identifier_datatype.script_path, err, parser->script_path);
3461 if (err) {
3462 push_error(vformat(R"(Error while getting cache for script "%s".)", p_identifier_datatype.script_path), p_identifier);
3463 return;
3464 }
3465 p_identifier->reduced_value = scr->find_class(p_identifier_datatype.class_type->fqcn);
3466 p_identifier->is_constant = true;
3467}
3468
3469void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType *p_base) {
3470 if (!p_identifier->get_datatype().has_no_type()) {
3471 return;
3472 }
3473
3474 GDScriptParser::DataType base;
3475 if (p_base == nullptr) {
3476 base = type_from_metatype(parser->current_class->get_datatype());
3477 } else {
3478 base = *p_base;
3479 }
3480
3481 StringName name = p_identifier->name;
3482
3483 if (base.kind == GDScriptParser::DataType::ENUM) {
3484 if (base.is_meta_type) {
3485 if (base.enum_values.has(name)) {
3486 p_identifier->set_datatype(type_from_metatype(base));
3487 p_identifier->is_constant = true;
3488 p_identifier->reduced_value = base.enum_values[name];
3489 return;
3490 }
3491
3492 // Enum does not have this value, return.
3493 return;
3494 } else {
3495 push_error(R"(Cannot get property from enum value.)", p_identifier);
3496 return;
3497 }
3498 }
3499
3500 if (base.kind == GDScriptParser::DataType::BUILTIN) {
3501 if (base.is_meta_type) {
3502 bool valid = true;
3503 Variant result = Variant::get_constant_value(base.builtin_type, name, &valid);
3504 if (valid) {
3505 p_identifier->is_constant = true;
3506 p_identifier->reduced_value = result;
3507 p_identifier->set_datatype(type_from_variant(result, p_identifier));
3508 } else if (base.is_hard_type()) {
3509#ifdef SUGGEST_GODOT4_RENAMES
3510 String rename_hint = String();
3511 if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GODOT_4_HINT)).booleanize()) {
3512 const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
3513 if (renamed_identifier_name) {
3514 rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name);
3515 }
3516 }
3517 push_error(vformat(R"(Cannot find constant "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier);
3518#else
3519 push_error(vformat(R"(Cannot find constant "%s" on base "%s".)", name, base.to_string()), p_identifier);
3520#endif // SUGGEST_GODOT4_RENAMES
3521 }
3522 } else {
3523 switch (base.builtin_type) {
3524 case Variant::NIL: {
3525 if (base.is_hard_type()) {
3526 push_error(vformat(R"(Invalid get index "%s" on base Nil)", name), p_identifier);
3527 }
3528 return;
3529 }
3530 case Variant::DICTIONARY: {
3531 GDScriptParser::DataType dummy;
3532 dummy.kind = GDScriptParser::DataType::VARIANT;
3533 p_identifier->set_datatype(dummy);
3534 return;
3535 }
3536 default: {
3537 Callable::CallError temp;
3538 Variant dummy;
3539 Variant::construct(base.builtin_type, dummy, nullptr, 0, temp);
3540 List<PropertyInfo> properties;
3541 dummy.get_property_list(&properties);
3542 for (const PropertyInfo &prop : properties) {
3543 if (prop.name == name) {
3544 p_identifier->set_datatype(type_from_property(prop));
3545 return;
3546 }
3547 }
3548 if (base.is_hard_type()) {
3549#ifdef SUGGEST_GODOT4_RENAMES
3550 String rename_hint = String();
3551 if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GODOT_4_HINT)).booleanize()) {
3552 const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
3553 if (renamed_identifier_name) {
3554 rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name);
3555 }
3556 }
3557 push_error(vformat(R"(Cannot find property "%s" on base "%s".%s)", name, base.to_string(), rename_hint), p_identifier);
3558#else
3559 push_error(vformat(R"(Cannot find property "%s" on base "%s".)", name, base.to_string()), p_identifier);
3560#endif // SUGGEST_GODOT4_RENAMES
3561 }
3562 }
3563 }
3564 }
3565 return;
3566 }
3567
3568 GDScriptParser::ClassNode *base_class = base.class_type;
3569 List<GDScriptParser::ClassNode *> script_classes;
3570 bool is_base = true;
3571
3572 if (base_class != nullptr) {
3573 get_class_node_current_scope_classes(base_class, &script_classes);
3574 }
3575
3576 bool is_constructor = base.is_meta_type && p_identifier->name == SNAME("new");
3577
3578 for (GDScriptParser::ClassNode *script_class : script_classes) {
3579 if (p_base == nullptr && script_class->identifier && script_class->identifier->name == name) {
3580 reduce_identifier_from_base_set_class(p_identifier, script_class->get_datatype());
3581 if (script_class->outer != nullptr) {
3582 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
3583 }
3584 return;
3585 }
3586
3587 if (is_constructor) {
3588 name = "_init";
3589 }
3590
3591 if (script_class->has_member(name)) {
3592 resolve_class_member(script_class, name, p_identifier);
3593
3594 GDScriptParser::ClassNode::Member member = script_class->get_member(name);
3595 switch (member.type) {
3596 case GDScriptParser::ClassNode::Member::CONSTANT: {
3597 p_identifier->set_datatype(member.get_datatype());
3598 p_identifier->is_constant = true;
3599 p_identifier->reduced_value = member.constant->initializer->reduced_value;
3600 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
3601 p_identifier->constant_source = member.constant;
3602 return;
3603 }
3604
3605 case GDScriptParser::ClassNode::Member::ENUM_VALUE: {
3606 p_identifier->set_datatype(member.get_datatype());
3607 p_identifier->is_constant = true;
3608 p_identifier->reduced_value = member.enum_value.value;
3609 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
3610 return;
3611 }
3612
3613 case GDScriptParser::ClassNode::Member::ENUM: {
3614 p_identifier->set_datatype(member.get_datatype());
3615 p_identifier->is_constant = true;
3616 p_identifier->reduced_value = member.m_enum->dictionary;
3617 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
3618 return;
3619 }
3620
3621 case GDScriptParser::ClassNode::Member::VARIABLE: {
3622 if (is_base && (!base.is_meta_type || member.variable->is_static)) {
3623 p_identifier->set_datatype(member.get_datatype());
3624 p_identifier->source = member.variable->is_static ? GDScriptParser::IdentifierNode::STATIC_VARIABLE : GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
3625 p_identifier->variable_source = member.variable;
3626 member.variable->usages += 1;
3627 return;
3628 }
3629 } break;
3630
3631 case GDScriptParser::ClassNode::Member::SIGNAL: {
3632 if (is_base && !base.is_meta_type) {
3633 p_identifier->set_datatype(member.get_datatype());
3634 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
3635 return;
3636 }
3637 } break;
3638
3639 case GDScriptParser::ClassNode::Member::FUNCTION: {
3640 if (is_base && (!base.is_meta_type || member.function->is_static)) {
3641 p_identifier->set_datatype(make_callable_type(member.function->info));
3642 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_FUNCTION;
3643 return;
3644 }
3645 } break;
3646
3647 case GDScriptParser::ClassNode::Member::CLASS: {
3648 reduce_identifier_from_base_set_class(p_identifier, member.get_datatype());
3649 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
3650 return;
3651 }
3652
3653 default: {
3654 // Do nothing
3655 }
3656 }
3657 }
3658
3659 if (is_base) {
3660 is_base = script_class->base_type.class_type != nullptr;
3661 if (!is_base && p_base != nullptr) {
3662 break;
3663 }
3664 }
3665 }
3666
3667 // Check native members. No need for native class recursion because Node exposes all Object's properties.
3668 const StringName &native = base.native_type;
3669
3670 if (class_exists(native)) {
3671 if (is_constructor) {
3672 name = "_init";
3673 }
3674
3675 MethodInfo method_info;
3676 if (ClassDB::has_property(native, name)) {
3677 StringName getter_name = ClassDB::get_property_getter(native, name);
3678 MethodBind *getter = ClassDB::get_method(native, getter_name);
3679 if (getter != nullptr) {
3680 bool has_setter = ClassDB::get_property_setter(native, name) != StringName();
3681 p_identifier->set_datatype(type_from_property(getter->get_return_info(), false, !has_setter));
3682 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
3683 }
3684 return;
3685 }
3686 if (ClassDB::get_method_info(native, name, &method_info)) {
3687 // Method is callable.
3688 p_identifier->set_datatype(make_callable_type(method_info));
3689 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
3690 return;
3691 }
3692 if (ClassDB::get_signal(native, name, &method_info)) {
3693 // Signal is a type too.
3694 p_identifier->set_datatype(make_signal_type(method_info));
3695 p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
3696 return;
3697 }
3698 if (ClassDB::has_enum(native, name)) {
3699 p_identifier->set_datatype(make_native_enum_type(name, native));
3700 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
3701 return;
3702 }
3703 bool valid = false;
3704
3705 int64_t int_constant = ClassDB::get_integer_constant(native, name, &valid);
3706 if (valid) {
3707 p_identifier->is_constant = true;
3708 p_identifier->reduced_value = int_constant;
3709 p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
3710
3711 // Check whether this constant, which exists, belongs to an enum
3712 StringName enum_name = ClassDB::get_integer_constant_enum(native, name);
3713 if (enum_name != StringName()) {
3714 p_identifier->set_datatype(make_native_enum_type(enum_name, native, false));
3715 } else {
3716 p_identifier->set_datatype(type_from_variant(int_constant, p_identifier));
3717 }
3718 }
3719 }
3720}
3721
3722void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_identifier, bool can_be_builtin) {
3723 // TODO: This is an opportunity to further infer types.
3724
3725 // Check if we are inside an enum. This allows enum values to access other elements of the same enum.
3726 if (current_enum) {
3727 for (int i = 0; i < current_enum->values.size(); i++) {
3728 const GDScriptParser::EnumNode::Value &element = current_enum->values[i];
3729 if (element.identifier->name == p_identifier->name) {
3730 StringName enum_name = current_enum->identifier ? current_enum->identifier->name : UNNAMED_ENUM;
3731 GDScriptParser::DataType type = make_enum_type(enum_name, parser->current_class->fqcn, false);
3732 if (element.parent_enum->identifier) {
3733 type.enum_type = element.parent_enum->identifier->name;
3734 }
3735 p_identifier->set_datatype(type);
3736
3737 if (element.resolved) {
3738 p_identifier->is_constant = true;
3739 p_identifier->reduced_value = element.value;
3740 } else {
3741 push_error(R"(Cannot use another enum element before it was declared.)", p_identifier);
3742 }
3743 return; // Found anyway.
3744 }
3745 }
3746 }
3747
3748 bool found_source = false;
3749 // Check if identifier is local.
3750 // If that's the case, the declaration already was solved before.
3751 switch (p_identifier->source) {
3752 case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER:
3753 p_identifier->set_datatype(p_identifier->parameter_source->get_datatype());
3754 found_source = true;
3755 break;
3756 case GDScriptParser::IdentifierNode::LOCAL_CONSTANT:
3757 case GDScriptParser::IdentifierNode::MEMBER_CONSTANT:
3758 p_identifier->set_datatype(p_identifier->constant_source->get_datatype());
3759 p_identifier->is_constant = true;
3760 // TODO: Constant should have a value on the node itself.
3761 p_identifier->reduced_value = p_identifier->constant_source->initializer->reduced_value;
3762 found_source = true;
3763 break;
3764 case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
3765 case GDScriptParser::IdentifierNode::INHERITED_VARIABLE:
3766 mark_lambda_use_self();
3767 break;
3768 case GDScriptParser::IdentifierNode::MEMBER_VARIABLE:
3769 mark_lambda_use_self();
3770 p_identifier->variable_source->usages++;
3771 [[fallthrough]];
3772 case GDScriptParser::IdentifierNode::STATIC_VARIABLE:
3773 case GDScriptParser::IdentifierNode::LOCAL_VARIABLE:
3774 p_identifier->set_datatype(p_identifier->variable_source->get_datatype());
3775 found_source = true;
3776 break;
3777 case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
3778 p_identifier->set_datatype(p_identifier->bind_source->get_datatype());
3779 found_source = true;
3780 break;
3781 case GDScriptParser::IdentifierNode::LOCAL_BIND: {
3782 GDScriptParser::DataType result = p_identifier->bind_source->get_datatype();
3783 result.is_constant = true;
3784 p_identifier->set_datatype(result);
3785 found_source = true;
3786 } break;
3787 case GDScriptParser::IdentifierNode::UNDEFINED_SOURCE:
3788 case GDScriptParser::IdentifierNode::MEMBER_FUNCTION:
3789 case GDScriptParser::IdentifierNode::MEMBER_CLASS:
3790 break;
3791 }
3792
3793#ifdef DEBUG_ENABLED
3794 if (!found_source && p_identifier->suite != nullptr && p_identifier->suite->has_local(p_identifier->name)) {
3795 parser->push_warning(p_identifier, GDScriptWarning::CONFUSABLE_LOCAL_USAGE, p_identifier->name);
3796 }
3797#endif
3798
3799 // Not a local, so check members.
3800 if (!found_source) {
3801 reduce_identifier_from_base(p_identifier);
3802 if (p_identifier->source != GDScriptParser::IdentifierNode::UNDEFINED_SOURCE || p_identifier->get_datatype().is_set()) {
3803 // Found.
3804 found_source = true;
3805 }
3806 }
3807
3808 if (found_source) {
3809 bool source_is_variable = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_VARIABLE || p_identifier->source == GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
3810 bool source_is_signal = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
3811 if ((source_is_variable || source_is_signal) && static_context) {
3812 if (parser->current_function) {
3813 // Get the parent function above any lambda.
3814 GDScriptParser::FunctionNode *parent_function = parser->current_function;
3815 while (parent_function->source_lambda) {
3816 parent_function = parent_function->source_lambda->parent_function;
3817 }
3818 push_error(vformat(R"*(Cannot access %s "%s" from the static function "%s()".)*", source_is_signal ? "signal" : "instance variable", p_identifier->name, parent_function->identifier->name), p_identifier);
3819 } else {
3820 push_error(vformat(R"*(Cannot access %s "%s" for a static variable initializer.)*", source_is_signal ? "signal" : "instance variable", p_identifier->name), p_identifier);
3821 }
3822 }
3823
3824 if (current_lambda != nullptr) {
3825 // If the identifier is a member variable (including the native class properties) or a signal, we consider the lambda to be using `self`, so we keep a reference to the current instance.
3826 if (source_is_variable || source_is_signal) {
3827 mark_lambda_use_self();
3828 return; // No need to capture.
3829 }
3830 // If the identifier is local, check if it's any kind of capture by comparing their source function.
3831 // Only capture locals and enum values. Constants are still accessible from the lambda using the script reference. If not, this method is done.
3832 if (p_identifier->source == GDScriptParser::IdentifierNode::UNDEFINED_SOURCE || p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_CONSTANT) {
3833 return;
3834 }
3835
3836 GDScriptParser::FunctionNode *function_test = current_lambda->function;
3837 // Make sure we aren't capturing variable in the same lambda.
3838 // This also add captures for nested lambdas.
3839 while (function_test != nullptr && function_test != p_identifier->source_function && function_test->source_lambda != nullptr && !function_test->source_lambda->captures_indices.has(p_identifier->name)) {
3840 function_test->source_lambda->captures_indices[p_identifier->name] = function_test->source_lambda->captures.size();
3841 function_test->source_lambda->captures.push_back(p_identifier);
3842 function_test = function_test->source_lambda->parent_function;
3843 }
3844 }
3845
3846 return;
3847 }
3848
3849 StringName name = p_identifier->name;
3850 p_identifier->source = GDScriptParser::IdentifierNode::UNDEFINED_SOURCE;
3851
3852 // Check globals. We make an exception for Variant::OBJECT because it's the base class for
3853 // non-builtin types so we allow doing e.g. Object.new()
3854 Variant::Type builtin_type = GDScriptParser::get_builtin_type(name);
3855 if (builtin_type != Variant::OBJECT && builtin_type < Variant::VARIANT_MAX) {
3856 if (can_be_builtin) {
3857 p_identifier->set_datatype(make_builtin_meta_type(builtin_type));
3858 return;
3859 } else {
3860 push_error(R"(Builtin type cannot be used as a name on its own.)", p_identifier);
3861 }
3862 }
3863
3864 if (class_exists(name)) {
3865 p_identifier->set_datatype(make_native_meta_type(name));
3866 return;
3867 }
3868
3869 if (ScriptServer::is_global_class(name)) {
3870 p_identifier->set_datatype(make_global_class_meta_type(name, p_identifier));
3871 return;
3872 }
3873
3874 // Try singletons.
3875 // Do this before globals because this might be a singleton loading another one before it's compiled.
3876 if (ProjectSettings::get_singleton()->has_autoload(name)) {
3877 const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(name);
3878 if (autoload.is_singleton) {
3879 // Singleton exists, so it's at least a Node.
3880 GDScriptParser::DataType result;
3881 result.kind = GDScriptParser::DataType::NATIVE;
3882 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3883 if (ResourceLoader::get_resource_type(autoload.path) == "GDScript") {
3884 Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path);
3885 if (singl_parser.is_valid()) {
3886 Error err = singl_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
3887 if (err == OK) {
3888 result = type_from_metatype(singl_parser->get_parser()->head->get_datatype());
3889 }
3890 }
3891 } else if (ResourceLoader::get_resource_type(autoload.path) == "PackedScene") {
3892 if (GDScriptLanguage::get_singleton()->has_any_global_constant(name)) {
3893 Variant constant = GDScriptLanguage::get_singleton()->get_any_global_constant(name);
3894 Node *node = Object::cast_to<Node>(constant);
3895 if (node != nullptr) {
3896 Ref<GDScript> scr = node->get_script();
3897 if (scr.is_valid()) {
3898 Ref<GDScriptParserRef> singl_parser = get_parser_for(scr->get_script_path());
3899 if (singl_parser.is_valid()) {
3900 Error err = singl_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
3901 if (err == OK) {
3902 result = type_from_metatype(singl_parser->get_parser()->head->get_datatype());
3903 }
3904 }
3905 }
3906 }
3907 }
3908 }
3909 result.is_constant = true;
3910 p_identifier->set_datatype(result);
3911 return;
3912 }
3913 }
3914
3915 if (CoreConstants::is_global_constant(name)) {
3916 int index = CoreConstants::get_global_constant_index(name);
3917 StringName enum_name = CoreConstants::get_global_constant_enum(index);
3918 int64_t value = CoreConstants::get_global_constant_value(index);
3919 if (enum_name != StringName()) {
3920 p_identifier->set_datatype(make_global_enum_type(enum_name, StringName(), false));
3921 } else {
3922 p_identifier->set_datatype(type_from_variant(value, p_identifier));
3923 }
3924 p_identifier->is_constant = true;
3925 p_identifier->reduced_value = value;
3926 return;
3927 }
3928
3929 if (GDScriptLanguage::get_singleton()->has_any_global_constant(name)) {
3930 Variant constant = GDScriptLanguage::get_singleton()->get_any_global_constant(name);
3931 p_identifier->set_datatype(type_from_variant(constant, p_identifier));
3932 p_identifier->is_constant = true;
3933 p_identifier->reduced_value = constant;
3934 return;
3935 }
3936
3937 if (CoreConstants::is_global_enum(name)) {
3938 p_identifier->set_datatype(make_global_enum_type(name, StringName(), true));
3939 if (!can_be_builtin) {
3940 push_error(vformat(R"(Global enum "%s" cannot be used on its own.)", name), p_identifier);
3941 }
3942 return;
3943 }
3944
3945 // Allow "Variant" here since it might be used for nested enums.
3946 if (can_be_builtin && name == SNAME("Variant")) {
3947 GDScriptParser::DataType variant;
3948 variant.kind = GDScriptParser::DataType::VARIANT;
3949 variant.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3950 variant.is_meta_type = true;
3951 variant.is_pseudo_type = true;
3952 p_identifier->set_datatype(variant);
3953 return;
3954 }
3955
3956 // Not found.
3957 // Check if it's a builtin function.
3958 if (GDScriptUtilityFunctions::function_exists(name)) {
3959 push_error(vformat(R"(Built-in function "%s" cannot be used as an identifier.)", name), p_identifier);
3960 } else {
3961#ifdef SUGGEST_GODOT4_RENAMES
3962 String rename_hint = String();
3963 if (GLOBAL_GET(GDScriptWarning::get_settings_path_from_code(GDScriptWarning::Code::RENAMED_IN_GODOT_4_HINT)).booleanize()) {
3964 const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
3965 if (renamed_identifier_name) {
3966 rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name);
3967 }
3968 }
3969 push_error(vformat(R"(Identifier "%s" not declared in the current scope.%s)", name, rename_hint), p_identifier);
3970#else
3971 push_error(vformat(R"(Identifier "%s" not declared in the current scope.)", name), p_identifier);
3972#endif // SUGGEST_GODOT4_RENAMES
3973 }
3974 GDScriptParser::DataType dummy;
3975 dummy.kind = GDScriptParser::DataType::VARIANT;
3976 p_identifier->set_datatype(dummy); // Just so type is set to something.
3977}
3978
3979void GDScriptAnalyzer::reduce_lambda(GDScriptParser::LambdaNode *p_lambda) {
3980 // Lambda is always a Callable.
3981 GDScriptParser::DataType lambda_type;
3982 lambda_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
3983 lambda_type.kind = GDScriptParser::DataType::BUILTIN;
3984 lambda_type.builtin_type = Variant::CALLABLE;
3985 p_lambda->set_datatype(lambda_type);
3986
3987 if (p_lambda->function == nullptr) {
3988 return;
3989 }
3990
3991 GDScriptParser::LambdaNode *previous_lambda = current_lambda;
3992 current_lambda = p_lambda;
3993 resolve_function_signature(p_lambda->function, p_lambda, true);
3994 current_lambda = previous_lambda;
3995
3996 pending_body_resolution_lambdas.push_back(p_lambda);
3997}
3998
3999void GDScriptAnalyzer::reduce_literal(GDScriptParser::LiteralNode *p_literal) {
4000 p_literal->reduced_value = p_literal->value;
4001 p_literal->is_constant = true;
4002
4003 p_literal->set_datatype(type_from_variant(p_literal->reduced_value, p_literal));
4004}
4005
4006void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
4007 if (!p_preload->path) {
4008 return;
4009 }
4010
4011 reduce_expression(p_preload->path);
4012
4013 if (!p_preload->path->is_constant) {
4014 push_error("Preloaded path must be a constant string.", p_preload->path);
4015 return;
4016 }
4017
4018 if (p_preload->path->reduced_value.get_type() != Variant::STRING) {
4019 push_error("Preloaded path must be a constant string.", p_preload->path);
4020 } else {
4021 p_preload->resolved_path = p_preload->path->reduced_value;
4022 // TODO: Save this as script dependency.
4023 if (p_preload->resolved_path.is_relative_path()) {
4024 p_preload->resolved_path = parser->script_path.get_base_dir().path_join(p_preload->resolved_path);
4025 }
4026 p_preload->resolved_path = p_preload->resolved_path.simplify_path();
4027 if (!ResourceLoader::exists(p_preload->resolved_path)) {
4028 Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
4029
4030 if (file_check->file_exists(p_preload->resolved_path)) {
4031 push_error(vformat(R"(Preload file "%s" has no resource loaders (unrecognized file extension).)", p_preload->resolved_path), p_preload->path);
4032 } else {
4033 push_error(vformat(R"(Preload file "%s" does not exist.)", p_preload->resolved_path), p_preload->path);
4034 }
4035 } else {
4036 // TODO: Don't load if validating: use completion cache.
4037
4038 // Must load GDScript and PackedScenes separately to permit cyclic references
4039 // as ResourceLoader::load() detect and reject those.
4040 if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "GDScript") {
4041 Error err = OK;
4042 Ref<GDScript> res = GDScriptCache::get_shallow_script(p_preload->resolved_path, err, parser->script_path);
4043 p_preload->resource = res;
4044 if (err != OK) {
4045 push_error(vformat(R"(Could not preload resource script "%s".)", p_preload->resolved_path), p_preload->path);
4046 }
4047 } else if (ResourceLoader::get_resource_type(p_preload->resolved_path) == "PackedScene") {
4048 Error err = OK;
4049 Ref<PackedScene> res = GDScriptCache::get_packed_scene(p_preload->resolved_path, err, parser->script_path);
4050 p_preload->resource = res;
4051 if (err != OK) {
4052 push_error(vformat(R"(Could not preload resource scene "%s".)", p_preload->resolved_path), p_preload->path);
4053 }
4054 } else {
4055 p_preload->resource = ResourceLoader::load(p_preload->resolved_path);
4056 if (p_preload->resource.is_null()) {
4057 push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
4058 }
4059 }
4060 }
4061 }
4062
4063 p_preload->is_constant = true;
4064 p_preload->reduced_value = p_preload->resource;
4065 p_preload->set_datatype(type_from_variant(p_preload->reduced_value, p_preload));
4066}
4067
4068void GDScriptAnalyzer::reduce_self(GDScriptParser::SelfNode *p_self) {
4069 p_self->is_constant = false;
4070 p_self->set_datatype(type_from_metatype(parser->current_class->get_datatype()));
4071 mark_lambda_use_self();
4072}
4073
4074void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscript, bool p_can_be_pseudo_type) {
4075 if (p_subscript->base == nullptr) {
4076 return;
4077 }
4078 if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
4079 reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base), true);
4080 } else if (p_subscript->base->type == GDScriptParser::Node::SUBSCRIPT) {
4081 reduce_subscript(static_cast<GDScriptParser::SubscriptNode *>(p_subscript->base), true);
4082 } else {
4083 reduce_expression(p_subscript->base);
4084 }
4085
4086 GDScriptParser::DataType result_type;
4087
4088 if (p_subscript->is_attribute) {
4089 if (p_subscript->attribute == nullptr) {
4090 return;
4091 }
4092
4093 GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
4094 bool valid = false;
4095 // If the base is a metatype, use the analyzer instead.
4096 if (p_subscript->base->is_constant && !base_type.is_meta_type) {
4097 // Just try to get it.
4098 Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
4099 if (valid) {
4100 p_subscript->is_constant = true;
4101 p_subscript->reduced_value = value;
4102 result_type = type_from_variant(value, p_subscript);
4103 }
4104 } else if (base_type.is_variant() || !base_type.is_hard_type()) {
4105 valid = !base_type.is_pseudo_type || p_can_be_pseudo_type;
4106 result_type.kind = GDScriptParser::DataType::VARIANT;
4107 if (base_type.is_variant() && base_type.is_hard_type() && base_type.is_meta_type && base_type.is_pseudo_type) {
4108 // Special case: it may be a global enum with pseudo base (e.g. Variant.Type).
4109 String enum_name;
4110 if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
4111 enum_name = String(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base)->name) + ENUM_SEPARATOR + String(p_subscript->attribute->name);
4112 }
4113 if (CoreConstants::is_global_enum(enum_name)) {
4114 result_type = make_global_enum_type(enum_name, StringName());
4115 } else {
4116 valid = false;
4117 mark_node_unsafe(p_subscript);
4118 }
4119 } else {
4120 mark_node_unsafe(p_subscript);
4121 }
4122 } else {
4123 reduce_identifier_from_base(p_subscript->attribute, &base_type);
4124 GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
4125 if (attr_type.is_set()) {
4126 valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
4127 result_type = attr_type;
4128 p_subscript->is_constant = p_subscript->attribute->is_constant;
4129 p_subscript->reduced_value = p_subscript->attribute->reduced_value;
4130 } else if (!base_type.is_meta_type || !base_type.is_constant) {
4131 valid = base_type.kind != GDScriptParser::DataType::BUILTIN;
4132#ifdef DEBUG_ENABLED
4133 if (valid) {
4134 parser->push_warning(p_subscript, GDScriptWarning::UNSAFE_PROPERTY_ACCESS, p_subscript->attribute->name, base_type.to_string());
4135 }
4136#endif
4137 result_type.kind = GDScriptParser::DataType::VARIANT;
4138 mark_node_unsafe(p_subscript);
4139 }
4140 }
4141 if (!valid) {
4142 GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
4143 if (!p_can_be_pseudo_type && (attr_type.is_pseudo_type || result_type.is_pseudo_type)) {
4144 push_error(vformat(R"(Type "%s" in base "%s" cannot be used on its own.)", p_subscript->attribute->name, type_from_metatype(base_type).to_string()), p_subscript->attribute);
4145 } else {
4146 push_error(vformat(R"(Cannot find member "%s" in base "%s".)", p_subscript->attribute->name, type_from_metatype(base_type).to_string()), p_subscript->attribute);
4147 }
4148 result_type.kind = GDScriptParser::DataType::VARIANT;
4149 }
4150 } else {
4151 if (p_subscript->index == nullptr) {
4152 return;
4153 }
4154 reduce_expression(p_subscript->index);
4155
4156 if (p_subscript->base->is_constant && p_subscript->index->is_constant) {
4157 // Just try to get it.
4158 bool valid = false;
4159 Variant value = p_subscript->base->reduced_value.get(p_subscript->index->reduced_value, &valid);
4160 if (!valid) {
4161 push_error(vformat(R"(Cannot get index "%s" from "%s".)", p_subscript->index->reduced_value, p_subscript->base->reduced_value), p_subscript->index);
4162 result_type.kind = GDScriptParser::DataType::VARIANT;
4163 } else {
4164 p_subscript->is_constant = true;
4165 p_subscript->reduced_value = value;
4166 result_type = type_from_variant(value, p_subscript);
4167 }
4168 } else {
4169 GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
4170 GDScriptParser::DataType index_type = p_subscript->index->get_datatype();
4171
4172 if (base_type.is_variant()) {
4173 result_type.kind = GDScriptParser::DataType::VARIANT;
4174 mark_node_unsafe(p_subscript);
4175 } else {
4176 if (base_type.kind == GDScriptParser::DataType::BUILTIN && !index_type.is_variant()) {
4177 // Check if indexing is valid.
4178 bool error = index_type.kind != GDScriptParser::DataType::BUILTIN && base_type.builtin_type != Variant::DICTIONARY;
4179 if (!error) {
4180 switch (base_type.builtin_type) {
4181 // Expect int or real as index.
4182 case Variant::PACKED_BYTE_ARRAY:
4183 case Variant::PACKED_COLOR_ARRAY:
4184 case Variant::PACKED_FLOAT32_ARRAY:
4185 case Variant::PACKED_FLOAT64_ARRAY:
4186 case Variant::PACKED_INT32_ARRAY:
4187 case Variant::PACKED_INT64_ARRAY:
4188 case Variant::PACKED_STRING_ARRAY:
4189 case Variant::PACKED_VECTOR2_ARRAY:
4190 case Variant::PACKED_VECTOR3_ARRAY:
4191 case Variant::ARRAY:
4192 case Variant::STRING:
4193 error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT;
4194 break;
4195 // Expect String only.
4196 case Variant::RECT2:
4197 case Variant::RECT2I:
4198 case Variant::PLANE:
4199 case Variant::QUATERNION:
4200 case Variant::AABB:
4201 case Variant::OBJECT:
4202 error = index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
4203 break;
4204 // Expect String or number.
4205 case Variant::BASIS:
4206 case Variant::VECTOR2:
4207 case Variant::VECTOR2I:
4208 case Variant::VECTOR3:
4209 case Variant::VECTOR3I:
4210 case Variant::VECTOR4:
4211 case Variant::VECTOR4I:
4212 case Variant::TRANSFORM2D:
4213 case Variant::TRANSFORM3D:
4214 case Variant::PROJECTION:
4215 error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT &&
4216 index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
4217 break;
4218 // Expect String or int.
4219 case Variant::COLOR:
4220 error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
4221 break;
4222 // Don't support indexing, but we will check it later.
4223 case Variant::RID:
4224 case Variant::BOOL:
4225 case Variant::CALLABLE:
4226 case Variant::FLOAT:
4227 case Variant::INT:
4228 case Variant::NIL:
4229 case Variant::NODE_PATH:
4230 case Variant::SIGNAL:
4231 case Variant::STRING_NAME:
4232 break;
4233 // Here for completeness.
4234 case Variant::DICTIONARY:
4235 case Variant::VARIANT_MAX:
4236 break;
4237 }
4238
4239 if (error) {
4240 push_error(vformat(R"(Invalid index type "%s" for a base of type "%s".)", index_type.to_string(), base_type.to_string()), p_subscript->index);
4241 }
4242 }
4243 } else if (base_type.kind != GDScriptParser::DataType::BUILTIN && !index_type.is_variant()) {
4244 if (index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME) {
4245 push_error(vformat(R"(Only String or StringName can be used as index for type "%s", but received a "%s".)", base_type.to_string(), index_type.to_string()), p_subscript->index);
4246 }
4247 }
4248
4249 // Check resulting type if possible.
4250 result_type.builtin_type = Variant::NIL;
4251 result_type.kind = GDScriptParser::DataType::BUILTIN;
4252 result_type.type_source = base_type.is_hard_type() ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
4253
4254 if (base_type.kind != GDScriptParser::DataType::BUILTIN) {
4255 base_type.builtin_type = Variant::OBJECT;
4256 }
4257 switch (base_type.builtin_type) {
4258 // Can't index at all.
4259 case Variant::RID:
4260 case Variant::BOOL:
4261 case Variant::CALLABLE:
4262 case Variant::FLOAT:
4263 case Variant::INT:
4264 case Variant::NIL:
4265 case Variant::NODE_PATH:
4266 case Variant::SIGNAL:
4267 case Variant::STRING_NAME:
4268 result_type.kind = GDScriptParser::DataType::VARIANT;
4269 push_error(vformat(R"(Cannot use subscript operator on a base of type "%s".)", base_type.to_string()), p_subscript->base);
4270 break;
4271 // Return int.
4272 case Variant::PACKED_BYTE_ARRAY:
4273 case Variant::PACKED_INT32_ARRAY:
4274 case Variant::PACKED_INT64_ARRAY:
4275 case Variant::VECTOR2I:
4276 case Variant::VECTOR3I:
4277 case Variant::VECTOR4I:
4278 result_type.builtin_type = Variant::INT;
4279 break;
4280 // Return float.
4281 case Variant::PACKED_FLOAT32_ARRAY:
4282 case Variant::PACKED_FLOAT64_ARRAY:
4283 case Variant::VECTOR2:
4284 case Variant::VECTOR3:
4285 case Variant::VECTOR4:
4286 case Variant::QUATERNION:
4287 result_type.builtin_type = Variant::FLOAT;
4288 break;
4289 // Return Color.
4290 case Variant::PACKED_COLOR_ARRAY:
4291 result_type.builtin_type = Variant::COLOR;
4292 break;
4293 // Return String.
4294 case Variant::PACKED_STRING_ARRAY:
4295 case Variant::STRING:
4296 result_type.builtin_type = Variant::STRING;
4297 break;
4298 // Return Vector2.
4299 case Variant::PACKED_VECTOR2_ARRAY:
4300 case Variant::TRANSFORM2D:
4301 case Variant::RECT2:
4302 result_type.builtin_type = Variant::VECTOR2;
4303 break;
4304 // Return Vector2I.
4305 case Variant::RECT2I:
4306 result_type.builtin_type = Variant::VECTOR2I;
4307 break;
4308 // Return Vector3.
4309 case Variant::PACKED_VECTOR3_ARRAY:
4310 case Variant::AABB:
4311 case Variant::BASIS:
4312 result_type.builtin_type = Variant::VECTOR3;
4313 break;
4314 // Depends on the index.
4315 case Variant::TRANSFORM3D:
4316 case Variant::PROJECTION:
4317 case Variant::PLANE:
4318 case Variant::COLOR:
4319 case Variant::DICTIONARY:
4320 case Variant::OBJECT:
4321 result_type.kind = GDScriptParser::DataType::VARIANT;
4322 result_type.type_source = GDScriptParser::DataType::UNDETECTED;
4323 break;
4324 // Can have an element type.
4325 case Variant::ARRAY:
4326 if (base_type.has_container_element_type()) {
4327 result_type = base_type.get_container_element_type();
4328 result_type.type_source = base_type.type_source;
4329 } else {
4330 result_type.kind = GDScriptParser::DataType::VARIANT;
4331 result_type.type_source = GDScriptParser::DataType::UNDETECTED;
4332 }
4333 break;
4334 // Here for completeness.
4335 case Variant::VARIANT_MAX:
4336 break;
4337 }
4338 }
4339 }
4340 }
4341
4342 p_subscript->set_datatype(result_type);
4343}
4344
4345void GDScriptAnalyzer::reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op, bool p_is_root) {
4346 reduce_expression(p_ternary_op->condition);
4347 reduce_expression(p_ternary_op->true_expr, p_is_root);
4348 reduce_expression(p_ternary_op->false_expr, p_is_root);
4349
4350 GDScriptParser::DataType result;
4351
4352 if (p_ternary_op->condition && p_ternary_op->condition->is_constant && p_ternary_op->true_expr->is_constant && p_ternary_op->false_expr && p_ternary_op->false_expr->is_constant) {
4353 p_ternary_op->is_constant = true;
4354 if (p_ternary_op->condition->reduced_value.booleanize()) {
4355 p_ternary_op->reduced_value = p_ternary_op->true_expr->reduced_value;
4356 } else {
4357 p_ternary_op->reduced_value = p_ternary_op->false_expr->reduced_value;
4358 }
4359 }
4360
4361 GDScriptParser::DataType true_type;
4362 if (p_ternary_op->true_expr) {
4363 true_type = p_ternary_op->true_expr->get_datatype();
4364 } else {
4365 true_type.kind = GDScriptParser::DataType::VARIANT;
4366 }
4367 GDScriptParser::DataType false_type;
4368 if (p_ternary_op->false_expr) {
4369 false_type = p_ternary_op->false_expr->get_datatype();
4370 } else {
4371 false_type.kind = GDScriptParser::DataType::VARIANT;
4372 }
4373
4374 if (true_type.is_variant() || false_type.is_variant()) {
4375 result.kind = GDScriptParser::DataType::VARIANT;
4376 } else {
4377 result = true_type;
4378 if (!is_type_compatible(true_type, false_type)) {
4379 result = false_type;
4380 if (!is_type_compatible(false_type, true_type)) {
4381 result.kind = GDScriptParser::DataType::VARIANT;
4382#ifdef DEBUG_ENABLED
4383 parser->push_warning(p_ternary_op, GDScriptWarning::INCOMPATIBLE_TERNARY);
4384#endif
4385 }
4386 }
4387 }
4388 result.type_source = true_type.is_hard_type() && false_type.is_hard_type() ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
4389
4390 p_ternary_op->set_datatype(result);
4391}
4392
4393void GDScriptAnalyzer::reduce_type_test(GDScriptParser::TypeTestNode *p_type_test) {
4394 GDScriptParser::DataType result;
4395 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
4396 result.kind = GDScriptParser::DataType::BUILTIN;
4397 result.builtin_type = Variant::BOOL;
4398 p_type_test->set_datatype(result);
4399
4400 if (!p_type_test->operand || !p_type_test->test_type) {
4401 return;
4402 }
4403
4404 reduce_expression(p_type_test->operand);
4405 GDScriptParser::DataType operand_type = p_type_test->operand->get_datatype();
4406 GDScriptParser::DataType test_type = type_from_metatype(resolve_datatype(p_type_test->test_type));
4407 p_type_test->test_datatype = test_type;
4408
4409 if (!operand_type.is_set() || !test_type.is_set()) {
4410 return;
4411 }
4412
4413 if (p_type_test->operand->is_constant) {
4414 p_type_test->is_constant = true;
4415 p_type_test->reduced_value = false;
4416
4417 if (!is_type_compatible(test_type, operand_type)) {
4418 push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)", operand_type.to_string(), test_type.to_string()), p_type_test->operand);
4419 } else if (is_type_compatible(test_type, type_from_variant(p_type_test->operand->reduced_value, p_type_test->operand))) {
4420 p_type_test->reduced_value = test_type.builtin_type != Variant::OBJECT || !p_type_test->operand->reduced_value.is_null();
4421 }
4422
4423 return;
4424 }
4425
4426 if (!is_type_compatible(test_type, operand_type) && !is_type_compatible(operand_type, test_type)) {
4427 if (operand_type.is_hard_type()) {
4428 push_error(vformat(R"(Expression is of type "%s" so it can't be of type "%s".)", operand_type.to_string(), test_type.to_string()), p_type_test->operand);
4429 } else {
4430 downgrade_node_type_source(p_type_test->operand);
4431 }
4432 }
4433}
4434
4435void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op) {
4436 reduce_expression(p_unary_op->operand);
4437
4438 GDScriptParser::DataType result;
4439
4440 if (p_unary_op->operand == nullptr) {
4441 result.kind = GDScriptParser::DataType::VARIANT;
4442 p_unary_op->set_datatype(result);
4443 return;
4444 }
4445
4446 GDScriptParser::DataType operand_type = p_unary_op->operand->get_datatype();
4447
4448 if (p_unary_op->operand->is_constant) {
4449 p_unary_op->is_constant = true;
4450 p_unary_op->reduced_value = Variant::evaluate(p_unary_op->variant_op, p_unary_op->operand->reduced_value, Variant());
4451 result = type_from_variant(p_unary_op->reduced_value, p_unary_op);
4452 }
4453
4454 if (operand_type.is_variant()) {
4455 result.kind = GDScriptParser::DataType::VARIANT;
4456 mark_node_unsafe(p_unary_op);
4457 } else {
4458 bool valid = false;
4459 result = get_operation_type(p_unary_op->variant_op, operand_type, valid, p_unary_op);
4460
4461 if (!valid) {
4462 push_error(vformat(R"(Invalid operand of type "%s" for unary operator "%s".)", operand_type.to_string(), Variant::get_operator_name(p_unary_op->variant_op)), p_unary_op);
4463 }
4464 }
4465
4466 p_unary_op->set_datatype(result);
4467}
4468
4469Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) {
4470 Variant value;
4471
4472 if (p_expression == nullptr) {
4473 return value;
4474 }
4475
4476 if (p_expression->is_constant) {
4477 is_reduced = true;
4478 value = p_expression->reduced_value;
4479 } else if (p_expression->type == GDScriptParser::Node::ARRAY) {
4480 value = make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
4481 } else if (p_expression->type == GDScriptParser::Node::DICTIONARY) {
4482 value = make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
4483 } else if (p_expression->type == GDScriptParser::Node::SUBSCRIPT) {
4484 value = make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
4485 }
4486
4487 return value;
4488}
4489
4490Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) {
4491 Array array = p_array->get_datatype().has_container_element_type() ? make_array_from_element_datatype(p_array->get_datatype().get_container_element_type()) : Array();
4492
4493 array.resize(p_array->elements.size());
4494 for (int i = 0; i < p_array->elements.size(); i++) {
4495 GDScriptParser::ExpressionNode *element = p_array->elements[i];
4496
4497 bool is_element_value_reduced = false;
4498 Variant element_value = make_expression_reduced_value(element, is_element_value_reduced);
4499 if (!is_element_value_reduced) {
4500 return Variant();
4501 }
4502
4503 array[i] = element_value;
4504 }
4505
4506 array.make_read_only();
4507
4508 is_reduced = true;
4509 return array;
4510}
4511
4512Variant GDScriptAnalyzer::make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced) {
4513 Dictionary dictionary;
4514
4515 for (int i = 0; i < p_dictionary->elements.size(); i++) {
4516 const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
4517
4518 bool is_element_key_reduced = false;
4519 Variant element_key = make_expression_reduced_value(element.key, is_element_key_reduced);
4520 if (!is_element_key_reduced) {
4521 return Variant();
4522 }
4523
4524 bool is_element_value_reduced = false;
4525 Variant element_value = make_expression_reduced_value(element.value, is_element_value_reduced);
4526 if (!is_element_value_reduced) {
4527 return Variant();
4528 }
4529
4530 dictionary[element_key] = element_value;
4531 }
4532
4533 dictionary.make_read_only();
4534
4535 is_reduced = true;
4536 return dictionary;
4537}
4538
4539Variant GDScriptAnalyzer::make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced) {
4540 if (p_subscript->base == nullptr || p_subscript->index == nullptr) {
4541 return Variant();
4542 }
4543
4544 bool is_base_value_reduced = false;
4545 Variant base_value = make_expression_reduced_value(p_subscript->base, is_base_value_reduced);
4546 if (!is_base_value_reduced) {
4547 return Variant();
4548 }
4549
4550 if (p_subscript->is_attribute) {
4551 bool is_valid = false;
4552 Variant value = base_value.get_named(p_subscript->attribute->name, is_valid);
4553 if (is_valid) {
4554 is_reduced = true;
4555 return value;
4556 } else {
4557 return Variant();
4558 }
4559 } else {
4560 bool is_index_value_reduced = false;
4561 Variant index_value = make_expression_reduced_value(p_subscript->index, is_index_value_reduced);
4562 if (!is_index_value_reduced) {
4563 return Variant();
4564 }
4565
4566 bool is_valid = false;
4567 Variant value = base_value.get(index_value, &is_valid);
4568 if (is_valid) {
4569 is_reduced = true;
4570 return value;
4571 } else {
4572 return Variant();
4573 }
4574 }
4575}
4576
4577Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) {
4578 Array array;
4579
4580 if (p_element_datatype.builtin_type == Variant::OBJECT) {
4581 Ref<Script> script_type = p_element_datatype.script_type;
4582 if (p_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) {
4583 Error err = OK;
4584 Ref<GDScript> scr = GDScriptCache::get_shallow_script(p_element_datatype.script_path, err, parser->script_path);
4585 if (err) {
4586 push_error(vformat(R"(Error while getting cache for script "%s".)", p_element_datatype.script_path), p_source_node);
4587 return array;
4588 }
4589 script_type.reference_ptr(scr->find_class(p_element_datatype.class_type->fqcn));
4590 }
4591
4592 array.set_typed(p_element_datatype.builtin_type, p_element_datatype.native_type, script_type);
4593 } else {
4594 array.set_typed(p_element_datatype.builtin_type, StringName(), Variant());
4595 }
4596
4597 return array;
4598}
4599
4600Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNode *p_variable) {
4601 Variant result = Variant();
4602
4603 if (p_variable->initializer) {
4604 bool is_initializer_value_reduced = false;
4605 Variant initializer_value = make_expression_reduced_value(p_variable->initializer, is_initializer_value_reduced);
4606 if (is_initializer_value_reduced) {
4607 result = initializer_value;
4608 }
4609 } else {
4610 GDScriptParser::DataType datatype = p_variable->get_datatype();
4611 if (datatype.is_hard_type()) {
4612 if (datatype.kind == GDScriptParser::DataType::BUILTIN && datatype.builtin_type != Variant::OBJECT) {
4613 if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type()) {
4614 result = make_array_from_element_datatype(datatype.get_container_element_type());
4615 } else {
4616 VariantInternal::initialize(&result, datatype.builtin_type);
4617 }
4618 } else if (datatype.kind == GDScriptParser::DataType::ENUM) {
4619 result = 0;
4620 }
4621 }
4622 }
4623
4624 return result;
4625}
4626
4627const HashMap<String, Ref<GDScriptParserRef>> &GDScriptAnalyzer::get_depended_parsers() {
4628 return depended_parsers;
4629}
4630
4631GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) {
4632 GDScriptParser::DataType result;
4633 result.is_constant = true;
4634 result.kind = GDScriptParser::DataType::BUILTIN;
4635 result.builtin_type = p_value.get_type();
4636 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; // Constant has explicit type.
4637
4638 if (p_value.get_type() == Variant::ARRAY) {
4639 const Array &array = p_value;
4640 if (array.get_typed_script()) {
4641 result.set_container_element_type(type_from_metatype(make_script_meta_type(array.get_typed_script())));
4642 } else if (array.get_typed_class_name()) {
4643 result.set_container_element_type(type_from_metatype(make_native_meta_type(array.get_typed_class_name())));
4644 } else if (array.get_typed_builtin() != Variant::NIL) {
4645 result.set_container_element_type(type_from_metatype(make_builtin_meta_type((Variant::Type)array.get_typed_builtin())));
4646 }
4647 } else if (p_value.get_type() == Variant::OBJECT) {
4648 // Object is treated as a native type, not a builtin type.
4649 result.kind = GDScriptParser::DataType::NATIVE;
4650
4651 Object *obj = p_value;
4652 if (!obj) {
4653 return GDScriptParser::DataType();
4654 }
4655 result.native_type = obj->get_class_name();
4656
4657 Ref<Script> scr = p_value; // Check if value is a script itself.
4658 if (scr.is_valid()) {
4659 result.is_meta_type = true;
4660 } else {
4661 result.is_meta_type = false;
4662 scr = obj->get_script();
4663 }
4664 if (scr.is_valid()) {
4665 Ref<GDScript> gds = scr;
4666 if (gds.is_valid()) {
4667 // This might be an inner class, so we want to get the parser for the root.
4668 // But still get the inner class from that tree.
4669 String script_path = gds->get_script_path();
4670 Ref<GDScriptParserRef> ref = get_parser_for(script_path);
4671 if (ref.is_null()) {
4672 push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
4673 GDScriptParser::DataType error_type;
4674 error_type.kind = GDScriptParser::DataType::VARIANT;
4675 return error_type;
4676 }
4677 Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
4678 GDScriptParser::ClassNode *found = nullptr;
4679 if (err == OK) {
4680 found = ref->get_parser()->find_class(gds->fully_qualified_name);
4681 if (found != nullptr) {
4682 err = resolve_class_inheritance(found, p_source);
4683 }
4684 }
4685 if (err || found == nullptr) {
4686 push_error(vformat(R"(Could not resolve script "%s".)", script_path), p_source);
4687 GDScriptParser::DataType error_type;
4688 error_type.kind = GDScriptParser::DataType::VARIANT;
4689 return error_type;
4690 }
4691
4692 result.kind = GDScriptParser::DataType::CLASS;
4693 result.native_type = found->get_datatype().native_type;
4694 result.class_type = found;
4695 result.script_path = ref->get_parser()->script_path;
4696 } else {
4697 result.kind = GDScriptParser::DataType::SCRIPT;
4698 result.native_type = scr->get_instance_base_type();
4699 result.script_path = scr->get_path();
4700 }
4701 result.script_type = scr;
4702 } else {
4703 result.kind = GDScriptParser::DataType::NATIVE;
4704 if (result.native_type == GDScriptNativeClass::get_class_static()) {
4705 result.is_meta_type = true;
4706 }
4707 }
4708 }
4709
4710 return result;
4711}
4712
4713GDScriptParser::DataType GDScriptAnalyzer::type_from_metatype(const GDScriptParser::DataType &p_meta_type) {
4714 GDScriptParser::DataType result = p_meta_type;
4715 result.is_meta_type = false;
4716 result.is_pseudo_type = false;
4717 if (p_meta_type.kind == GDScriptParser::DataType::ENUM) {
4718 result.builtin_type = Variant::INT;
4719 } else {
4720 result.is_constant = false;
4721 }
4722 return result;
4723}
4724
4725GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo &p_property, bool p_is_arg, bool p_is_readonly) const {
4726 GDScriptParser::DataType result;
4727 result.is_read_only = p_is_readonly;
4728 result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
4729 if (p_property.type == Variant::NIL && (p_is_arg || (p_property.usage & PROPERTY_USAGE_NIL_IS_VARIANT))) {
4730 // Variant
4731 result.kind = GDScriptParser::DataType::VARIANT;
4732 return result;
4733 }
4734 result.builtin_type = p_property.type;
4735 if (p_property.type == Variant::OBJECT) {
4736 result.kind = GDScriptParser::DataType::NATIVE;
4737 result.native_type = p_property.class_name == StringName() ? SNAME("Object") : p_property.class_name;
4738 } else {
4739 result.kind = GDScriptParser::DataType::BUILTIN;
4740 result.builtin_type = p_property.type;
4741 if (p_property.type == Variant::ARRAY && p_property.hint == PROPERTY_HINT_ARRAY_TYPE) {
4742 // Check element type.
4743 StringName elem_type_name = p_property.hint_string;
4744 GDScriptParser::DataType elem_type;
4745 elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
4746
4747 Variant::Type elem_builtin_type = GDScriptParser::get_builtin_type(elem_type_name);
4748 if (elem_builtin_type < Variant::VARIANT_MAX) {
4749 // Builtin type.
4750 elem_type.kind = GDScriptParser::DataType::BUILTIN;
4751 elem_type.builtin_type = elem_builtin_type;
4752 } else if (class_exists(elem_type_name)) {
4753 elem_type.kind = GDScriptParser::DataType::NATIVE;
4754 elem_type.builtin_type = Variant::OBJECT;
4755 elem_type.native_type = p_property.hint_string;
4756 } else if (ScriptServer::is_global_class(elem_type_name)) {
4757 // Just load this as it shouldn't be a GDScript.
4758 Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(elem_type_name));
4759 elem_type.kind = GDScriptParser::DataType::SCRIPT;
4760 elem_type.builtin_type = Variant::OBJECT;
4761 elem_type.native_type = script->get_instance_base_type();
4762 elem_type.script_type = script;
4763 } else {
4764 ERR_FAIL_V_MSG(result, "Could not find element type from property hint of a typed array.");
4765 }
4766 elem_type.is_constant = false;
4767 result.set_container_element_type(elem_type);
4768 } else if (p_property.type == Variant::INT) {
4769 // Check if it's enum.
4770 if ((p_property.usage & PROPERTY_USAGE_CLASS_IS_ENUM) && p_property.class_name != StringName()) {
4771 if (CoreConstants::is_global_enum(p_property.class_name)) {
4772 result = make_global_enum_type(p_property.class_name, StringName(), false);
4773 result.is_constant = false;
4774 } else {
4775 Vector<String> names = String(p_property.class_name).split(ENUM_SEPARATOR);
4776 if (names.size() == 2) {
4777 result = make_native_enum_type(names[1], names[0], false);
4778 result.is_constant = false;
4779 }
4780 }
4781 }
4782 // PROPERTY_USAGE_CLASS_IS_BITFIELD: BitField[T] isn't supported (yet?), use plain int.
4783 }
4784 }
4785 return result;
4786}
4787
4788bool GDScriptAnalyzer::get_function_signature(GDScriptParser::Node *p_source, bool p_is_constructor, GDScriptParser::DataType p_base_type, const StringName &p_function, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, BitField<MethodFlags> &r_method_flags, StringName *r_native_class) {
4789 r_method_flags = METHOD_FLAGS_DEFAULT;
4790 r_default_arg_count = 0;
4791 if (r_native_class) {
4792 *r_native_class = StringName();
4793 }
4794 StringName function_name = p_function;
4795
4796 bool was_enum = false;
4797 if (p_base_type.kind == GDScriptParser::DataType::ENUM) {
4798 was_enum = true;
4799 if (p_base_type.is_meta_type) {
4800 // Enum type can be treated as a dictionary value.
4801 p_base_type.kind = GDScriptParser::DataType::BUILTIN;
4802 p_base_type.is_meta_type = false;
4803 } else {
4804 push_error("Cannot call function on enum value.", p_source);
4805 return false;
4806 }
4807 }
4808
4809 if (p_base_type.kind == GDScriptParser::DataType::BUILTIN) {
4810 // Construct a base type to get methods.
4811 Callable::CallError err;
4812 Variant dummy;
4813 Variant::construct(p_base_type.builtin_type, dummy, nullptr, 0, err);
4814 if (err.error != Callable::CallError::CALL_OK) {
4815 ERR_FAIL_V_MSG(false, "Could not construct base Variant type.");
4816 }
4817 List<MethodInfo> methods;
4818 dummy.get_method_list(&methods);
4819
4820 for (const MethodInfo &E : methods) {
4821 if (E.name == p_function) {
4822 function_signature_from_info(E, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
4823 // Cannot use non-const methods on enums.
4824 if (!r_method_flags.has_flag(METHOD_FLAG_STATIC) && was_enum && !(E.flags & METHOD_FLAG_CONST)) {
4825 push_error(vformat(R"*(Cannot call non-const Dictionary function "%s()" on enum "%s".)*", p_function, p_base_type.enum_type), p_source);
4826 }
4827 return true;
4828 }
4829 }
4830
4831 return false;
4832 }
4833
4834 StringName base_native = p_base_type.native_type;
4835 if (base_native != StringName()) {
4836 // Empty native class might happen in some Script implementations.
4837 // Just ignore it.
4838 if (!class_exists(base_native)) {
4839 push_error(vformat("Native class %s used in script doesn't exist or isn't exposed.", base_native), p_source);
4840 return false;
4841 } else if (p_is_constructor && !ClassDB::can_instantiate(base_native)) {
4842 if (p_base_type.kind == GDScriptParser::DataType::CLASS) {
4843 push_error(vformat(R"(Class "%s" cannot be constructed as it is based on abstract native class "%s".)", p_base_type.class_type->fqcn.get_file(), base_native), p_source);
4844 } else if (p_base_type.kind == GDScriptParser::DataType::SCRIPT) {
4845 push_error(vformat(R"(Script "%s" cannot be constructed as it is based on abstract native class "%s".)", p_base_type.script_path.get_file(), base_native), p_source);
4846 } else {
4847 push_error(vformat(R"(Native class "%s" cannot be constructed as it is abstract.)", base_native), p_source);
4848 }
4849 return false;
4850 }
4851 }
4852
4853 if (p_is_constructor) {
4854 function_name = GDScriptLanguage::get_singleton()->strings._init;
4855 r_method_flags.set_flag(METHOD_FLAG_STATIC);
4856 }
4857
4858 GDScriptParser::ClassNode *base_class = p_base_type.class_type;
4859 GDScriptParser::FunctionNode *found_function = nullptr;
4860
4861 while (found_function == nullptr && base_class != nullptr) {
4862 if (base_class->has_member(function_name)) {
4863 if (base_class->get_member(function_name).type != GDScriptParser::ClassNode::Member::FUNCTION) {
4864 // TODO: If this is Callable it can have a better error message.
4865 push_error(vformat(R"(Member "%s" is not a function.)", function_name), p_source);
4866 return false;
4867 }
4868
4869 resolve_class_member(base_class, function_name, p_source);
4870 found_function = base_class->get_member(function_name).function;
4871 }
4872
4873 resolve_class_inheritance(base_class, p_source);
4874 base_class = base_class->base_type.class_type;
4875 }
4876
4877 if (found_function != nullptr) {
4878 if (p_is_constructor || found_function->is_static) {
4879 r_method_flags.set_flag(METHOD_FLAG_STATIC);
4880 }
4881 for (int i = 0; i < found_function->parameters.size(); i++) {
4882 r_par_types.push_back(found_function->parameters[i]->get_datatype());
4883 if (found_function->parameters[i]->initializer != nullptr) {
4884 r_default_arg_count++;
4885 }
4886 }
4887 r_return_type = p_is_constructor ? p_base_type : found_function->get_datatype();
4888 r_return_type.is_meta_type = false;
4889 r_return_type.is_coroutine = found_function->is_coroutine;
4890
4891 return true;
4892 }
4893
4894 Ref<Script> base_script = p_base_type.script_type;
4895
4896 while (base_script.is_valid() && base_script->has_method(function_name)) {
4897 MethodInfo info = base_script->get_method_info(function_name);
4898
4899 if (!(info == MethodInfo())) {
4900 return function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
4901 }
4902 base_script = base_script->get_base_script();
4903 }
4904
4905 // If the base is a script, it might be trying to access members of the Script class itself.
4906 if (p_base_type.is_meta_type && !p_is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) {
4907 MethodInfo info;
4908 StringName script_class = p_base_type.kind == GDScriptParser::DataType::SCRIPT ? p_base_type.script_type->get_class_name() : StringName(GDScript::get_class_static());
4909
4910 if (ClassDB::get_method_info(script_class, function_name, &info)) {
4911 return function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
4912 }
4913 }
4914
4915 if (p_is_constructor) {
4916 // Native types always have a default constructor.
4917 r_return_type = p_base_type;
4918 r_return_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
4919 r_return_type.is_meta_type = false;
4920 return true;
4921 }
4922
4923 MethodInfo info;
4924 if (ClassDB::get_method_info(base_native, function_name, &info)) {
4925 bool valid = function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
4926 if (valid && Engine::get_singleton()->has_singleton(base_native)) {
4927 r_method_flags.set_flag(METHOD_FLAG_STATIC);
4928 }
4929#ifdef DEBUG_ENABLED
4930 MethodBind *native_method = ClassDB::get_method(base_native, function_name);
4931 if (native_method && r_native_class) {
4932 *r_native_class = native_method->get_instance_class();
4933 }
4934#endif
4935 return valid;
4936 }
4937
4938 return false;
4939}
4940
4941bool GDScriptAnalyzer::function_signature_from_info(const MethodInfo &p_info, GDScriptParser::DataType &r_return_type, List<GDScriptParser::DataType> &r_par_types, int &r_default_arg_count, BitField<MethodFlags> &r_method_flags) {
4942 r_return_type = type_from_property(p_info.return_val);
4943 r_default_arg_count = p_info.default_arguments.size();
4944 r_method_flags = p_info.flags;
4945
4946 for (const PropertyInfo &E : p_info.arguments) {
4947 r_par_types.push_back(type_from_property(E, true));
4948 }
4949 return true;
4950}
4951
4952void GDScriptAnalyzer::validate_call_arg(const MethodInfo &p_method, const GDScriptParser::CallNode *p_call) {
4953 List<GDScriptParser::DataType> arg_types;
4954
4955 for (const PropertyInfo &E : p_method.arguments) {
4956 arg_types.push_back(type_from_property(E, true));
4957 }
4958
4959 validate_call_arg(arg_types, p_method.default_arguments.size(), (p_method.flags & METHOD_FLAG_VARARG) != 0, p_call);
4960}
4961
4962void GDScriptAnalyzer::validate_call_arg(const List<GDScriptParser::DataType> &p_par_types, int p_default_args_count, bool p_is_vararg, const GDScriptParser::CallNode *p_call) {
4963 if (p_call->arguments.size() < p_par_types.size() - p_default_args_count) {
4964 push_error(vformat(R"*(Too few arguments for "%s()" call. Expected at least %d but received %d.)*", p_call->function_name, p_par_types.size() - p_default_args_count, p_call->arguments.size()), p_call);
4965 }
4966 if (!p_is_vararg && p_call->arguments.size() > p_par_types.size()) {
4967 push_error(vformat(R"*(Too many arguments for "%s()" call. Expected at most %d but received %d.)*", p_call->function_name, p_par_types.size(), p_call->arguments.size()), p_call->arguments[p_par_types.size()]);
4968 }
4969
4970 for (int i = 0; i < p_call->arguments.size(); i++) {
4971 if (i >= p_par_types.size()) {
4972 // Already on vararg place.
4973 break;
4974 }
4975 GDScriptParser::DataType par_type = p_par_types[i];
4976
4977 if (par_type.is_hard_type() && p_call->arguments[i]->is_constant) {
4978 update_const_expression_builtin_type(p_call->arguments[i], par_type, "pass");
4979 }
4980 GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
4981
4982 if (arg_type.is_variant() || !arg_type.is_hard_type()) {
4983 // Argument can be anything, so this is unsafe (unless the parameter is a hard variant).
4984 if (!(par_type.is_hard_type() && par_type.is_variant())) {
4985 mark_node_unsafe(p_call->arguments[i]);
4986 }
4987 } else if (par_type.is_hard_type() && !is_type_compatible(par_type, arg_type, true)) {
4988 // Supertypes are acceptable for dynamic compliance, but it's unsafe.
4989 mark_node_unsafe(p_call);
4990 if (!is_type_compatible(arg_type, par_type)) {
4991 push_error(vformat(R"*(Invalid argument for "%s()" function: argument %d should be "%s" but is "%s".)*",
4992 p_call->function_name, i + 1, par_type.to_string(), arg_type.to_string()),
4993 p_call->arguments[i]);
4994 }
4995#ifdef DEBUG_ENABLED
4996 } else if (par_type.kind == GDScriptParser::DataType::BUILTIN && par_type.builtin_type == Variant::INT && arg_type.kind == GDScriptParser::DataType::BUILTIN && arg_type.builtin_type == Variant::FLOAT) {
4997 parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, p_call->function_name);
4998#endif
4999 }
5000 }
5001}
5002
5003#ifdef DEBUG_ENABLED
5004void GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_identifier, const String &p_context, const bool p_in_local_scope) {
5005 const StringName &name = p_identifier->name;
5006 GDScriptParser::DataType base = parser->current_class->get_datatype();
5007 GDScriptParser::ClassNode *base_class = base.class_type;
5008
5009 {
5010 List<MethodInfo> gdscript_funcs;
5011 GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs);
5012
5013 for (MethodInfo &info : gdscript_funcs) {
5014 if (info.name == name) {
5015 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function");
5016 return;
5017 }
5018 }
5019 if (Variant::has_utility_function(name)) {
5020 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function");
5021 return;
5022 } else if (ClassDB::class_exists(name)) {
5023 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "global class");
5024 return;
5025 } else if (GDScriptParser::get_builtin_type(name) != Variant::VARIANT_MAX) {
5026 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in type");
5027 return;
5028 }
5029 }
5030
5031 if (p_in_local_scope) {
5032 while (base_class != nullptr) {
5033 if (base_class->has_member(name)) {
5034 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE, p_context, p_identifier->name, base_class->get_member(name).get_type_name(), itos(base_class->get_member(name).get_line()));
5035 return;
5036 }
5037 base_class = base_class->base_type.class_type;
5038 }
5039 }
5040
5041 StringName parent = base.native_type;
5042 while (parent != StringName()) {
5043 ERR_FAIL_COND_MSG(!class_exists(parent), "Non-existent native base class.");
5044
5045 if (ClassDB::has_method(parent, name, true)) {
5046 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "method", parent);
5047 return;
5048 } else if (ClassDB::has_signal(parent, name, true)) {
5049 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "signal", parent);
5050 return;
5051 } else if (ClassDB::has_property(parent, name, true)) {
5052 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "property", parent);
5053 return;
5054 } else if (ClassDB::has_integer_constant(parent, name, true)) {
5055 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "constant", parent);
5056 return;
5057 } else if (ClassDB::has_enum(parent, name, true)) {
5058 parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "enum", parent);
5059 return;
5060 }
5061 parent = ClassDB::get_parent_class(parent);
5062 }
5063}
5064#endif
5065
5066GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source) {
5067 // Unary version.
5068 GDScriptParser::DataType nil_type;
5069 nil_type.builtin_type = Variant::NIL;
5070 nil_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
5071 return get_operation_type(p_operation, p_a, nil_type, r_valid, p_source);
5072}
5073
5074GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, const GDScriptParser::DataType &p_b, bool &r_valid, const GDScriptParser::Node *p_source) {
5075 if (p_operation == Variant::OP_AND || p_operation == Variant::OP_OR) {
5076 // Those work for any type of argument and always return a boolean.
5077 // They don't use the Variant operator since they have short-circuit semantics.
5078 r_valid = true;
5079 GDScriptParser::DataType result;
5080 result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
5081 result.kind = GDScriptParser::DataType::BUILTIN;
5082 result.builtin_type = Variant::BOOL;
5083 return result;
5084 }
5085
5086 Variant::Type a_type = p_a.builtin_type;
5087 Variant::Type b_type = p_b.builtin_type;
5088
5089 if (p_a.kind == GDScriptParser::DataType::ENUM) {
5090 if (p_a.is_meta_type) {
5091 a_type = Variant::DICTIONARY;
5092 } else {
5093 a_type = Variant::INT;
5094 }
5095 }
5096 if (p_b.kind == GDScriptParser::DataType::ENUM) {
5097 if (p_b.is_meta_type) {
5098 b_type = Variant::DICTIONARY;
5099 } else {
5100 b_type = Variant::INT;
5101 }
5102 }
5103
5104 GDScriptParser::DataType result;
5105 bool hard_operation = p_a.is_hard_type() && p_b.is_hard_type();
5106
5107 if (p_operation == Variant::OP_ADD && a_type == Variant::ARRAY && b_type == Variant::ARRAY) {
5108 if (p_a.has_container_element_type() && p_b.has_container_element_type() && p_a.get_container_element_type() == p_b.get_container_element_type()) {
5109 r_valid = true;
5110 result = p_a;
5111 result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
5112 return result;
5113 }
5114 }
5115
5116 Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type);
5117 bool validated = op_eval != nullptr;
5118
5119 if (validated) {
5120 r_valid = true;
5121 result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
5122 result.kind = GDScriptParser::DataType::BUILTIN;
5123 result.builtin_type = Variant::get_operator_return_type(p_operation, a_type, b_type);
5124 } else {
5125 r_valid = !hard_operation;
5126 result.kind = GDScriptParser::DataType::VARIANT;
5127 }
5128
5129 return result;
5130}
5131
5132// TODO: Add safe/unsafe return variable (for variant cases)
5133bool GDScriptAnalyzer::is_type_compatible(const GDScriptParser::DataType &p_target, const GDScriptParser::DataType &p_source, bool p_allow_implicit_conversion, const GDScriptParser::Node *p_source_node) {
5134 // These return "true" so it doesn't affect users negatively.
5135 ERR_FAIL_COND_V_MSG(!p_target.is_set(), true, "Parser bug (please report): Trying to check compatibility of unset target type");
5136 ERR_FAIL_COND_V_MSG(!p_source.is_set(), true, "Parser bug (please report): Trying to check compatibility of unset value type");
5137
5138 if (p_target.kind == GDScriptParser::DataType::VARIANT) {
5139 // Variant can receive anything.
5140 return true;
5141 }
5142
5143 if (p_source.kind == GDScriptParser::DataType::VARIANT) {
5144 // TODO: This is acceptable but unsafe. Make sure unsafe line is set.
5145 return true;
5146 }
5147
5148 if (p_target.kind == GDScriptParser::DataType::BUILTIN) {
5149 bool valid = p_source.kind == GDScriptParser::DataType::BUILTIN && p_target.builtin_type == p_source.builtin_type;
5150 if (!valid && p_allow_implicit_conversion) {
5151 valid = Variant::can_convert_strict(p_source.builtin_type, p_target.builtin_type);
5152 }
5153 if (!valid && p_target.builtin_type == Variant::INT && p_source.kind == GDScriptParser::DataType::ENUM && !p_source.is_meta_type) {
5154 // Enum value is also integer.
5155 valid = true;
5156 }
5157 if (valid && p_target.builtin_type == Variant::ARRAY && p_source.builtin_type == Variant::ARRAY) {
5158 // Check the element type.
5159 if (p_target.has_container_element_type() && p_source.has_container_element_type()) {
5160 valid = p_target.get_container_element_type() == p_source.get_container_element_type();
5161 }
5162 }
5163 return valid;
5164 }
5165
5166 if (p_target.kind == GDScriptParser::DataType::ENUM) {
5167 if (p_source.kind == GDScriptParser::DataType::BUILTIN && p_source.builtin_type == Variant::INT) {
5168#ifdef DEBUG_ENABLED
5169 if (p_source_node) {
5170 parser->push_warning(p_source_node, GDScriptWarning::INT_AS_ENUM_WITHOUT_CAST);
5171 }
5172#endif
5173 return true;
5174 }
5175 if (p_source.kind == GDScriptParser::DataType::ENUM) {
5176 if (p_source.native_type == p_target.native_type) {
5177 return true;
5178 }
5179 }
5180 return false;
5181 }
5182
5183 // From here on the target type is an object, so we have to test polymorphism.
5184
5185 if (p_source.kind == GDScriptParser::DataType::BUILTIN && p_source.builtin_type == Variant::NIL) {
5186 // null is acceptable in object.
5187 return true;
5188 }
5189
5190 StringName src_native;
5191 Ref<Script> src_script;
5192 const GDScriptParser::ClassNode *src_class = nullptr;
5193
5194 switch (p_source.kind) {
5195 case GDScriptParser::DataType::NATIVE:
5196 if (p_target.kind != GDScriptParser::DataType::NATIVE) {
5197 // Non-native class cannot be supertype of native.
5198 return false;
5199 }
5200 if (p_source.is_meta_type) {
5201 src_native = GDScriptNativeClass::get_class_static();
5202 } else {
5203 src_native = p_source.native_type;
5204 }
5205 break;
5206 case GDScriptParser::DataType::SCRIPT:
5207 if (p_target.kind == GDScriptParser::DataType::CLASS) {
5208 // A script type cannot be a subtype of a GDScript class.
5209 return false;
5210 }
5211 if (p_source.is_meta_type) {
5212 src_native = p_source.script_type->get_class_name();
5213 } else {
5214 src_script = p_source.script_type;
5215 src_native = src_script->get_instance_base_type();
5216 }
5217 break;
5218 case GDScriptParser::DataType::CLASS:
5219 if (p_source.is_meta_type) {
5220 src_native = GDScript::get_class_static();
5221 } else {
5222 src_class = p_source.class_type;
5223 const GDScriptParser::ClassNode *base = src_class;
5224 while (base->base_type.kind == GDScriptParser::DataType::CLASS) {
5225 base = base->base_type.class_type;
5226 }
5227 src_native = base->base_type.native_type;
5228 src_script = base->base_type.script_type;
5229 }
5230 break;
5231 case GDScriptParser::DataType::VARIANT:
5232 case GDScriptParser::DataType::BUILTIN:
5233 case GDScriptParser::DataType::ENUM:
5234 case GDScriptParser::DataType::RESOLVING:
5235 case GDScriptParser::DataType::UNRESOLVED:
5236 break; // Already solved before.
5237 }
5238
5239 switch (p_target.kind) {
5240 case GDScriptParser::DataType::NATIVE: {
5241 if (p_target.is_meta_type) {
5242 return ClassDB::is_parent_class(src_native, GDScriptNativeClass::get_class_static());
5243 }
5244 return ClassDB::is_parent_class(src_native, p_target.native_type);
5245 }
5246 case GDScriptParser::DataType::SCRIPT:
5247 if (p_target.is_meta_type) {
5248 return ClassDB::is_parent_class(src_native, p_target.script_type->get_class_name());
5249 }
5250 while (src_script.is_valid()) {
5251 if (src_script == p_target.script_type) {
5252 return true;
5253 }
5254 src_script = src_script->get_base_script();
5255 }
5256 return false;
5257 case GDScriptParser::DataType::CLASS:
5258 if (p_target.is_meta_type) {
5259 return ClassDB::is_parent_class(src_native, GDScript::get_class_static());
5260 }
5261 while (src_class != nullptr) {
5262 if (src_class == p_target.class_type || src_class->fqcn == p_target.class_type->fqcn) {
5263 return true;
5264 }
5265 src_class = src_class->base_type.class_type;
5266 }
5267 return false;
5268 case GDScriptParser::DataType::VARIANT:
5269 case GDScriptParser::DataType::BUILTIN:
5270 case GDScriptParser::DataType::ENUM:
5271 case GDScriptParser::DataType::RESOLVING:
5272 case GDScriptParser::DataType::UNRESOLVED:
5273 break; // Already solved before.
5274 }
5275
5276 return false;
5277}
5278
5279void GDScriptAnalyzer::push_error(const String &p_message, const GDScriptParser::Node *p_origin) {
5280 mark_node_unsafe(p_origin);
5281 parser->push_error(p_message, p_origin);
5282}
5283
5284void GDScriptAnalyzer::mark_node_unsafe(const GDScriptParser::Node *p_node) {
5285#ifdef DEBUG_ENABLED
5286 if (p_node == nullptr) {
5287 return;
5288 }
5289
5290 for (int i = p_node->start_line; i <= p_node->end_line; i++) {
5291 parser->unsafe_lines.insert(i);
5292 }
5293#endif
5294}
5295
5296void GDScriptAnalyzer::downgrade_node_type_source(GDScriptParser::Node *p_node) {
5297 GDScriptParser::IdentifierNode *identifier = nullptr;
5298 if (p_node->type == GDScriptParser::Node::IDENTIFIER) {
5299 identifier = static_cast<GDScriptParser::IdentifierNode *>(p_node);
5300 } else if (p_node->type == GDScriptParser::Node::SUBSCRIPT) {
5301 GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_node);
5302 if (subscript->is_attribute) {
5303 identifier = subscript->attribute;
5304 }
5305 }
5306 if (identifier == nullptr) {
5307 return;
5308 }
5309
5310 GDScriptParser::Node *source = nullptr;
5311 switch (identifier->source) {
5312 case GDScriptParser::IdentifierNode::MEMBER_VARIABLE: {
5313 source = identifier->variable_source;
5314 } break;
5315 case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER: {
5316 source = identifier->parameter_source;
5317 } break;
5318 case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: {
5319 source = identifier->variable_source;
5320 } break;
5321 case GDScriptParser::IdentifierNode::LOCAL_ITERATOR: {
5322 source = identifier->bind_source;
5323 } break;
5324 default:
5325 break;
5326 }
5327 if (source == nullptr) {
5328 return;
5329 }
5330
5331 GDScriptParser::DataType datatype;
5332 datatype.kind = GDScriptParser::DataType::VARIANT;
5333 source->set_datatype(datatype);
5334}
5335
5336void GDScriptAnalyzer::mark_lambda_use_self() {
5337 GDScriptParser::LambdaNode *lambda = current_lambda;
5338 while (lambda != nullptr) {
5339 lambda->use_self = true;
5340 lambda = lambda->parent_lambda;
5341 }
5342}
5343
5344void GDScriptAnalyzer::resolve_pending_lambda_bodies() {
5345 if (pending_body_resolution_lambdas.is_empty()) {
5346 return;
5347 }
5348
5349 GDScriptParser::LambdaNode *previous_lambda = current_lambda;
5350
5351 List<GDScriptParser::LambdaNode *> lambdas = pending_body_resolution_lambdas;
5352 pending_body_resolution_lambdas.clear();
5353
5354 for (GDScriptParser::LambdaNode *lambda : lambdas) {
5355 current_lambda = lambda;
5356 resolve_function_body(lambda->function, true);
5357
5358 int captures_amount = lambda->captures.size();
5359 if (captures_amount > 0) {
5360 // Create space for lambda parameters.
5361 // At the beginning to not mess with optional parameters.
5362 int param_count = lambda->function->parameters.size();
5363 lambda->function->parameters.resize(param_count + captures_amount);
5364 for (int i = param_count - 1; i >= 0; i--) {
5365 lambda->function->parameters.write[i + captures_amount] = lambda->function->parameters[i];
5366 lambda->function->parameters_indices[lambda->function->parameters[i]->identifier->name] = i + captures_amount;
5367 }
5368
5369 // Add captures as extra parameters at the beginning.
5370 for (int i = 0; i < lambda->captures.size(); i++) {
5371 GDScriptParser::IdentifierNode *capture = lambda->captures[i];
5372 GDScriptParser::ParameterNode *capture_param = parser->alloc_node<GDScriptParser::ParameterNode>();
5373 capture_param->identifier = capture;
5374 capture_param->usages = capture->usages;
5375 capture_param->set_datatype(capture->get_datatype());
5376
5377 lambda->function->parameters.write[i] = capture_param;
5378 lambda->function->parameters_indices[capture->name] = i;
5379 }
5380 }
5381 }
5382
5383 current_lambda = previous_lambda;
5384}
5385
5386bool GDScriptAnalyzer::class_exists(const StringName &p_class) const {
5387 return ClassDB::class_exists(p_class) && ClassDB::is_class_exposed(p_class);
5388}
5389
5390Ref<GDScriptParserRef> GDScriptAnalyzer::get_parser_for(const String &p_path) {
5391 Ref<GDScriptParserRef> ref;
5392 if (depended_parsers.has(p_path)) {
5393 ref = depended_parsers[p_path];
5394 } else {
5395 Error err = OK;
5396 ref = GDScriptCache::get_parser(p_path, GDScriptParserRef::EMPTY, err, parser->script_path);
5397 if (ref.is_valid()) {
5398 depended_parsers[p_path] = ref;
5399 }
5400 }
5401
5402 return ref;
5403}
5404
5405Error GDScriptAnalyzer::resolve_inheritance() {
5406 return resolve_class_inheritance(parser->head, true);
5407}
5408
5409Error GDScriptAnalyzer::resolve_interface() {
5410 resolve_class_interface(parser->head, true);
5411 return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
5412}
5413
5414Error GDScriptAnalyzer::resolve_body() {
5415 resolve_class_body(parser->head, true);
5416 return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
5417}
5418
5419Error GDScriptAnalyzer::resolve_dependencies() {
5420 for (KeyValue<String, Ref<GDScriptParserRef>> &K : depended_parsers) {
5421 if (K.value.is_null()) {
5422 return ERR_PARSE_ERROR;
5423 }
5424 K.value->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
5425 }
5426
5427 return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
5428}
5429
5430Error GDScriptAnalyzer::analyze() {
5431 parser->errors.clear();
5432 Error err = OK;
5433
5434 err = resolve_inheritance();
5435 if (err) {
5436 return err;
5437 }
5438
5439 // Apply annotations.
5440 for (GDScriptParser::AnnotationNode *&E : parser->head->annotations) {
5441 resolve_annotation(E);
5442 E->apply(parser, parser->head);
5443 }
5444
5445 resolve_interface();
5446 resolve_body();
5447 if (!parser->errors.is_empty()) {
5448 return ERR_PARSE_ERROR;
5449 }
5450
5451 return resolve_dependencies();
5452}
5453
5454GDScriptAnalyzer::GDScriptAnalyzer(GDScriptParser *p_parser) {
5455 parser = p_parser;
5456}
5457