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