Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/gdscript/gdscript_analyzer.cpp
10277 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 && left_type.builtin_type == Variant::INT && right_type.builtin_type == Variant::INT) {
3106
parser->push_warning(p_binary_op, GDScriptWarning::INTEGER_DIVISION);
3107
}
3108
#endif // DEBUG_ENABLED
3109
3110
if (p_binary_op->left_operand->is_constant && p_binary_op->right_operand->is_constant) {
3111
p_binary_op->is_constant = true;
3112
if (p_binary_op->variant_op < Variant::OP_MAX) {
3113
bool valid = false;
3114
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);
3115
if (!valid) {
3116
if (p_binary_op->reduced_value.get_type() == Variant::STRING) {
3117
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);
3118
} else {
3119
push_error(vformat(R"(Invalid operands to operator %s, %s and %s.)",
3120
Variant::get_operator_name(p_binary_op->variant_op),
3121
Variant::get_type_name(p_binary_op->left_operand->reduced_value.get_type()),
3122
Variant::get_type_name(p_binary_op->right_operand->reduced_value.get_type())),
3123
p_binary_op);
3124
}
3125
}
3126
} else {
3127
ERR_PRINT("Parser bug: unknown binary operation.");
3128
}
3129
p_binary_op->set_datatype(type_from_variant(p_binary_op->reduced_value, p_binary_op));
3130
3131
return;
3132
}
3133
3134
GDScriptParser::DataType result;
3135
3136
if ((p_binary_op->variant_op == Variant::OP_EQUAL || p_binary_op->variant_op == Variant::OP_NOT_EQUAL) &&
3137
((left_type.kind == GDScriptParser::DataType::BUILTIN && left_type.builtin_type == Variant::NIL) || (right_type.kind == GDScriptParser::DataType::BUILTIN && right_type.builtin_type == Variant::NIL))) {
3138
// "==" and "!=" operators always return a boolean when comparing to null.
3139
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3140
result.kind = GDScriptParser::DataType::BUILTIN;
3141
result.builtin_type = Variant::BOOL;
3142
} else if (p_binary_op->variant_op == Variant::OP_MODULE && left_type.builtin_type == Variant::STRING) {
3143
// The modulo operator (%) on string acts as formatting and will always return a string.
3144
result.type_source = left_type.type_source;
3145
result.kind = GDScriptParser::DataType::BUILTIN;
3146
result.builtin_type = Variant::STRING;
3147
} else if (left_type.is_variant() || right_type.is_variant()) {
3148
// Cannot infer type because one operand can be anything.
3149
result.kind = GDScriptParser::DataType::VARIANT;
3150
mark_node_unsafe(p_binary_op);
3151
} else if (p_binary_op->variant_op < Variant::OP_MAX) {
3152
bool valid = false;
3153
result = get_operation_type(p_binary_op->variant_op, left_type, right_type, valid, p_binary_op);
3154
if (!valid) {
3155
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);
3156
} else if (!result.is_hard_type()) {
3157
mark_node_unsafe(p_binary_op);
3158
}
3159
} else {
3160
ERR_PRINT("Parser bug: unknown binary operation.");
3161
}
3162
3163
p_binary_op->set_datatype(result);
3164
}
3165
3166
#ifdef SUGGEST_GODOT4_RENAMES
3167
const char *get_rename_from_map(const char *map[][2], String key) {
3168
for (int index = 0; map[index][0]; index++) {
3169
if (map[index][0] == key) {
3170
return map[index][1];
3171
}
3172
}
3173
return nullptr;
3174
}
3175
3176
// Checks if an identifier/function name has been renamed in Godot 4, uses ProjectConverter3To4 for rename map.
3177
// Returns the new name if found, nullptr otherwise.
3178
const char *check_for_renamed_identifier(String identifier, GDScriptParser::Node::Type type) {
3179
switch (type) {
3180
case GDScriptParser::Node::IDENTIFIER: {
3181
// Check properties
3182
const char *result = get_rename_from_map(RenamesMap3To4::gdscript_properties_renames, identifier);
3183
if (result) {
3184
return result;
3185
}
3186
// Check enum values
3187
result = get_rename_from_map(RenamesMap3To4::enum_renames, identifier);
3188
if (result) {
3189
return result;
3190
}
3191
// Check color constants
3192
result = get_rename_from_map(RenamesMap3To4::color_renames, identifier);
3193
if (result) {
3194
return result;
3195
}
3196
// Check type names
3197
result = get_rename_from_map(RenamesMap3To4::class_renames, identifier);
3198
if (result) {
3199
return result;
3200
}
3201
return get_rename_from_map(RenamesMap3To4::builtin_types_renames, identifier);
3202
}
3203
case GDScriptParser::Node::CALL: {
3204
const char *result = get_rename_from_map(RenamesMap3To4::gdscript_function_renames, identifier);
3205
if (result) {
3206
return result;
3207
}
3208
// Built-in Types are mistaken for function calls when the built-in type is not found.
3209
// Check built-in types if function rename not found
3210
return get_rename_from_map(RenamesMap3To4::builtin_types_renames, identifier);
3211
}
3212
// Signal references don't get parsed through the GDScriptAnalyzer. No support for signal rename hints.
3213
default:
3214
// No rename found, return null
3215
return nullptr;
3216
}
3217
}
3218
#endif // SUGGEST_GODOT4_RENAMES
3219
3220
void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_await, bool p_is_root) {
3221
bool all_is_constant = true;
3222
HashMap<int, GDScriptParser::ArrayNode *> arrays; // For array literal to potentially type when passing.
3223
HashMap<int, GDScriptParser::DictionaryNode *> dictionaries; // Same, but for dictionaries.
3224
for (int i = 0; i < p_call->arguments.size(); i++) {
3225
reduce_expression(p_call->arguments[i]);
3226
if (p_call->arguments[i]->type == GDScriptParser::Node::ARRAY) {
3227
arrays[i] = static_cast<GDScriptParser::ArrayNode *>(p_call->arguments[i]);
3228
} else if (p_call->arguments[i]->type == GDScriptParser::Node::DICTIONARY) {
3229
dictionaries[i] = static_cast<GDScriptParser::DictionaryNode *>(p_call->arguments[i]);
3230
}
3231
all_is_constant = all_is_constant && p_call->arguments[i]->is_constant;
3232
}
3233
3234
GDScriptParser::Node::Type callee_type = p_call->get_callee_type();
3235
GDScriptParser::DataType call_type;
3236
3237
if (!p_call->is_super && callee_type == GDScriptParser::Node::IDENTIFIER) {
3238
// Call to name directly.
3239
StringName function_name = p_call->function_name;
3240
3241
if (function_name == SNAME("Object")) {
3242
push_error(R"*(Invalid constructor "Object()", use "Object.new()" instead.)*", p_call);
3243
p_call->set_datatype(call_type);
3244
return;
3245
}
3246
3247
Variant::Type builtin_type = GDScriptParser::get_builtin_type(function_name);
3248
if (builtin_type < Variant::VARIANT_MAX) {
3249
// Is a builtin constructor.
3250
call_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3251
call_type.kind = GDScriptParser::DataType::BUILTIN;
3252
call_type.builtin_type = builtin_type;
3253
3254
bool safe_to_fold = true;
3255
switch (builtin_type) {
3256
// Those are stored by reference so not suited for compile-time construction.
3257
// Because in this case they would be the same reference in all constructed values.
3258
case Variant::OBJECT:
3259
case Variant::DICTIONARY:
3260
case Variant::ARRAY:
3261
case Variant::PACKED_BYTE_ARRAY:
3262
case Variant::PACKED_INT32_ARRAY:
3263
case Variant::PACKED_INT64_ARRAY:
3264
case Variant::PACKED_FLOAT32_ARRAY:
3265
case Variant::PACKED_FLOAT64_ARRAY:
3266
case Variant::PACKED_STRING_ARRAY:
3267
case Variant::PACKED_VECTOR2_ARRAY:
3268
case Variant::PACKED_VECTOR3_ARRAY:
3269
case Variant::PACKED_COLOR_ARRAY:
3270
case Variant::PACKED_VECTOR4_ARRAY:
3271
safe_to_fold = false;
3272
break;
3273
default:
3274
break;
3275
}
3276
3277
if (all_is_constant && safe_to_fold) {
3278
// Construct here.
3279
Vector<const Variant *> args;
3280
for (int i = 0; i < p_call->arguments.size(); i++) {
3281
args.push_back(&(p_call->arguments[i]->reduced_value));
3282
}
3283
3284
Callable::CallError err;
3285
Variant value;
3286
Variant::construct(builtin_type, value, (const Variant **)args.ptr(), args.size(), err);
3287
3288
switch (err.error) {
3289
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
3290
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,
3291
Variant::get_type_name(Variant::Type(err.expected)), p_call->arguments[err.argument]->get_datatype().to_string()),
3292
p_call->arguments[err.argument]);
3293
break;
3294
case Callable::CallError::CALL_ERROR_INVALID_METHOD: {
3295
String signature = Variant::get_type_name(builtin_type) + "(";
3296
for (int i = 0; i < p_call->arguments.size(); i++) {
3297
if (i > 0) {
3298
signature += ", ";
3299
}
3300
signature += p_call->arguments[i]->get_datatype().to_string();
3301
}
3302
signature += ")";
3303
push_error(vformat(R"(No constructor of "%s" matches the signature "%s".)", Variant::get_type_name(builtin_type), signature), p_call->callee);
3304
} break;
3305
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
3306
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);
3307
break;
3308
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
3309
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);
3310
break;
3311
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
3312
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
3313
break; // Can't happen in a builtin constructor.
3314
case Callable::CallError::CALL_OK:
3315
p_call->is_constant = true;
3316
p_call->reduced_value = value;
3317
break;
3318
}
3319
} else {
3320
// If there's one argument, try to use copy constructor (those aren't explicitly defined).
3321
if (p_call->arguments.size() == 1) {
3322
GDScriptParser::DataType arg_type = p_call->arguments[0]->get_datatype();
3323
if (arg_type.is_hard_type() && !arg_type.is_variant()) {
3324
if (arg_type.kind == GDScriptParser::DataType::BUILTIN && arg_type.builtin_type == builtin_type) {
3325
// Okay.
3326
p_call->set_datatype(call_type);
3327
return;
3328
}
3329
} else {
3330
#ifdef DEBUG_ENABLED
3331
mark_node_unsafe(p_call);
3332
// Constructors support overloads.
3333
Vector<String> types;
3334
for (int i = 0; i < Variant::VARIANT_MAX; i++) {
3335
if (i != builtin_type && Variant::can_convert_strict((Variant::Type)i, builtin_type)) {
3336
types.push_back(Variant::get_type_name((Variant::Type)i));
3337
}
3338
}
3339
String expected_types = function_name;
3340
if (types.size() == 1) {
3341
expected_types += "\" or \"" + types[0];
3342
} else if (types.size() >= 2) {
3343
for (int i = 0; i < types.size() - 1; i++) {
3344
expected_types += "\", \"" + types[i];
3345
}
3346
expected_types += "\", or \"" + types[types.size() - 1];
3347
}
3348
parser->push_warning(p_call->arguments[0], GDScriptWarning::UNSAFE_CALL_ARGUMENT, "1", "constructor", function_name, expected_types, "Variant");
3349
#endif // DEBUG_ENABLED
3350
p_call->set_datatype(call_type);
3351
return;
3352
}
3353
}
3354
3355
List<MethodInfo> constructors;
3356
Variant::get_constructor_list(builtin_type, &constructors);
3357
bool match = false;
3358
3359
for (const MethodInfo &info : constructors) {
3360
if (p_call->arguments.size() < info.arguments.size() - info.default_arguments.size()) {
3361
continue;
3362
}
3363
if (p_call->arguments.size() > info.arguments.size()) {
3364
continue;
3365
}
3366
3367
bool types_match = true;
3368
3369
for (int64_t i = 0; i < p_call->arguments.size(); ++i) {
3370
GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
3371
GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
3372
if (!is_type_compatible(par_type, arg_type, true)) {
3373
types_match = false;
3374
break;
3375
#ifdef DEBUG_ENABLED
3376
} else {
3377
if (par_type.builtin_type == Variant::INT && arg_type.builtin_type == Variant::FLOAT && builtin_type != Variant::INT) {
3378
parser->push_warning(p_call, GDScriptWarning::NARROWING_CONVERSION, function_name);
3379
}
3380
#endif // DEBUG_ENABLED
3381
}
3382
}
3383
3384
if (types_match) {
3385
for (int64_t i = 0; i < p_call->arguments.size(); ++i) {
3386
GDScriptParser::DataType par_type = type_from_property(info.arguments[i], true);
3387
if (p_call->arguments[i]->is_constant) {
3388
update_const_expression_builtin_type(p_call->arguments[i], par_type, "pass");
3389
}
3390
#ifdef DEBUG_ENABLED
3391
if (!(par_type.is_variant() && par_type.is_hard_type())) {
3392
GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
3393
if (arg_type.is_variant() || !arg_type.is_hard_type()) {
3394
mark_node_unsafe(p_call);
3395
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());
3396
}
3397
}
3398
#endif // DEBUG_ENABLED
3399
}
3400
match = true;
3401
call_type = type_from_property(info.return_val);
3402
break;
3403
}
3404
}
3405
3406
if (!match) {
3407
String signature = Variant::get_type_name(builtin_type) + "(";
3408
for (int i = 0; i < p_call->arguments.size(); i++) {
3409
if (i > 0) {
3410
signature += ", ";
3411
}
3412
signature += p_call->arguments[i]->get_datatype().to_string();
3413
}
3414
signature += ")";
3415
push_error(vformat(R"(No constructor of "%s" matches the signature "%s".)", Variant::get_type_name(builtin_type), signature), p_call);
3416
}
3417
}
3418
3419
#ifdef DEBUG_ENABLED
3420
// Consider `Signal(self, "my_signal")` as an implicit use of the signal.
3421
if (builtin_type == Variant::SIGNAL && p_call->arguments.size() >= 2) {
3422
const GDScriptParser::ExpressionNode *object_arg = p_call->arguments[0];
3423
if (object_arg && object_arg->type == GDScriptParser::Node::SELF) {
3424
const GDScriptParser::ExpressionNode *signal_arg = p_call->arguments[1];
3425
if (signal_arg && signal_arg->is_constant) {
3426
const StringName &signal_name = signal_arg->reduced_value;
3427
if (parser->current_class->has_member(signal_name)) {
3428
const GDScriptParser::ClassNode::Member &member = parser->current_class->get_member(signal_name);
3429
if (member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
3430
member.signal->usages++;
3431
}
3432
}
3433
}
3434
}
3435
}
3436
#endif // DEBUG_ENABLED
3437
3438
p_call->set_datatype(call_type);
3439
return;
3440
} else if (GDScriptUtilityFunctions::function_exists(function_name)) {
3441
MethodInfo function_info = GDScriptUtilityFunctions::get_function_info(function_name);
3442
3443
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)) {
3444
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
3445
}
3446
3447
if (all_is_constant && GDScriptUtilityFunctions::is_function_constant(function_name)) {
3448
// Can call on compilation.
3449
Vector<const Variant *> args;
3450
for (int i = 0; i < p_call->arguments.size(); i++) {
3451
args.push_back(&(p_call->arguments[i]->reduced_value));
3452
}
3453
3454
Variant value;
3455
Callable::CallError err;
3456
GDScriptUtilityFunctions::get_function(function_name)(&value, (const Variant **)args.ptr(), args.size(), err);
3457
3458
switch (err.error) {
3459
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
3460
if (value.get_type() == Variant::STRING && !value.operator String().is_empty()) {
3461
push_error(vformat(R"*(Invalid argument for "%s()" function: %s)*", function_name, value), p_call->arguments[err.argument]);
3462
} else {
3463
// Do not use `type_from_property()` for expected type, since utility functions use their own checks.
3464
push_error(vformat(R"*(Invalid argument for "%s()" function: argument %d should be "%s" but is "%s".)*", function_name, err.argument + 1,
3465
Variant::get_type_name((Variant::Type)err.expected), p_call->arguments[err.argument]->get_datatype().to_string()),
3466
p_call->arguments[err.argument]);
3467
}
3468
break;
3469
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
3470
push_error(vformat(R"(Invalid call for function "%s".)", function_name), p_call);
3471
break;
3472
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
3473
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);
3474
break;
3475
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
3476
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);
3477
break;
3478
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
3479
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
3480
break; // Can't happen in a builtin constructor.
3481
case Callable::CallError::CALL_OK:
3482
p_call->is_constant = true;
3483
p_call->reduced_value = value;
3484
break;
3485
}
3486
} else {
3487
validate_call_arg(function_info, p_call);
3488
}
3489
p_call->set_datatype(type_from_property(function_info.return_val));
3490
return;
3491
} else if (Variant::has_utility_function(function_name)) {
3492
MethodInfo function_info = info_from_utility_func(function_name);
3493
3494
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)) {
3495
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", function_name), p_call);
3496
}
3497
3498
if (all_is_constant && Variant::get_utility_function_type(function_name) == Variant::UTILITY_FUNC_TYPE_MATH) {
3499
// Can call on compilation.
3500
Vector<const Variant *> args;
3501
for (int i = 0; i < p_call->arguments.size(); i++) {
3502
args.push_back(&(p_call->arguments[i]->reduced_value));
3503
}
3504
3505
Variant value;
3506
Callable::CallError err;
3507
Variant::call_utility_function(function_name, &value, (const Variant **)args.ptr(), args.size(), err);
3508
3509
switch (err.error) {
3510
case Callable::CallError::CALL_ERROR_INVALID_ARGUMENT:
3511
if (value.get_type() == Variant::STRING && !value.operator String().is_empty()) {
3512
push_error(vformat(R"*(Invalid argument for "%s()" function: %s)*", function_name, value), p_call->arguments[err.argument]);
3513
} else {
3514
// Do not use `type_from_property()` for expected type, since utility functions use their own checks.
3515
push_error(vformat(R"*(Invalid argument for "%s()" function: argument %d should be "%s" but is "%s".)*", function_name, err.argument + 1,
3516
Variant::get_type_name((Variant::Type)err.expected), p_call->arguments[err.argument]->get_datatype().to_string()),
3517
p_call->arguments[err.argument]);
3518
}
3519
break;
3520
case Callable::CallError::CALL_ERROR_INVALID_METHOD:
3521
push_error(vformat(R"(Invalid call for function "%s".)", function_name), p_call);
3522
break;
3523
case Callable::CallError::CALL_ERROR_TOO_MANY_ARGUMENTS:
3524
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);
3525
break;
3526
case Callable::CallError::CALL_ERROR_TOO_FEW_ARGUMENTS:
3527
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);
3528
break;
3529
case Callable::CallError::CALL_ERROR_METHOD_NOT_CONST:
3530
case Callable::CallError::CALL_ERROR_INSTANCE_IS_NULL:
3531
break; // Can't happen in a builtin constructor.
3532
case Callable::CallError::CALL_OK:
3533
p_call->is_constant = true;
3534
p_call->reduced_value = value;
3535
break;
3536
}
3537
} else {
3538
validate_call_arg(function_info, p_call);
3539
}
3540
p_call->set_datatype(type_from_property(function_info.return_val));
3541
return;
3542
}
3543
}
3544
3545
GDScriptParser::DataType base_type;
3546
call_type.kind = GDScriptParser::DataType::VARIANT;
3547
bool is_self = false;
3548
3549
if (p_call->is_super) {
3550
base_type = parser->current_class->base_type;
3551
base_type.is_meta_type = false;
3552
is_self = true;
3553
3554
if (p_call->callee == nullptr && current_lambda != nullptr) {
3555
push_error("Cannot use `super()` inside a lambda.", p_call);
3556
}
3557
} else if (callee_type == GDScriptParser::Node::IDENTIFIER) {
3558
base_type = parser->current_class->get_datatype();
3559
base_type.is_meta_type = false;
3560
is_self = true;
3561
} else if (callee_type == GDScriptParser::Node::SUBSCRIPT) {
3562
GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee);
3563
if (subscript->base == nullptr) {
3564
// Invalid syntax, error already set on parser.
3565
p_call->set_datatype(call_type);
3566
mark_node_unsafe(p_call);
3567
return;
3568
}
3569
if (!subscript->is_attribute) {
3570
// Invalid call. Error already sent in parser.
3571
// TODO: Could check if Callable here.
3572
p_call->set_datatype(call_type);
3573
mark_node_unsafe(p_call);
3574
return;
3575
}
3576
if (subscript->attribute == nullptr) {
3577
// Invalid call. Error already sent in parser.
3578
p_call->set_datatype(call_type);
3579
mark_node_unsafe(p_call);
3580
return;
3581
}
3582
3583
GDScriptParser::IdentifierNode *base_id = nullptr;
3584
if (subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
3585
base_id = static_cast<GDScriptParser::IdentifierNode *>(subscript->base);
3586
}
3587
if (base_id && GDScriptParser::get_builtin_type(base_id->name) < Variant::VARIANT_MAX) {
3588
base_type = make_builtin_meta_type(GDScriptParser::get_builtin_type(base_id->name));
3589
} else {
3590
reduce_expression(subscript->base);
3591
base_type = subscript->base->get_datatype();
3592
is_self = subscript->base->type == GDScriptParser::Node::SELF;
3593
}
3594
} else {
3595
// Invalid call. Error already sent in parser.
3596
// TODO: Could check if Callable here too.
3597
p_call->set_datatype(call_type);
3598
mark_node_unsafe(p_call);
3599
return;
3600
}
3601
3602
int default_arg_count = 0;
3603
BitField<MethodFlags> method_flags = {};
3604
GDScriptParser::DataType return_type;
3605
List<GDScriptParser::DataType> par_types;
3606
3607
bool is_constructor = (base_type.is_meta_type || (p_call->callee && p_call->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_call->function_name == SNAME("new");
3608
3609
if (is_constructor) {
3610
if (Engine::get_singleton()->has_singleton(base_type.native_type)) {
3611
push_error(vformat(R"(Cannot construct native class "%s" because it is an engine singleton.)", base_type.native_type), p_call);
3612
p_call->set_datatype(call_type);
3613
return;
3614
}
3615
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())) {
3616
push_error(vformat(R"(Cannot construct abstract class "%s".)", base_type.to_string()), p_call);
3617
}
3618
}
3619
3620
if (get_function_signature(p_call, is_constructor, base_type, p_call->function_name, return_type, par_types, default_arg_count, method_flags)) {
3621
p_call->is_static = method_flags.has_flag(METHOD_FLAG_STATIC);
3622
// 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.
3623
// 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.
3624
if (p_call->is_super) {
3625
if (method_flags.has_flag(METHOD_FLAG_VIRTUAL)) {
3626
push_error(vformat(R"*(Cannot call the parent class' virtual function "%s()" because it hasn't been defined.)*", p_call->function_name), p_call);
3627
} else if (method_flags.has_flag(METHOD_FLAG_VIRTUAL_REQUIRED)) {
3628
push_error(vformat(R"*(Cannot call the parent class' abstract function "%s()" because it hasn't been defined.)*", p_call->function_name), p_call);
3629
}
3630
}
3631
3632
// If the function requires typed arrays we must make literals be typed.
3633
for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) {
3634
int index = E.key;
3635
if (index < par_types.size() && par_types.get(index).is_hard_type() && par_types.get(index).has_container_element_type(0)) {
3636
update_array_literal_element_type(E.value, par_types.get(index).get_container_element_type(0));
3637
}
3638
}
3639
for (const KeyValue<int, GDScriptParser::DictionaryNode *> &E : dictionaries) {
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_types()) {
3642
GDScriptParser::DataType key = par_types.get(index).get_container_element_type_or_variant(0);
3643
GDScriptParser::DataType value = par_types.get(index).get_container_element_type_or_variant(1);
3644
update_dictionary_literal_element_type(E.value, key, value);
3645
}
3646
}
3647
validate_call_arg(par_types, default_arg_count, method_flags.has_flag(METHOD_FLAG_VARARG), p_call);
3648
3649
if (base_type.kind == GDScriptParser::DataType::ENUM && base_type.is_meta_type) {
3650
// Enum type is treated as a dictionary value for function calls.
3651
base_type.is_meta_type = false;
3652
}
3653
3654
if (is_self && static_context && !p_call->is_static) {
3655
// Get the parent function above any lambda.
3656
GDScriptParser::FunctionNode *parent_function = parser->current_function;
3657
while (parent_function && parent_function->source_lambda) {
3658
parent_function = parent_function->source_lambda->parent_function;
3659
}
3660
3661
if (parent_function) {
3662
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);
3663
} else {
3664
push_error(vformat(R"*(Cannot call non-static function "%s()" from a static variable initializer.)*", p_call->function_name), p_call);
3665
}
3666
} else if (!is_self && base_type.is_meta_type && !p_call->is_static) {
3667
base_type.is_meta_type = false; // For `to_string()`.
3668
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);
3669
} else if (is_self && !p_call->is_static) {
3670
mark_lambda_use_self();
3671
}
3672
3673
if (!p_is_root && !p_is_await && return_type.is_hard_type() && return_type.kind == GDScriptParser::DataType::BUILTIN && return_type.builtin_type == Variant::NIL) {
3674
push_error(vformat(R"*(Cannot get return value of call to "%s()" because it returns "void".)*", p_call->function_name), p_call);
3675
}
3676
3677
#ifdef DEBUG_ENABLED
3678
// FIXME: No warning for built-in constructors and utilities due to early return.
3679
if (p_is_root && return_type.kind != GDScriptParser::DataType::UNRESOLVED && return_type.builtin_type != Variant::NIL &&
3680
!(p_call->is_super && p_call->function_name == GDScriptLanguage::get_singleton()->strings._init)) {
3681
parser->push_warning(p_call, GDScriptWarning::RETURN_VALUE_DISCARDED, p_call->function_name);
3682
}
3683
3684
if (method_flags.has_flag(METHOD_FLAG_STATIC) && !is_constructor && !base_type.is_meta_type && !is_self) {
3685
String caller_type = base_type.to_string();
3686
3687
parser->push_warning(p_call, GDScriptWarning::STATIC_CALLED_ON_INSTANCE, p_call->function_name, caller_type);
3688
}
3689
3690
// Consider `emit_signal()`, `connect()`, and `disconnect()` as implicit uses of the signal.
3691
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()) {
3692
const GDScriptParser::ExpressionNode *signal_arg = p_call->arguments[0];
3693
if (signal_arg && signal_arg->is_constant) {
3694
const StringName &signal_name = signal_arg->reduced_value;
3695
if (parser->current_class->has_member(signal_name)) {
3696
const GDScriptParser::ClassNode::Member &member = parser->current_class->get_member(signal_name);
3697
if (member.type == GDScriptParser::ClassNode::Member::SIGNAL) {
3698
member.signal->usages++;
3699
}
3700
}
3701
}
3702
}
3703
#endif // DEBUG_ENABLED
3704
3705
call_type = return_type;
3706
} else {
3707
bool found = false;
3708
3709
// Enums do not have functions other than the built-in dictionary ones.
3710
if (base_type.kind == GDScriptParser::DataType::ENUM && base_type.is_meta_type) {
3711
if (base_type.builtin_type == Variant::DICTIONARY) {
3712
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);
3713
} else {
3714
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);
3715
}
3716
} else if (!p_call->is_super && callee_type != GDScriptParser::Node::NONE) { // Check if the name exists as something else.
3717
GDScriptParser::IdentifierNode *callee_id;
3718
if (callee_type == GDScriptParser::Node::IDENTIFIER) {
3719
callee_id = static_cast<GDScriptParser::IdentifierNode *>(p_call->callee);
3720
} else {
3721
// Can only be attribute.
3722
callee_id = static_cast<GDScriptParser::SubscriptNode *>(p_call->callee)->attribute;
3723
}
3724
if (callee_id) {
3725
reduce_identifier_from_base(callee_id, &base_type);
3726
GDScriptParser::DataType callee_datatype = callee_id->get_datatype();
3727
if (callee_datatype.is_set() && !callee_datatype.is_variant()) {
3728
found = true;
3729
if (callee_datatype.builtin_type == Variant::CALLABLE) {
3730
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);
3731
} else {
3732
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);
3733
}
3734
#ifdef DEBUG_ENABLED
3735
} else if (!is_self && !(base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::BUILTIN)) {
3736
parser->push_warning(p_call, GDScriptWarning::UNSAFE_METHOD_ACCESS, p_call->function_name, base_type.to_string());
3737
mark_node_unsafe(p_call);
3738
#endif // DEBUG_ENABLED
3739
}
3740
}
3741
}
3742
if (!found && (is_self || (base_type.is_hard_type() && base_type.kind == GDScriptParser::DataType::BUILTIN))) {
3743
String base_name = is_self && !p_call->is_super ? "self" : base_type.to_string();
3744
#ifdef SUGGEST_GODOT4_RENAMES
3745
String rename_hint;
3746
if (GLOBAL_GET_CACHED(bool, "debug/gdscript/warnings/renamed_in_godot_4_hint")) {
3747
const char *renamed_function_name = check_for_renamed_identifier(p_call->function_name, p_call->type);
3748
if (renamed_function_name) {
3749
rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", String(renamed_function_name) + "()");
3750
}
3751
}
3752
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);
3753
#else
3754
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);
3755
#endif // SUGGEST_GODOT4_RENAMES
3756
} else if (!found && (!p_call->is_super && base_type.is_hard_type() && base_type.is_meta_type)) {
3757
push_error(vformat(R"*(Static function "%s()" not found in base "%s".)*", p_call->function_name, base_type.to_string()), p_call);
3758
}
3759
}
3760
3761
if (call_type.is_coroutine && !p_is_await && !p_is_root) {
3762
push_error(vformat(R"*(Function "%s()" is a coroutine, so it must be called with "await".)*", p_call->function_name), p_call);
3763
}
3764
3765
p_call->set_datatype(call_type);
3766
}
3767
3768
void GDScriptAnalyzer::reduce_cast(GDScriptParser::CastNode *p_cast) {
3769
reduce_expression(p_cast->operand);
3770
3771
GDScriptParser::DataType cast_type = type_from_metatype(resolve_datatype(p_cast->cast_type));
3772
3773
if (!cast_type.is_set()) {
3774
mark_node_unsafe(p_cast);
3775
return;
3776
}
3777
3778
p_cast->set_datatype(cast_type);
3779
if (p_cast->operand->is_constant) {
3780
update_const_expression_builtin_type(p_cast->operand, cast_type, "cast", true);
3781
if (cast_type.is_variant() || p_cast->operand->get_datatype() == cast_type) {
3782
p_cast->is_constant = true;
3783
p_cast->reduced_value = p_cast->operand->reduced_value;
3784
}
3785
}
3786
3787
if (p_cast->operand->type == GDScriptParser::Node::ARRAY && cast_type.has_container_element_type(0)) {
3788
update_array_literal_element_type(static_cast<GDScriptParser::ArrayNode *>(p_cast->operand), cast_type.get_container_element_type(0));
3789
}
3790
3791
if (p_cast->operand->type == GDScriptParser::Node::DICTIONARY && cast_type.has_container_element_types()) {
3792
update_dictionary_literal_element_type(static_cast<GDScriptParser::DictionaryNode *>(p_cast->operand),
3793
cast_type.get_container_element_type_or_variant(0), cast_type.get_container_element_type_or_variant(1));
3794
}
3795
3796
if (!cast_type.is_variant()) {
3797
GDScriptParser::DataType op_type = p_cast->operand->get_datatype();
3798
if (op_type.is_variant() || !op_type.is_hard_type()) {
3799
mark_node_unsafe(p_cast);
3800
#ifdef DEBUG_ENABLED
3801
parser->push_warning(p_cast, GDScriptWarning::UNSAFE_CAST, cast_type.to_string());
3802
#endif // DEBUG_ENABLED
3803
} else {
3804
bool valid = false;
3805
if (op_type.builtin_type == Variant::INT && cast_type.kind == GDScriptParser::DataType::ENUM) {
3806
mark_node_unsafe(p_cast);
3807
valid = true;
3808
} else if (op_type.kind == GDScriptParser::DataType::ENUM && cast_type.builtin_type == Variant::INT) {
3809
valid = true;
3810
} else if (op_type.kind == GDScriptParser::DataType::BUILTIN && cast_type.kind == GDScriptParser::DataType::BUILTIN) {
3811
valid = Variant::can_convert(op_type.builtin_type, cast_type.builtin_type);
3812
} else if (op_type.kind != GDScriptParser::DataType::BUILTIN && cast_type.kind != GDScriptParser::DataType::BUILTIN) {
3813
valid = is_type_compatible(cast_type, op_type) || is_type_compatible(op_type, cast_type);
3814
}
3815
3816
if (!valid) {
3817
push_error(vformat(R"(Invalid cast. Cannot convert from "%s" to "%s".)", op_type.to_string(), cast_type.to_string()), p_cast->cast_type);
3818
}
3819
}
3820
}
3821
}
3822
3823
void GDScriptAnalyzer::reduce_dictionary(GDScriptParser::DictionaryNode *p_dictionary) {
3824
HashMap<Variant, GDScriptParser::ExpressionNode *, VariantHasher, StringLikeVariantComparator> elements;
3825
3826
for (int i = 0; i < p_dictionary->elements.size(); i++) {
3827
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
3828
if (p_dictionary->style == GDScriptParser::DictionaryNode::PYTHON_DICT) {
3829
reduce_expression(element.key);
3830
}
3831
reduce_expression(element.value);
3832
3833
if (element.key->is_constant) {
3834
if (elements.has(element.key->reduced_value)) {
3835
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);
3836
} else {
3837
elements[element.key->reduced_value] = element.value;
3838
}
3839
}
3840
}
3841
3842
// It's dictionary in any case.
3843
GDScriptParser::DataType dict_type;
3844
dict_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3845
dict_type.kind = GDScriptParser::DataType::BUILTIN;
3846
dict_type.builtin_type = Variant::DICTIONARY;
3847
dict_type.is_constant = true;
3848
3849
p_dictionary->set_datatype(dict_type);
3850
}
3851
3852
void GDScriptAnalyzer::reduce_get_node(GDScriptParser::GetNodeNode *p_get_node) {
3853
GDScriptParser::DataType result;
3854
result.kind = GDScriptParser::DataType::VARIANT;
3855
3856
if (!ClassDB::is_parent_class(parser->current_class->base_type.native_type, SNAME("Node"))) {
3857
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);
3858
p_get_node->set_datatype(result);
3859
return;
3860
}
3861
3862
if (static_context) {
3863
push_error(vformat(R"*(Cannot use shorthand "get_node()" notation ("%c") in a static function.)*", p_get_node->use_dollar ? '$' : '%'), p_get_node);
3864
p_get_node->set_datatype(result);
3865
return;
3866
}
3867
3868
mark_lambda_use_self();
3869
3870
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
3871
result.kind = GDScriptParser::DataType::NATIVE;
3872
result.builtin_type = Variant::OBJECT;
3873
result.native_type = SNAME("Node");
3874
p_get_node->set_datatype(result);
3875
}
3876
3877
GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const StringName &p_class_name, const GDScriptParser::Node *p_source) {
3878
GDScriptParser::DataType type;
3879
3880
String path = ScriptServer::get_global_class_path(p_class_name);
3881
String ext = path.get_extension();
3882
if (ext == GDScriptLanguage::get_singleton()->get_extension()) {
3883
Ref<GDScriptParserRef> ref = parser->get_depended_parser_for(path);
3884
if (ref.is_null()) {
3885
push_error(vformat(R"(Could not find script for class "%s".)", p_class_name), p_source);
3886
type.type_source = GDScriptParser::DataType::UNDETECTED;
3887
type.kind = GDScriptParser::DataType::VARIANT;
3888
return type;
3889
}
3890
3891
Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
3892
if (err) {
3893
push_error(vformat(R"(Could not resolve class "%s", because of a parser error.)", p_class_name), p_source);
3894
type.type_source = GDScriptParser::DataType::UNDETECTED;
3895
type.kind = GDScriptParser::DataType::VARIANT;
3896
return type;
3897
}
3898
3899
return ref->get_parser()->head->get_datatype();
3900
} else {
3901
return make_script_meta_type(ResourceLoader::load(path, "Script"));
3902
}
3903
}
3904
3905
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) {
3906
// Delicate piece of code that intentionally doesn't use the GDScript cache or `get_depended_parser_for`.
3907
// Search dependencies for the parser that owns `p_class` and make a cache entry for it.
3908
// 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.
3909
// Since https://github.com/godotengine/godot/pull/94871 there can technically be multiple parsers for the same script in the same parser tree.
3910
// Even if unlikely, getting the wrong parser could lead to strange undefined behavior without errors.
3911
3912
if (p_class == nullptr) {
3913
return nullptr;
3914
}
3915
3916
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = external_class_parser_cache.find(p_class)) {
3917
return E->value;
3918
}
3919
3920
if (parser->has_class(p_class)) {
3921
return nullptr;
3922
}
3923
3924
if (p_from_class == nullptr) {
3925
p_from_class = parser->head;
3926
}
3927
3928
Ref<GDScriptParserRef> parser_ref;
3929
for (const GDScriptParser::ClassNode *look_class = p_from_class; look_class != nullptr; look_class = look_class->base_type.class_type) {
3930
if (parser->has_class(look_class)) {
3931
parser_ref = find_cached_external_parser_for_class(p_class, parser);
3932
if (parser_ref.is_valid()) {
3933
break;
3934
}
3935
}
3936
3937
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = external_class_parser_cache.find(look_class)) {
3938
parser_ref = find_cached_external_parser_for_class(p_class, E->value);
3939
if (parser_ref.is_valid()) {
3940
break;
3941
}
3942
}
3943
3944
String look_class_script_path = look_class->get_datatype().script_path;
3945
if (HashMap<String, Ref<GDScriptParserRef>>::Iterator E = parser->depended_parsers.find(look_class_script_path)) {
3946
parser_ref = find_cached_external_parser_for_class(p_class, E->value);
3947
if (parser_ref.is_valid()) {
3948
break;
3949
}
3950
}
3951
}
3952
3953
if (parser_ref.is_null()) {
3954
push_error(vformat(R"(Parser bug (please report): Could not find external parser for class "%s". (%s))", p_class->fqcn, p_context), p_source);
3955
// A null parser will be inserted into the cache, so this error won't spam for the same class.
3956
// This is ok, the values of external_class_parser_cache are not assumed to be valid references.
3957
}
3958
3959
external_class_parser_cache.insert(p_class, parser_ref);
3960
return parser_ref;
3961
}
3962
3963
Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, const Ref<GDScriptParserRef> &p_dependant_parser) {
3964
if (p_dependant_parser.is_null()) {
3965
return nullptr;
3966
}
3967
3968
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = p_dependant_parser->get_analyzer()->external_class_parser_cache.find(p_class)) {
3969
if (E->value.is_valid()) {
3970
// Silently ensure it's parsed.
3971
E->value->raise_status(GDScriptParserRef::PARSED);
3972
if (E->value->get_parser()->has_class(p_class)) {
3973
return E->value;
3974
}
3975
}
3976
}
3977
3978
if (p_dependant_parser->get_parser()->has_class(p_class)) {
3979
return p_dependant_parser;
3980
}
3981
3982
// Silently ensure it's parsed.
3983
p_dependant_parser->raise_status(GDScriptParserRef::PARSED);
3984
return find_cached_external_parser_for_class(p_class, p_dependant_parser->get_parser());
3985
}
3986
3987
Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, GDScriptParser *p_dependant_parser) {
3988
if (p_dependant_parser == nullptr) {
3989
return nullptr;
3990
}
3991
3992
String script_path = p_class->get_datatype().script_path;
3993
if (HashMap<String, Ref<GDScriptParserRef>>::Iterator E = p_dependant_parser->depended_parsers.find(script_path)) {
3994
if (E->value.is_valid()) {
3995
// Silently ensure it's parsed.
3996
E->value->raise_status(GDScriptParserRef::PARSED);
3997
if (E->value->get_parser()->has_class(p_class)) {
3998
return E->value;
3999
}
4000
}
4001
}
4002
4003
return nullptr;
4004
}
4005
4006
Ref<GDScript> GDScriptAnalyzer::get_depended_shallow_script(const String &p_path, Error &r_error) {
4007
// To keep a local cache of the parser for resolving external nodes later.
4008
const String path = ResourceUID::ensure_path(p_path);
4009
parser->get_depended_parser_for(path);
4010
Ref<GDScript> scr = GDScriptCache::get_shallow_script(path, r_error, parser->script_path);
4011
return scr;
4012
}
4013
4014
void GDScriptAnalyzer::reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype) {
4015
ERR_FAIL_NULL(p_identifier);
4016
4017
p_identifier->set_datatype(p_identifier_datatype);
4018
Error err = OK;
4019
Ref<GDScript> scr = get_depended_shallow_script(p_identifier_datatype.script_path, err);
4020
if (err) {
4021
push_error(vformat(R"(Error while getting cache for script "%s".)", p_identifier_datatype.script_path), p_identifier);
4022
return;
4023
}
4024
p_identifier->reduced_value = scr->find_class(p_identifier_datatype.class_type->fqcn);
4025
p_identifier->is_constant = true;
4026
}
4027
4028
void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType *p_base) {
4029
if (!p_identifier->get_datatype().has_no_type()) {
4030
return;
4031
}
4032
4033
GDScriptParser::DataType base;
4034
if (p_base == nullptr) {
4035
base = type_from_metatype(parser->current_class->get_datatype());
4036
} else {
4037
base = *p_base;
4038
}
4039
4040
StringName name = p_identifier->name;
4041
4042
if (base.kind == GDScriptParser::DataType::ENUM) {
4043
if (base.is_meta_type) {
4044
if (base.enum_values.has(name)) {
4045
p_identifier->set_datatype(type_from_metatype(base));
4046
p_identifier->is_constant = true;
4047
p_identifier->reduced_value = base.enum_values[name];
4048
return;
4049
}
4050
4051
// Enum does not have this value, return.
4052
return;
4053
} else {
4054
push_error(R"(Cannot get property from enum value.)", p_identifier);
4055
return;
4056
}
4057
}
4058
4059
if (base.kind == GDScriptParser::DataType::BUILTIN) {
4060
if (base.is_meta_type) {
4061
bool valid = false;
4062
4063
if (Variant::has_constant(base.builtin_type, name)) {
4064
valid = true;
4065
4066
const Variant constant_value = Variant::get_constant_value(base.builtin_type, name);
4067
4068
p_identifier->is_constant = true;
4069
p_identifier->reduced_value = constant_value;
4070
p_identifier->set_datatype(type_from_variant(constant_value, p_identifier));
4071
}
4072
4073
if (!valid) {
4074
const StringName enum_name = Variant::get_enum_for_enumeration(base.builtin_type, name);
4075
if (enum_name != StringName()) {
4076
valid = true;
4077
4078
p_identifier->is_constant = true;
4079
p_identifier->reduced_value = Variant::get_enum_value(base.builtin_type, enum_name, name);
4080
p_identifier->set_datatype(make_builtin_enum_type(enum_name, base.builtin_type, false));
4081
}
4082
}
4083
4084
if (!valid && Variant::has_enum(base.builtin_type, name)) {
4085
valid = true;
4086
4087
p_identifier->set_datatype(make_builtin_enum_type(name, base.builtin_type, true));
4088
}
4089
4090
if (!valid && base.is_hard_type()) {
4091
#ifdef SUGGEST_GODOT4_RENAMES
4092
String rename_hint;
4093
if (GLOBAL_GET_CACHED(bool, "debug/gdscript/warnings/renamed_in_godot_4_hint")) {
4094
const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
4095
if (renamed_identifier_name) {
4096
rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name);
4097
}
4098
}
4099
push_error(vformat(R"(Cannot find member "%s" in base "%s".%s)", name, base.to_string(), rename_hint), p_identifier);
4100
#else
4101
push_error(vformat(R"(Cannot find member "%s" in base "%s".)", name, base.to_string()), p_identifier);
4102
#endif // SUGGEST_GODOT4_RENAMES
4103
}
4104
} else {
4105
switch (base.builtin_type) {
4106
case Variant::NIL: {
4107
if (base.is_hard_type()) {
4108
push_error(vformat(R"(Cannot get property "%s" on a null object.)", name), p_identifier);
4109
}
4110
return;
4111
}
4112
case Variant::DICTIONARY: {
4113
GDScriptParser::DataType dummy;
4114
dummy.kind = GDScriptParser::DataType::VARIANT;
4115
p_identifier->set_datatype(dummy);
4116
return;
4117
}
4118
default: {
4119
Callable::CallError temp;
4120
Variant dummy;
4121
Variant::construct(base.builtin_type, dummy, nullptr, 0, temp);
4122
List<PropertyInfo> properties;
4123
dummy.get_property_list(&properties);
4124
for (const PropertyInfo &prop : properties) {
4125
if (prop.name == name) {
4126
p_identifier->set_datatype(type_from_property(prop));
4127
return;
4128
}
4129
}
4130
if (Variant::has_builtin_method(base.builtin_type, name)) {
4131
p_identifier->set_datatype(make_callable_type(Variant::get_builtin_method_info(base.builtin_type, name)));
4132
return;
4133
}
4134
if (base.is_hard_type()) {
4135
#ifdef SUGGEST_GODOT4_RENAMES
4136
String rename_hint;
4137
if (GLOBAL_GET_CACHED(bool, "debug/gdscript/warnings/renamed_in_godot_4_hint")) {
4138
const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
4139
if (renamed_identifier_name) {
4140
rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name);
4141
}
4142
}
4143
push_error(vformat(R"(Cannot find member "%s" in base "%s".%s)", name, base.to_string(), rename_hint), p_identifier);
4144
#else
4145
push_error(vformat(R"(Cannot find member "%s" in base "%s".)", name, base.to_string()), p_identifier);
4146
#endif // SUGGEST_GODOT4_RENAMES
4147
}
4148
}
4149
}
4150
}
4151
return;
4152
}
4153
4154
GDScriptParser::ClassNode *base_class = base.class_type;
4155
List<GDScriptParser::ClassNode *> script_classes;
4156
bool is_base = true;
4157
4158
if (base_class != nullptr) {
4159
get_class_node_current_scope_classes(base_class, &script_classes, p_identifier);
4160
}
4161
4162
bool is_constructor = base.is_meta_type && p_identifier->name == SNAME("new");
4163
4164
for (GDScriptParser::ClassNode *script_class : script_classes) {
4165
if (p_base == nullptr && script_class->identifier && script_class->identifier->name == name) {
4166
reduce_identifier_from_base_set_class(p_identifier, script_class->get_datatype());
4167
if (script_class->outer != nullptr) {
4168
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
4169
}
4170
return;
4171
}
4172
4173
if (is_constructor) {
4174
name = "_init";
4175
}
4176
4177
if (script_class->has_member(name)) {
4178
resolve_class_member(script_class, name, p_identifier);
4179
4180
GDScriptParser::ClassNode::Member member = script_class->get_member(name);
4181
switch (member.type) {
4182
case GDScriptParser::ClassNode::Member::CONSTANT: {
4183
p_identifier->set_datatype(member.get_datatype());
4184
p_identifier->is_constant = true;
4185
p_identifier->reduced_value = member.constant->initializer->reduced_value;
4186
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4187
p_identifier->constant_source = member.constant;
4188
return;
4189
}
4190
4191
case GDScriptParser::ClassNode::Member::ENUM_VALUE: {
4192
p_identifier->set_datatype(member.get_datatype());
4193
p_identifier->is_constant = true;
4194
p_identifier->reduced_value = member.enum_value.value;
4195
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4196
return;
4197
}
4198
4199
case GDScriptParser::ClassNode::Member::ENUM: {
4200
p_identifier->set_datatype(member.get_datatype());
4201
p_identifier->is_constant = true;
4202
p_identifier->reduced_value = member.m_enum->dictionary;
4203
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4204
return;
4205
}
4206
4207
case GDScriptParser::ClassNode::Member::VARIABLE: {
4208
if (is_base && (!base.is_meta_type || member.variable->is_static)) {
4209
p_identifier->set_datatype(member.get_datatype());
4210
p_identifier->source = member.variable->is_static ? GDScriptParser::IdentifierNode::STATIC_VARIABLE : GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
4211
p_identifier->variable_source = member.variable;
4212
member.variable->usages += 1;
4213
return;
4214
}
4215
} break;
4216
4217
case GDScriptParser::ClassNode::Member::SIGNAL: {
4218
if (is_base && !base.is_meta_type) {
4219
p_identifier->set_datatype(member.get_datatype());
4220
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
4221
p_identifier->signal_source = member.signal;
4222
member.signal->usages += 1;
4223
return;
4224
}
4225
} break;
4226
4227
case GDScriptParser::ClassNode::Member::FUNCTION: {
4228
if (is_base && (!base.is_meta_type || member.function->is_static || is_constructor)) {
4229
p_identifier->set_datatype(make_callable_type(member.function->info));
4230
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_FUNCTION;
4231
p_identifier->function_source = member.function;
4232
p_identifier->function_source_is_static = member.function->is_static;
4233
return;
4234
}
4235
} break;
4236
4237
case GDScriptParser::ClassNode::Member::CLASS: {
4238
reduce_identifier_from_base_set_class(p_identifier, member.get_datatype());
4239
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CLASS;
4240
return;
4241
}
4242
4243
default: {
4244
// Do nothing
4245
}
4246
}
4247
}
4248
4249
if (is_base) {
4250
is_base = script_class->base_type.class_type != nullptr;
4251
if (!is_base && p_base != nullptr) {
4252
break;
4253
}
4254
}
4255
}
4256
4257
// Check non-GDScript scripts.
4258
Ref<Script> script_type = base.script_type;
4259
4260
if (base_class == nullptr && script_type.is_valid()) {
4261
List<PropertyInfo> property_list;
4262
script_type->get_script_property_list(&property_list);
4263
4264
for (const PropertyInfo &property_info : property_list) {
4265
if (property_info.name != p_identifier->name) {
4266
continue;
4267
}
4268
4269
const GDScriptParser::DataType property_type = GDScriptAnalyzer::type_from_property(property_info, false, false);
4270
4271
p_identifier->set_datatype(property_type);
4272
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_VARIABLE;
4273
return;
4274
}
4275
4276
MethodInfo method_info = script_type->get_method_info(p_identifier->name);
4277
4278
if (method_info.name == p_identifier->name) {
4279
p_identifier->set_datatype(make_callable_type(method_info));
4280
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_FUNCTION;
4281
p_identifier->function_source_is_static = method_info.flags & METHOD_FLAG_STATIC;
4282
return;
4283
}
4284
4285
List<MethodInfo> signal_list;
4286
script_type->get_script_signal_list(&signal_list);
4287
4288
for (const MethodInfo &signal_info : signal_list) {
4289
if (signal_info.name != p_identifier->name) {
4290
continue;
4291
}
4292
4293
const GDScriptParser::DataType signal_type = make_signal_type(signal_info);
4294
4295
p_identifier->set_datatype(signal_type);
4296
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
4297
return;
4298
}
4299
4300
HashMap<StringName, Variant> constant_map;
4301
script_type->get_constants(&constant_map);
4302
4303
if (constant_map.has(p_identifier->name)) {
4304
Variant constant = constant_map.get(p_identifier->name);
4305
4306
p_identifier->set_datatype(make_builtin_meta_type(constant.get_type()));
4307
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4308
return;
4309
}
4310
}
4311
4312
// Check native members. No need for native class recursion because Node exposes all Object's properties.
4313
const StringName &native = base.native_type;
4314
4315
if (class_exists(native)) {
4316
if (is_constructor) {
4317
name = "_init";
4318
}
4319
4320
MethodInfo method_info;
4321
if (ClassDB::has_property(native, name)) {
4322
StringName getter_name = ClassDB::get_property_getter(native, name);
4323
MethodBind *getter = ClassDB::get_method(native, getter_name);
4324
if (getter != nullptr) {
4325
bool has_setter = ClassDB::get_property_setter(native, name) != StringName();
4326
p_identifier->set_datatype(type_from_property(getter->get_return_info(), false, !has_setter));
4327
p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4328
}
4329
return;
4330
}
4331
if (ClassDB::get_method_info(native, name, &method_info)) {
4332
// Method is callable.
4333
p_identifier->set_datatype(make_callable_type(method_info));
4334
p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4335
return;
4336
}
4337
if (ClassDB::get_signal(native, name, &method_info)) {
4338
// Signal is a type too.
4339
p_identifier->set_datatype(make_signal_type(method_info));
4340
p_identifier->source = GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4341
return;
4342
}
4343
if (ClassDB::has_enum(native, name)) {
4344
p_identifier->set_datatype(make_native_enum_type(name, native));
4345
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4346
return;
4347
}
4348
bool valid = false;
4349
4350
int64_t int_constant = ClassDB::get_integer_constant(native, name, &valid);
4351
if (valid) {
4352
p_identifier->is_constant = true;
4353
p_identifier->reduced_value = int_constant;
4354
p_identifier->source = GDScriptParser::IdentifierNode::MEMBER_CONSTANT;
4355
4356
// Check whether this constant, which exists, belongs to an enum
4357
StringName enum_name = ClassDB::get_integer_constant_enum(native, name);
4358
if (enum_name != StringName()) {
4359
p_identifier->set_datatype(make_native_enum_type(enum_name, native, false));
4360
} else {
4361
p_identifier->set_datatype(type_from_variant(int_constant, p_identifier));
4362
}
4363
}
4364
}
4365
}
4366
4367
void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_identifier, bool can_be_builtin) {
4368
// TODO: This is an opportunity to further infer types.
4369
4370
// Check if we are inside an enum. This allows enum values to access other elements of the same enum.
4371
if (current_enum) {
4372
for (int i = 0; i < current_enum->values.size(); i++) {
4373
const GDScriptParser::EnumNode::Value &element = current_enum->values[i];
4374
if (element.identifier->name == p_identifier->name) {
4375
StringName enum_name = current_enum->identifier ? current_enum->identifier->name : UNNAMED_ENUM;
4376
GDScriptParser::DataType type = make_class_enum_type(enum_name, parser->current_class, parser->script_path, false);
4377
if (element.parent_enum->identifier) {
4378
type.enum_type = element.parent_enum->identifier->name;
4379
}
4380
p_identifier->set_datatype(type);
4381
4382
if (element.resolved) {
4383
p_identifier->is_constant = true;
4384
p_identifier->reduced_value = element.value;
4385
} else {
4386
push_error(R"(Cannot use another enum element before it was declared.)", p_identifier);
4387
}
4388
return; // Found anyway.
4389
}
4390
}
4391
}
4392
4393
bool found_source = false;
4394
// Check if identifier is local.
4395
// If that's the case, the declaration already was solved before.
4396
switch (p_identifier->source) {
4397
case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER:
4398
p_identifier->set_datatype(p_identifier->parameter_source->get_datatype());
4399
found_source = true;
4400
break;
4401
case GDScriptParser::IdentifierNode::LOCAL_CONSTANT:
4402
case GDScriptParser::IdentifierNode::MEMBER_CONSTANT:
4403
p_identifier->set_datatype(p_identifier->constant_source->get_datatype());
4404
p_identifier->is_constant = true;
4405
// TODO: Constant should have a value on the node itself.
4406
p_identifier->reduced_value = p_identifier->constant_source->initializer->reduced_value;
4407
found_source = true;
4408
break;
4409
case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
4410
p_identifier->signal_source->usages++;
4411
[[fallthrough]];
4412
case GDScriptParser::IdentifierNode::INHERITED_VARIABLE:
4413
mark_lambda_use_self();
4414
break;
4415
case GDScriptParser::IdentifierNode::MEMBER_VARIABLE:
4416
mark_lambda_use_self();
4417
p_identifier->variable_source->usages++;
4418
[[fallthrough]];
4419
case GDScriptParser::IdentifierNode::STATIC_VARIABLE:
4420
case GDScriptParser::IdentifierNode::LOCAL_VARIABLE:
4421
p_identifier->set_datatype(p_identifier->variable_source->get_datatype());
4422
found_source = true;
4423
#ifdef DEBUG_ENABLED
4424
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)) {
4425
parser->push_warning(p_identifier, GDScriptWarning::UNASSIGNED_VARIABLE, p_identifier->name);
4426
}
4427
#endif // DEBUG_ENABLED
4428
break;
4429
case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
4430
p_identifier->set_datatype(p_identifier->bind_source->get_datatype());
4431
found_source = true;
4432
break;
4433
case GDScriptParser::IdentifierNode::LOCAL_BIND: {
4434
GDScriptParser::DataType result = p_identifier->bind_source->get_datatype();
4435
result.is_constant = true;
4436
p_identifier->set_datatype(result);
4437
found_source = true;
4438
} break;
4439
case GDScriptParser::IdentifierNode::UNDEFINED_SOURCE:
4440
case GDScriptParser::IdentifierNode::MEMBER_FUNCTION:
4441
case GDScriptParser::IdentifierNode::MEMBER_CLASS:
4442
case GDScriptParser::IdentifierNode::NATIVE_CLASS:
4443
break;
4444
}
4445
4446
#ifdef DEBUG_ENABLED
4447
if (!found_source && p_identifier->suite != nullptr && p_identifier->suite->has_local(p_identifier->name)) {
4448
parser->push_warning(p_identifier, GDScriptWarning::CONFUSABLE_LOCAL_USAGE, p_identifier->name);
4449
}
4450
#endif // DEBUG_ENABLED
4451
4452
// Not a local, so check members.
4453
4454
if (!found_source) {
4455
reduce_identifier_from_base(p_identifier);
4456
if (p_identifier->source != GDScriptParser::IdentifierNode::UNDEFINED_SOURCE || p_identifier->get_datatype().is_set()) {
4457
// Found.
4458
found_source = true;
4459
}
4460
}
4461
4462
if (found_source) {
4463
const bool source_is_instance_variable = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_VARIABLE || p_identifier->source == GDScriptParser::IdentifierNode::INHERITED_VARIABLE;
4464
const bool source_is_instance_function = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_FUNCTION && !p_identifier->function_source_is_static;
4465
const bool source_is_signal = p_identifier->source == GDScriptParser::IdentifierNode::MEMBER_SIGNAL;
4466
4467
if (static_context && (source_is_instance_variable || source_is_instance_function || source_is_signal)) {
4468
// Get the parent function above any lambda.
4469
GDScriptParser::FunctionNode *parent_function = parser->current_function;
4470
while (parent_function && parent_function->source_lambda) {
4471
parent_function = parent_function->source_lambda->parent_function;
4472
}
4473
4474
String source_type;
4475
if (source_is_instance_variable) {
4476
source_type = "non-static variable";
4477
} else if (source_is_instance_function) {
4478
source_type = "non-static function";
4479
} else { // source_is_signal
4480
source_type = "signal";
4481
}
4482
4483
if (parent_function) {
4484
push_error(vformat(R"*(Cannot access %s "%s" from the static function "%s()".)*", source_type, p_identifier->name, parent_function->identifier->name), p_identifier);
4485
} else {
4486
push_error(vformat(R"*(Cannot access %s "%s" from a static variable initializer.)*", source_type, p_identifier->name), p_identifier);
4487
}
4488
}
4489
4490
if (current_lambda != nullptr) {
4491
// If the identifier is a member variable (including the native class properties), member function, or a signal,
4492
// we consider the lambda to be using `self`, so we keep a reference to the current instance.
4493
if (source_is_instance_variable || source_is_instance_function || source_is_signal) {
4494
mark_lambda_use_self();
4495
return; // No need to capture.
4496
}
4497
4498
switch (p_identifier->source) {
4499
case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER:
4500
case GDScriptParser::IdentifierNode::LOCAL_VARIABLE:
4501
case GDScriptParser::IdentifierNode::LOCAL_ITERATOR:
4502
case GDScriptParser::IdentifierNode::LOCAL_BIND:
4503
break; // Need to capture.
4504
case GDScriptParser::IdentifierNode::UNDEFINED_SOURCE: // A global.
4505
case GDScriptParser::IdentifierNode::LOCAL_CONSTANT:
4506
case GDScriptParser::IdentifierNode::MEMBER_VARIABLE:
4507
case GDScriptParser::IdentifierNode::MEMBER_CONSTANT:
4508
case GDScriptParser::IdentifierNode::MEMBER_FUNCTION:
4509
case GDScriptParser::IdentifierNode::MEMBER_SIGNAL:
4510
case GDScriptParser::IdentifierNode::MEMBER_CLASS:
4511
case GDScriptParser::IdentifierNode::INHERITED_VARIABLE:
4512
case GDScriptParser::IdentifierNode::STATIC_VARIABLE:
4513
case GDScriptParser::IdentifierNode::NATIVE_CLASS:
4514
return; // No need to capture.
4515
}
4516
4517
GDScriptParser::FunctionNode *function_test = current_lambda->function;
4518
// Make sure we aren't capturing variable in the same lambda.
4519
// This also add captures for nested lambdas.
4520
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)) {
4521
function_test->source_lambda->captures_indices[p_identifier->name] = function_test->source_lambda->captures.size();
4522
function_test->source_lambda->captures.push_back(p_identifier);
4523
function_test = function_test->source_lambda->parent_function;
4524
}
4525
}
4526
4527
return;
4528
}
4529
4530
StringName name = p_identifier->name;
4531
p_identifier->source = GDScriptParser::IdentifierNode::UNDEFINED_SOURCE;
4532
4533
// Not a local or a member, so check globals.
4534
4535
Variant::Type builtin_type = GDScriptParser::get_builtin_type(name);
4536
if (builtin_type < Variant::VARIANT_MAX) {
4537
if (can_be_builtin) {
4538
p_identifier->set_datatype(make_builtin_meta_type(builtin_type));
4539
return;
4540
} else {
4541
push_error(R"(Builtin type cannot be used as a name on its own.)", p_identifier);
4542
}
4543
}
4544
4545
if (class_exists(name)) {
4546
p_identifier->source = GDScriptParser::IdentifierNode::NATIVE_CLASS;
4547
p_identifier->set_datatype(make_native_meta_type(name));
4548
return;
4549
}
4550
4551
if (ScriptServer::is_global_class(name)) {
4552
p_identifier->set_datatype(make_global_class_meta_type(name, p_identifier));
4553
return;
4554
}
4555
4556
// Try singletons.
4557
// Do this before globals because this might be a singleton loading another one before it's compiled.
4558
if (ProjectSettings::get_singleton()->has_autoload(name)) {
4559
const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(name);
4560
if (autoload.is_singleton) {
4561
// Singleton exists, so it's at least a Node.
4562
GDScriptParser::DataType result;
4563
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
4564
result.kind = GDScriptParser::DataType::NATIVE;
4565
result.builtin_type = Variant::OBJECT;
4566
result.native_type = SNAME("Node");
4567
if (ResourceLoader::get_resource_type(autoload.path) == "GDScript") {
4568
Ref<GDScriptParserRef> single_parser = parser->get_depended_parser_for(autoload.path);
4569
if (single_parser.is_valid()) {
4570
Error err = single_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
4571
if (err == OK) {
4572
result = type_from_metatype(single_parser->get_parser()->head->get_datatype());
4573
}
4574
}
4575
} else if (ResourceLoader::get_resource_type(autoload.path) == "PackedScene") {
4576
if (GDScriptLanguage::get_singleton()->has_any_global_constant(name)) {
4577
Variant constant = GDScriptLanguage::get_singleton()->get_any_global_constant(name);
4578
Node *node = Object::cast_to<Node>(constant);
4579
if (node != nullptr) {
4580
Ref<GDScript> scr = node->get_script();
4581
if (scr.is_valid()) {
4582
Ref<GDScriptParserRef> single_parser = parser->get_depended_parser_for(scr->get_script_path());
4583
if (single_parser.is_valid()) {
4584
Error err = single_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
4585
if (err == OK) {
4586
result = type_from_metatype(single_parser->get_parser()->head->get_datatype());
4587
}
4588
}
4589
}
4590
}
4591
}
4592
}
4593
result.is_constant = true;
4594
p_identifier->set_datatype(result);
4595
return;
4596
}
4597
}
4598
4599
if (CoreConstants::is_global_constant(name)) {
4600
int index = CoreConstants::get_global_constant_index(name);
4601
StringName enum_name = CoreConstants::get_global_constant_enum(index);
4602
int64_t value = CoreConstants::get_global_constant_value(index);
4603
if (enum_name != StringName()) {
4604
p_identifier->set_datatype(make_global_enum_type(enum_name, StringName(), false));
4605
} else {
4606
p_identifier->set_datatype(type_from_variant(value, p_identifier));
4607
}
4608
p_identifier->is_constant = true;
4609
p_identifier->reduced_value = value;
4610
return;
4611
}
4612
4613
if (GDScriptLanguage::get_singleton()->has_any_global_constant(name)) {
4614
Variant constant = GDScriptLanguage::get_singleton()->get_any_global_constant(name);
4615
p_identifier->set_datatype(type_from_variant(constant, p_identifier));
4616
p_identifier->is_constant = true;
4617
p_identifier->reduced_value = constant;
4618
return;
4619
}
4620
4621
if (CoreConstants::is_global_enum(name)) {
4622
p_identifier->set_datatype(make_global_enum_type(name, StringName(), true));
4623
if (!can_be_builtin) {
4624
push_error(vformat(R"(Global enum "%s" cannot be used on its own.)", name), p_identifier);
4625
}
4626
return;
4627
}
4628
4629
if (Variant::has_utility_function(name) || GDScriptUtilityFunctions::function_exists(name)) {
4630
p_identifier->is_constant = true;
4631
p_identifier->reduced_value = Callable(memnew(GDScriptUtilityCallable(name)));
4632
MethodInfo method_info;
4633
if (GDScriptUtilityFunctions::function_exists(name)) {
4634
method_info = GDScriptUtilityFunctions::get_function_info(name);
4635
} else {
4636
method_info = Variant::get_utility_function_info(name);
4637
}
4638
p_identifier->set_datatype(make_callable_type(method_info));
4639
return;
4640
}
4641
4642
// Allow "Variant" here since it might be used for nested enums.
4643
if (can_be_builtin && name == SNAME("Variant")) {
4644
GDScriptParser::DataType variant;
4645
variant.kind = GDScriptParser::DataType::VARIANT;
4646
variant.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
4647
variant.is_meta_type = true;
4648
variant.is_pseudo_type = true;
4649
p_identifier->set_datatype(variant);
4650
return;
4651
}
4652
4653
// Not found.
4654
#ifdef SUGGEST_GODOT4_RENAMES
4655
String rename_hint;
4656
if (GLOBAL_GET_CACHED(bool, "debug/gdscript/warnings/renamed_in_godot_4_hint")) {
4657
const char *renamed_identifier_name = check_for_renamed_identifier(name, p_identifier->type);
4658
if (renamed_identifier_name) {
4659
rename_hint = " " + vformat(R"(Did you mean to use "%s"?)", renamed_identifier_name);
4660
}
4661
}
4662
push_error(vformat(R"(Identifier "%s" not declared in the current scope.%s)", name, rename_hint), p_identifier);
4663
#else
4664
push_error(vformat(R"(Identifier "%s" not declared in the current scope.)", name), p_identifier);
4665
#endif // SUGGEST_GODOT4_RENAMES
4666
GDScriptParser::DataType dummy;
4667
dummy.kind = GDScriptParser::DataType::VARIANT;
4668
p_identifier->set_datatype(dummy); // Just so type is set to something.
4669
}
4670
4671
void GDScriptAnalyzer::reduce_lambda(GDScriptParser::LambdaNode *p_lambda) {
4672
// Lambda is always a Callable.
4673
GDScriptParser::DataType lambda_type;
4674
lambda_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
4675
lambda_type.kind = GDScriptParser::DataType::BUILTIN;
4676
lambda_type.builtin_type = Variant::CALLABLE;
4677
p_lambda->set_datatype(lambda_type);
4678
4679
if (p_lambda->function == nullptr) {
4680
return;
4681
}
4682
4683
GDScriptParser::LambdaNode *previous_lambda = current_lambda;
4684
current_lambda = p_lambda;
4685
resolve_function_signature(p_lambda->function, p_lambda, true);
4686
current_lambda = previous_lambda;
4687
4688
pending_body_resolution_lambdas.push_back(p_lambda);
4689
}
4690
4691
void GDScriptAnalyzer::reduce_literal(GDScriptParser::LiteralNode *p_literal) {
4692
p_literal->reduced_value = p_literal->value;
4693
p_literal->is_constant = true;
4694
4695
p_literal->set_datatype(type_from_variant(p_literal->reduced_value, p_literal));
4696
}
4697
4698
void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
4699
if (!p_preload->path) {
4700
return;
4701
}
4702
4703
reduce_expression(p_preload->path);
4704
4705
if (!p_preload->path->is_constant) {
4706
push_error("Preloaded path must be a constant string.", p_preload->path);
4707
return;
4708
}
4709
4710
if (p_preload->path->reduced_value.get_type() != Variant::STRING) {
4711
push_error("Preloaded path must be a constant string.", p_preload->path);
4712
} else {
4713
p_preload->resolved_path = p_preload->path->reduced_value;
4714
// TODO: Save this as script dependency.
4715
if (p_preload->resolved_path.is_relative_path()) {
4716
p_preload->resolved_path = parser->script_path.get_base_dir().path_join(p_preload->resolved_path);
4717
}
4718
p_preload->resolved_path = p_preload->resolved_path.simplify_path();
4719
if (!ResourceLoader::exists(p_preload->resolved_path)) {
4720
Ref<FileAccess> file_check = FileAccess::create(FileAccess::ACCESS_RESOURCES);
4721
4722
if (file_check->file_exists(p_preload->resolved_path)) {
4723
push_error(vformat(R"(Preload file "%s" has no resource loaders (unrecognized file extension).)", p_preload->resolved_path), p_preload->path);
4724
} else {
4725
push_error(vformat(R"(Preload file "%s" does not exist.)", p_preload->resolved_path), p_preload->path);
4726
}
4727
} else {
4728
// TODO: Don't load if validating: use completion cache.
4729
4730
// Must load GDScript separately to permit cyclic references
4731
// as ResourceLoader::load() detects and rejects those.
4732
const String &res_type = ResourceLoader::get_resource_type(p_preload->resolved_path);
4733
if (res_type == "GDScript") {
4734
Error err = OK;
4735
Ref<GDScript> res = get_depended_shallow_script(p_preload->resolved_path, err);
4736
p_preload->resource = res;
4737
if (err != OK) {
4738
push_error(vformat(R"(Could not preload resource script "%s".)", p_preload->resolved_path), p_preload->path);
4739
}
4740
} else {
4741
Error err = OK;
4742
p_preload->resource = ResourceLoader::load(p_preload->resolved_path, res_type, ResourceFormatLoader::CACHE_MODE_REUSE, &err);
4743
if (err == ERR_BUSY) {
4744
p_preload->resource = ResourceLoader::ensure_resource_ref_override_for_outer_load(p_preload->resolved_path, res_type);
4745
}
4746
if (p_preload->resource.is_null()) {
4747
push_error(vformat(R"(Could not preload resource file "%s".)", p_preload->resolved_path), p_preload->path);
4748
}
4749
}
4750
}
4751
}
4752
4753
p_preload->is_constant = true;
4754
p_preload->reduced_value = p_preload->resource;
4755
p_preload->set_datatype(type_from_variant(p_preload->reduced_value, p_preload));
4756
4757
// TODO: Not sure if this is necessary anymore.
4758
// 'type_from_variant()' should call 'resolve_class_inheritance()' which would call 'ensure_cached_external_parser_for_class()'
4759
// Better safe than sorry.
4760
ensure_cached_external_parser_for_class(p_preload->get_datatype().class_type, nullptr, "Trying to resolve preload", p_preload);
4761
}
4762
4763
void GDScriptAnalyzer::reduce_self(GDScriptParser::SelfNode *p_self) {
4764
p_self->is_constant = false;
4765
p_self->set_datatype(type_from_metatype(parser->current_class->get_datatype()));
4766
mark_lambda_use_self();
4767
}
4768
4769
void GDScriptAnalyzer::reduce_subscript(GDScriptParser::SubscriptNode *p_subscript, bool p_can_be_pseudo_type) {
4770
if (p_subscript->base == nullptr) {
4771
return;
4772
}
4773
if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
4774
reduce_identifier(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base), true);
4775
} else if (p_subscript->base->type == GDScriptParser::Node::SUBSCRIPT) {
4776
reduce_subscript(static_cast<GDScriptParser::SubscriptNode *>(p_subscript->base), true);
4777
} else {
4778
reduce_expression(p_subscript->base);
4779
}
4780
4781
GDScriptParser::DataType result_type;
4782
4783
if (p_subscript->is_attribute) {
4784
if (p_subscript->attribute == nullptr) {
4785
return;
4786
}
4787
4788
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
4789
bool valid = false;
4790
4791
// If the base is a metatype, use the analyzer instead.
4792
if (p_subscript->base->is_constant && !base_type.is_meta_type) {
4793
// GH-92534. If the base is a GDScript, use the analyzer instead.
4794
bool base_is_gdscript = false;
4795
if (p_subscript->base->reduced_value.get_type() == Variant::OBJECT) {
4796
Ref<GDScript> gdscript = Object::cast_to<GDScript>(p_subscript->base->reduced_value.get_validated_object());
4797
if (gdscript.is_valid()) {
4798
base_is_gdscript = true;
4799
// Makes a metatype from a constant GDScript, since `base_type` is not a metatype.
4800
GDScriptParser::DataType base_type_meta = type_from_variant(gdscript, p_subscript);
4801
// First try to reduce the attribute from the metatype.
4802
reduce_identifier_from_base(p_subscript->attribute, &base_type_meta);
4803
GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
4804
if (attr_type.is_set()) {
4805
valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
4806
result_type = attr_type;
4807
p_subscript->is_constant = p_subscript->attribute->is_constant;
4808
p_subscript->reduced_value = p_subscript->attribute->reduced_value;
4809
}
4810
if (!valid) {
4811
// If unsuccessful, reset and return to the normal route.
4812
p_subscript->attribute->set_datatype(GDScriptParser::DataType());
4813
}
4814
}
4815
}
4816
if (!base_is_gdscript) {
4817
// Just try to get it.
4818
Variant value = p_subscript->base->reduced_value.get_named(p_subscript->attribute->name, valid);
4819
if (valid) {
4820
p_subscript->is_constant = true;
4821
p_subscript->reduced_value = value;
4822
result_type = type_from_variant(value, p_subscript);
4823
}
4824
}
4825
}
4826
4827
if (valid) {
4828
// Do nothing.
4829
} else if (base_type.is_variant() || !base_type.is_hard_type()) {
4830
valid = !base_type.is_pseudo_type || p_can_be_pseudo_type;
4831
result_type.kind = GDScriptParser::DataType::VARIANT;
4832
if (base_type.is_variant() && base_type.is_hard_type() && base_type.is_meta_type && base_type.is_pseudo_type) {
4833
// Special case: it may be a global enum with pseudo base (e.g. Variant.Type).
4834
String enum_name;
4835
if (p_subscript->base->type == GDScriptParser::Node::IDENTIFIER) {
4836
enum_name = String(static_cast<GDScriptParser::IdentifierNode *>(p_subscript->base)->name) + ENUM_SEPARATOR + String(p_subscript->attribute->name);
4837
}
4838
if (CoreConstants::is_global_enum(enum_name)) {
4839
result_type = make_global_enum_type(enum_name, StringName());
4840
} else {
4841
valid = false;
4842
mark_node_unsafe(p_subscript);
4843
}
4844
} else {
4845
mark_node_unsafe(p_subscript);
4846
}
4847
} else {
4848
reduce_identifier_from_base(p_subscript->attribute, &base_type);
4849
GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
4850
if (attr_type.is_set()) {
4851
if (base_type.builtin_type == Variant::DICTIONARY && base_type.has_container_element_types()) {
4852
Variant::Type key_type = base_type.get_container_element_type_or_variant(0).builtin_type;
4853
valid = key_type == Variant::NIL || key_type == Variant::STRING || key_type == Variant::STRING_NAME;
4854
if (base_type.has_container_element_type(1)) {
4855
result_type = base_type.get_container_element_type(1);
4856
result_type.type_source = base_type.type_source;
4857
} else {
4858
result_type.builtin_type = Variant::NIL;
4859
result_type.kind = GDScriptParser::DataType::VARIANT;
4860
result_type.type_source = GDScriptParser::DataType::UNDETECTED;
4861
}
4862
} else {
4863
valid = !attr_type.is_pseudo_type || p_can_be_pseudo_type;
4864
result_type = attr_type;
4865
p_subscript->is_constant = p_subscript->attribute->is_constant;
4866
p_subscript->reduced_value = p_subscript->attribute->reduced_value;
4867
}
4868
} else if (!base_type.is_meta_type || !base_type.is_constant) {
4869
valid = base_type.kind != GDScriptParser::DataType::BUILTIN;
4870
#ifdef DEBUG_ENABLED
4871
if (valid) {
4872
parser->push_warning(p_subscript, GDScriptWarning::UNSAFE_PROPERTY_ACCESS, p_subscript->attribute->name, base_type.to_string());
4873
}
4874
#endif // DEBUG_ENABLED
4875
result_type.kind = GDScriptParser::DataType::VARIANT;
4876
mark_node_unsafe(p_subscript);
4877
}
4878
}
4879
4880
if (!valid) {
4881
GDScriptParser::DataType attr_type = p_subscript->attribute->get_datatype();
4882
if (!p_can_be_pseudo_type && (attr_type.is_pseudo_type || result_type.is_pseudo_type)) {
4883
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);
4884
} else {
4885
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);
4886
}
4887
result_type.kind = GDScriptParser::DataType::VARIANT;
4888
}
4889
} else {
4890
if (p_subscript->index == nullptr) {
4891
return;
4892
}
4893
reduce_expression(p_subscript->index);
4894
4895
if (p_subscript->base->is_constant && p_subscript->index->is_constant) {
4896
// Just try to get it.
4897
bool valid = false;
4898
// TODO: Check if `p_subscript->base->reduced_value` is GDScript.
4899
Variant value = p_subscript->base->reduced_value.get(p_subscript->index->reduced_value, &valid);
4900
if (!valid) {
4901
push_error(vformat(R"(Cannot get index "%s" from "%s".)", p_subscript->index->reduced_value, p_subscript->base->reduced_value), p_subscript->index);
4902
result_type.kind = GDScriptParser::DataType::VARIANT;
4903
} else {
4904
p_subscript->is_constant = true;
4905
p_subscript->reduced_value = value;
4906
result_type = type_from_variant(value, p_subscript);
4907
}
4908
} else {
4909
GDScriptParser::DataType base_type = p_subscript->base->get_datatype();
4910
GDScriptParser::DataType index_type = p_subscript->index->get_datatype();
4911
4912
if (base_type.is_variant()) {
4913
result_type.kind = GDScriptParser::DataType::VARIANT;
4914
mark_node_unsafe(p_subscript);
4915
} else {
4916
if (base_type.kind == GDScriptParser::DataType::BUILTIN && !index_type.is_variant()) {
4917
// Check if indexing is valid.
4918
bool error = index_type.kind != GDScriptParser::DataType::BUILTIN && base_type.builtin_type != Variant::DICTIONARY;
4919
if (!error) {
4920
switch (base_type.builtin_type) {
4921
// Expect int or real as index.
4922
case Variant::PACKED_BYTE_ARRAY:
4923
case Variant::PACKED_FLOAT32_ARRAY:
4924
case Variant::PACKED_FLOAT64_ARRAY:
4925
case Variant::PACKED_INT32_ARRAY:
4926
case Variant::PACKED_INT64_ARRAY:
4927
case Variant::PACKED_STRING_ARRAY:
4928
case Variant::PACKED_VECTOR2_ARRAY:
4929
case Variant::PACKED_VECTOR3_ARRAY:
4930
case Variant::PACKED_COLOR_ARRAY:
4931
case Variant::PACKED_VECTOR4_ARRAY:
4932
case Variant::ARRAY:
4933
case Variant::STRING:
4934
error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT;
4935
break;
4936
// Expect String only.
4937
case Variant::RECT2:
4938
case Variant::RECT2I:
4939
case Variant::PLANE:
4940
case Variant::QUATERNION:
4941
case Variant::AABB:
4942
case Variant::OBJECT:
4943
error = index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
4944
break;
4945
// Expect String or number.
4946
case Variant::BASIS:
4947
case Variant::VECTOR2:
4948
case Variant::VECTOR2I:
4949
case Variant::VECTOR3:
4950
case Variant::VECTOR3I:
4951
case Variant::VECTOR4:
4952
case Variant::VECTOR4I:
4953
case Variant::TRANSFORM2D:
4954
case Variant::TRANSFORM3D:
4955
case Variant::PROJECTION:
4956
error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::FLOAT &&
4957
index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
4958
break;
4959
// Expect String or int.
4960
case Variant::COLOR:
4961
error = index_type.builtin_type != Variant::INT && index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME;
4962
break;
4963
// Don't support indexing, but we will check it later.
4964
case Variant::RID:
4965
case Variant::BOOL:
4966
case Variant::CALLABLE:
4967
case Variant::FLOAT:
4968
case Variant::INT:
4969
case Variant::NIL:
4970
case Variant::NODE_PATH:
4971
case Variant::SIGNAL:
4972
case Variant::STRING_NAME:
4973
break;
4974
// Support depends on if the dictionary has a typed key, otherwise anything is valid.
4975
case Variant::DICTIONARY:
4976
if (base_type.has_container_element_type(0)) {
4977
GDScriptParser::DataType key_type = base_type.get_container_element_type(0);
4978
switch (index_type.builtin_type) {
4979
// Null value will be treated as an empty object, allow.
4980
case Variant::NIL:
4981
error = key_type.builtin_type != Variant::OBJECT;
4982
break;
4983
// Objects are parsed for validity in a similar manner to container types.
4984
case Variant::OBJECT:
4985
if (key_type.builtin_type == Variant::OBJECT) {
4986
error = !key_type.can_reference(index_type);
4987
} else {
4988
error = key_type.builtin_type != Variant::NIL;
4989
}
4990
break;
4991
// String and StringName interchangeable in this context.
4992
case Variant::STRING:
4993
case Variant::STRING_NAME:
4994
error = key_type.builtin_type != Variant::STRING_NAME && key_type.builtin_type != Variant::STRING;
4995
break;
4996
// Ints are valid indices for floats, but not the other way around.
4997
case Variant::INT:
4998
error = key_type.builtin_type != Variant::INT && key_type.builtin_type != Variant::FLOAT;
4999
break;
5000
// All other cases require the types to match exactly.
5001
default:
5002
error = key_type.builtin_type != index_type.builtin_type;
5003
break;
5004
}
5005
}
5006
break;
5007
// Here for completeness.
5008
case Variant::VARIANT_MAX:
5009
break;
5010
}
5011
5012
if (error) {
5013
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);
5014
}
5015
}
5016
} else if (base_type.kind != GDScriptParser::DataType::BUILTIN && !index_type.is_variant()) {
5017
if (index_type.builtin_type != Variant::STRING && index_type.builtin_type != Variant::STRING_NAME) {
5018
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);
5019
}
5020
}
5021
5022
// Check resulting type if possible.
5023
result_type.builtin_type = Variant::NIL;
5024
result_type.kind = GDScriptParser::DataType::BUILTIN;
5025
result_type.type_source = base_type.is_hard_type() ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
5026
5027
if (base_type.kind != GDScriptParser::DataType::BUILTIN) {
5028
base_type.builtin_type = Variant::OBJECT;
5029
}
5030
switch (base_type.builtin_type) {
5031
// Can't index at all.
5032
case Variant::RID:
5033
case Variant::BOOL:
5034
case Variant::CALLABLE:
5035
case Variant::FLOAT:
5036
case Variant::INT:
5037
case Variant::NIL:
5038
case Variant::NODE_PATH:
5039
case Variant::SIGNAL:
5040
case Variant::STRING_NAME:
5041
result_type.kind = GDScriptParser::DataType::VARIANT;
5042
push_error(vformat(R"(Cannot use subscript operator on a base of type "%s".)", base_type.to_string()), p_subscript->base);
5043
break;
5044
// Return int.
5045
case Variant::PACKED_BYTE_ARRAY:
5046
case Variant::PACKED_INT32_ARRAY:
5047
case Variant::PACKED_INT64_ARRAY:
5048
case Variant::VECTOR2I:
5049
case Variant::VECTOR3I:
5050
case Variant::VECTOR4I:
5051
result_type.builtin_type = Variant::INT;
5052
break;
5053
// Return float.
5054
case Variant::PACKED_FLOAT32_ARRAY:
5055
case Variant::PACKED_FLOAT64_ARRAY:
5056
case Variant::VECTOR2:
5057
case Variant::VECTOR3:
5058
case Variant::VECTOR4:
5059
case Variant::QUATERNION:
5060
result_type.builtin_type = Variant::FLOAT;
5061
break;
5062
// Return String.
5063
case Variant::PACKED_STRING_ARRAY:
5064
case Variant::STRING:
5065
result_type.builtin_type = Variant::STRING;
5066
break;
5067
// Return Vector2.
5068
case Variant::PACKED_VECTOR2_ARRAY:
5069
case Variant::TRANSFORM2D:
5070
case Variant::RECT2:
5071
result_type.builtin_type = Variant::VECTOR2;
5072
break;
5073
// Return Vector2I.
5074
case Variant::RECT2I:
5075
result_type.builtin_type = Variant::VECTOR2I;
5076
break;
5077
// Return Vector3.
5078
case Variant::PACKED_VECTOR3_ARRAY:
5079
case Variant::AABB:
5080
case Variant::BASIS:
5081
result_type.builtin_type = Variant::VECTOR3;
5082
break;
5083
// Return Color.
5084
case Variant::PACKED_COLOR_ARRAY:
5085
result_type.builtin_type = Variant::COLOR;
5086
break;
5087
// Return Vector4.
5088
case Variant::PACKED_VECTOR4_ARRAY:
5089
result_type.builtin_type = Variant::VECTOR4;
5090
break;
5091
// Depends on the index.
5092
case Variant::TRANSFORM3D:
5093
case Variant::PROJECTION:
5094
case Variant::PLANE:
5095
case Variant::COLOR:
5096
case Variant::OBJECT:
5097
result_type.kind = GDScriptParser::DataType::VARIANT;
5098
result_type.type_source = GDScriptParser::DataType::UNDETECTED;
5099
break;
5100
// Can have an element type.
5101
case Variant::ARRAY:
5102
if (base_type.has_container_element_type(0)) {
5103
result_type = base_type.get_container_element_type(0);
5104
result_type.type_source = base_type.type_source;
5105
} else {
5106
result_type.kind = GDScriptParser::DataType::VARIANT;
5107
result_type.type_source = GDScriptParser::DataType::UNDETECTED;
5108
}
5109
break;
5110
// Can have two element types, but we only care about the value.
5111
case Variant::DICTIONARY:
5112
if (base_type.has_container_element_type(1)) {
5113
result_type = base_type.get_container_element_type(1);
5114
result_type.type_source = base_type.type_source;
5115
} else {
5116
result_type.kind = GDScriptParser::DataType::VARIANT;
5117
result_type.type_source = GDScriptParser::DataType::UNDETECTED;
5118
}
5119
break;
5120
// Here for completeness.
5121
case Variant::VARIANT_MAX:
5122
break;
5123
}
5124
}
5125
}
5126
}
5127
5128
p_subscript->set_datatype(result_type);
5129
}
5130
5131
void GDScriptAnalyzer::reduce_ternary_op(GDScriptParser::TernaryOpNode *p_ternary_op, bool p_is_root) {
5132
reduce_expression(p_ternary_op->condition);
5133
reduce_expression(p_ternary_op->true_expr, p_is_root);
5134
reduce_expression(p_ternary_op->false_expr, p_is_root);
5135
5136
GDScriptParser::DataType result;
5137
5138
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) {
5139
p_ternary_op->is_constant = true;
5140
if (p_ternary_op->condition->reduced_value.booleanize()) {
5141
p_ternary_op->reduced_value = p_ternary_op->true_expr->reduced_value;
5142
} else {
5143
p_ternary_op->reduced_value = p_ternary_op->false_expr->reduced_value;
5144
}
5145
}
5146
5147
GDScriptParser::DataType true_type;
5148
if (p_ternary_op->true_expr) {
5149
true_type = p_ternary_op->true_expr->get_datatype();
5150
} else {
5151
true_type.kind = GDScriptParser::DataType::VARIANT;
5152
}
5153
GDScriptParser::DataType false_type;
5154
if (p_ternary_op->false_expr) {
5155
false_type = p_ternary_op->false_expr->get_datatype();
5156
} else {
5157
false_type.kind = GDScriptParser::DataType::VARIANT;
5158
}
5159
5160
if (true_type.is_variant() || false_type.is_variant()) {
5161
result.kind = GDScriptParser::DataType::VARIANT;
5162
} else {
5163
result = true_type;
5164
if (!is_type_compatible(true_type, false_type)) {
5165
result = false_type;
5166
if (!is_type_compatible(false_type, true_type)) {
5167
result.kind = GDScriptParser::DataType::VARIANT;
5168
#ifdef DEBUG_ENABLED
5169
parser->push_warning(p_ternary_op, GDScriptWarning::INCOMPATIBLE_TERNARY);
5170
#endif // DEBUG_ENABLED
5171
}
5172
}
5173
}
5174
result.type_source = true_type.is_hard_type() && false_type.is_hard_type() ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
5175
5176
p_ternary_op->set_datatype(result);
5177
}
5178
5179
void GDScriptAnalyzer::reduce_type_test(GDScriptParser::TypeTestNode *p_type_test) {
5180
GDScriptParser::DataType result;
5181
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
5182
result.kind = GDScriptParser::DataType::BUILTIN;
5183
result.builtin_type = Variant::BOOL;
5184
p_type_test->set_datatype(result);
5185
5186
if (!p_type_test->operand || !p_type_test->test_type) {
5187
return;
5188
}
5189
5190
reduce_expression(p_type_test->operand);
5191
GDScriptParser::DataType operand_type = p_type_test->operand->get_datatype();
5192
GDScriptParser::DataType test_type = type_from_metatype(resolve_datatype(p_type_test->test_type));
5193
p_type_test->test_datatype = test_type;
5194
5195
if (!operand_type.is_set() || !test_type.is_set()) {
5196
return;
5197
}
5198
5199
if (p_type_test->operand->is_constant) {
5200
p_type_test->is_constant = true;
5201
p_type_test->reduced_value = false;
5202
5203
if (!is_type_compatible(test_type, operand_type)) {
5204
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);
5205
} else if (is_type_compatible(test_type, type_from_variant(p_type_test->operand->reduced_value, p_type_test->operand))) {
5206
p_type_test->reduced_value = test_type.builtin_type != Variant::OBJECT || !p_type_test->operand->reduced_value.is_null();
5207
}
5208
5209
return;
5210
}
5211
5212
if (!is_type_compatible(test_type, operand_type) && !is_type_compatible(operand_type, test_type)) {
5213
if (operand_type.is_hard_type()) {
5214
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);
5215
} else {
5216
downgrade_node_type_source(p_type_test->operand);
5217
}
5218
}
5219
}
5220
5221
void GDScriptAnalyzer::reduce_unary_op(GDScriptParser::UnaryOpNode *p_unary_op) {
5222
reduce_expression(p_unary_op->operand);
5223
5224
GDScriptParser::DataType result;
5225
5226
if (p_unary_op->operand == nullptr) {
5227
result.kind = GDScriptParser::DataType::VARIANT;
5228
p_unary_op->set_datatype(result);
5229
return;
5230
}
5231
5232
GDScriptParser::DataType operand_type = p_unary_op->operand->get_datatype();
5233
5234
if (p_unary_op->operand->is_constant) {
5235
p_unary_op->is_constant = true;
5236
p_unary_op->reduced_value = Variant::evaluate(p_unary_op->variant_op, p_unary_op->operand->reduced_value, Variant());
5237
result = type_from_variant(p_unary_op->reduced_value, p_unary_op);
5238
}
5239
5240
if (operand_type.is_variant()) {
5241
result.kind = GDScriptParser::DataType::VARIANT;
5242
mark_node_unsafe(p_unary_op);
5243
} else {
5244
bool valid = false;
5245
result = get_operation_type(p_unary_op->variant_op, operand_type, valid, p_unary_op);
5246
5247
if (!valid) {
5248
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);
5249
}
5250
}
5251
5252
p_unary_op->set_datatype(result);
5253
}
5254
5255
Variant GDScriptAnalyzer::make_expression_reduced_value(GDScriptParser::ExpressionNode *p_expression, bool &is_reduced) {
5256
if (p_expression == nullptr) {
5257
return Variant();
5258
}
5259
5260
if (p_expression->is_constant) {
5261
is_reduced = true;
5262
return p_expression->reduced_value;
5263
}
5264
5265
switch (p_expression->type) {
5266
case GDScriptParser::Node::ARRAY:
5267
return make_array_reduced_value(static_cast<GDScriptParser::ArrayNode *>(p_expression), is_reduced);
5268
case GDScriptParser::Node::DICTIONARY:
5269
return make_dictionary_reduced_value(static_cast<GDScriptParser::DictionaryNode *>(p_expression), is_reduced);
5270
case GDScriptParser::Node::SUBSCRIPT:
5271
return make_subscript_reduced_value(static_cast<GDScriptParser::SubscriptNode *>(p_expression), is_reduced);
5272
case GDScriptParser::Node::CALL:
5273
return make_call_reduced_value(static_cast<GDScriptParser::CallNode *>(p_expression), is_reduced);
5274
default:
5275
break;
5276
}
5277
5278
return Variant();
5279
}
5280
5281
Variant GDScriptAnalyzer::make_array_reduced_value(GDScriptParser::ArrayNode *p_array, bool &is_reduced) {
5282
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();
5283
5284
array.resize(p_array->elements.size());
5285
for (int i = 0; i < p_array->elements.size(); i++) {
5286
GDScriptParser::ExpressionNode *element = p_array->elements[i];
5287
5288
bool is_element_value_reduced = false;
5289
Variant element_value = make_expression_reduced_value(element, is_element_value_reduced);
5290
if (!is_element_value_reduced) {
5291
return Variant();
5292
}
5293
5294
array[i] = element_value;
5295
}
5296
5297
array.make_read_only();
5298
5299
is_reduced = true;
5300
return array;
5301
}
5302
5303
Variant GDScriptAnalyzer::make_dictionary_reduced_value(GDScriptParser::DictionaryNode *p_dictionary, bool &is_reduced) {
5304
Dictionary dictionary = p_dictionary->get_datatype().has_container_element_types()
5305
? 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))
5306
: Dictionary();
5307
5308
for (int i = 0; i < p_dictionary->elements.size(); i++) {
5309
const GDScriptParser::DictionaryNode::Pair &element = p_dictionary->elements[i];
5310
5311
bool is_element_key_reduced = false;
5312
Variant element_key = make_expression_reduced_value(element.key, is_element_key_reduced);
5313
if (!is_element_key_reduced) {
5314
return Variant();
5315
}
5316
5317
bool is_element_value_reduced = false;
5318
Variant element_value = make_expression_reduced_value(element.value, is_element_value_reduced);
5319
if (!is_element_value_reduced) {
5320
return Variant();
5321
}
5322
5323
dictionary[element_key] = element_value;
5324
}
5325
5326
dictionary.make_read_only();
5327
5328
is_reduced = true;
5329
return dictionary;
5330
}
5331
5332
Variant GDScriptAnalyzer::make_subscript_reduced_value(GDScriptParser::SubscriptNode *p_subscript, bool &is_reduced) {
5333
if (p_subscript->base == nullptr || p_subscript->index == nullptr) {
5334
return Variant();
5335
}
5336
5337
bool is_base_value_reduced = false;
5338
Variant base_value = make_expression_reduced_value(p_subscript->base, is_base_value_reduced);
5339
if (!is_base_value_reduced) {
5340
return Variant();
5341
}
5342
5343
if (p_subscript->is_attribute) {
5344
bool is_valid = false;
5345
Variant value = base_value.get_named(p_subscript->attribute->name, is_valid);
5346
if (is_valid) {
5347
is_reduced = true;
5348
return value;
5349
} else {
5350
return Variant();
5351
}
5352
} else {
5353
bool is_index_value_reduced = false;
5354
Variant index_value = make_expression_reduced_value(p_subscript->index, is_index_value_reduced);
5355
if (!is_index_value_reduced) {
5356
return Variant();
5357
}
5358
5359
bool is_valid = false;
5360
Variant value = base_value.get(index_value, &is_valid);
5361
if (is_valid) {
5362
is_reduced = true;
5363
return value;
5364
} else {
5365
return Variant();
5366
}
5367
}
5368
}
5369
5370
Variant GDScriptAnalyzer::make_call_reduced_value(GDScriptParser::CallNode *p_call, bool &is_reduced) {
5371
if (p_call->get_callee_type() == GDScriptParser::Node::IDENTIFIER) {
5372
Variant::Type type = Variant::NIL;
5373
if (p_call->function_name == SNAME("Array")) {
5374
type = Variant::ARRAY;
5375
} else if (p_call->function_name == SNAME("Dictionary")) {
5376
type = Variant::DICTIONARY;
5377
} else {
5378
return Variant();
5379
}
5380
5381
Vector<Variant> args;
5382
args.resize(p_call->arguments.size());
5383
const Variant **argptrs = (const Variant **)alloca(sizeof(const Variant *) * args.size());
5384
for (int i = 0; i < p_call->arguments.size(); i++) {
5385
bool is_arg_value_reduced = false;
5386
Variant arg_value = make_expression_reduced_value(p_call->arguments[i], is_arg_value_reduced);
5387
if (!is_arg_value_reduced) {
5388
return Variant();
5389
}
5390
args.write[i] = arg_value;
5391
argptrs[i] = &args[i];
5392
}
5393
5394
Variant result;
5395
Callable::CallError ce;
5396
Variant::construct(type, result, argptrs, args.size(), ce);
5397
if (ce.error) {
5398
push_error(vformat(R"(Failed to construct "%s".)", Variant::get_type_name(type)), p_call);
5399
return Variant();
5400
}
5401
5402
if (type == Variant::ARRAY) {
5403
Array array = result;
5404
array.make_read_only();
5405
} else if (type == Variant::DICTIONARY) {
5406
Dictionary dictionary = result;
5407
dictionary.make_read_only();
5408
}
5409
5410
is_reduced = true;
5411
return result;
5412
}
5413
5414
return Variant();
5415
}
5416
5417
Array GDScriptAnalyzer::make_array_from_element_datatype(const GDScriptParser::DataType &p_element_datatype, const GDScriptParser::Node *p_source_node) {
5418
Array array;
5419
5420
if (p_element_datatype.builtin_type == Variant::OBJECT) {
5421
Ref<Script> script_type = p_element_datatype.script_type;
5422
if (p_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) {
5423
Error err = OK;
5424
Ref<GDScript> scr = get_depended_shallow_script(p_element_datatype.script_path, err);
5425
if (err) {
5426
push_error(vformat(R"(Error while getting cache for script "%s".)", p_element_datatype.script_path), p_source_node);
5427
return array;
5428
}
5429
script_type.reference_ptr(scr->find_class(p_element_datatype.class_type->fqcn));
5430
}
5431
5432
array.set_typed(p_element_datatype.builtin_type, p_element_datatype.native_type, script_type);
5433
} else {
5434
array.set_typed(p_element_datatype.builtin_type, StringName(), Variant());
5435
}
5436
5437
return array;
5438
}
5439
5440
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) {
5441
Dictionary dictionary;
5442
StringName key_name;
5443
Variant key_script;
5444
StringName value_name;
5445
Variant value_script;
5446
5447
if (p_key_element_datatype.builtin_type == Variant::OBJECT) {
5448
Ref<Script> script_type = p_key_element_datatype.script_type;
5449
if (p_key_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) {
5450
Error err = OK;
5451
Ref<GDScript> scr = get_depended_shallow_script(p_key_element_datatype.script_path, err);
5452
if (err) {
5453
push_error(vformat(R"(Error while getting cache for script "%s".)", p_key_element_datatype.script_path), p_source_node);
5454
return dictionary;
5455
}
5456
script_type.reference_ptr(scr->find_class(p_key_element_datatype.class_type->fqcn));
5457
}
5458
5459
key_name = p_key_element_datatype.native_type;
5460
key_script = script_type;
5461
}
5462
5463
if (p_value_element_datatype.builtin_type == Variant::OBJECT) {
5464
Ref<Script> script_type = p_value_element_datatype.script_type;
5465
if (p_value_element_datatype.kind == GDScriptParser::DataType::CLASS && script_type.is_null()) {
5466
Error err = OK;
5467
Ref<GDScript> scr = get_depended_shallow_script(p_value_element_datatype.script_path, err);
5468
if (err) {
5469
push_error(vformat(R"(Error while getting cache for script "%s".)", p_value_element_datatype.script_path), p_source_node);
5470
return dictionary;
5471
}
5472
script_type.reference_ptr(scr->find_class(p_value_element_datatype.class_type->fqcn));
5473
}
5474
5475
value_name = p_value_element_datatype.native_type;
5476
value_script = script_type;
5477
}
5478
5479
dictionary.set_typed(p_key_element_datatype.builtin_type, key_name, key_script, p_value_element_datatype.builtin_type, value_name, value_script);
5480
return dictionary;
5481
}
5482
5483
Variant GDScriptAnalyzer::make_variable_default_value(GDScriptParser::VariableNode *p_variable) {
5484
Variant result = Variant();
5485
5486
if (p_variable->initializer) {
5487
bool is_initializer_value_reduced = false;
5488
Variant initializer_value = make_expression_reduced_value(p_variable->initializer, is_initializer_value_reduced);
5489
if (is_initializer_value_reduced) {
5490
result = initializer_value;
5491
}
5492
} else {
5493
GDScriptParser::DataType datatype = p_variable->get_datatype();
5494
if (datatype.is_hard_type()) {
5495
if (datatype.kind == GDScriptParser::DataType::BUILTIN && datatype.builtin_type != Variant::OBJECT) {
5496
if (datatype.builtin_type == Variant::ARRAY && datatype.has_container_element_type(0)) {
5497
result = make_array_from_element_datatype(datatype.get_container_element_type(0));
5498
} else if (datatype.builtin_type == Variant::DICTIONARY && datatype.has_container_element_types()) {
5499
GDScriptParser::DataType key = datatype.get_container_element_type_or_variant(0);
5500
GDScriptParser::DataType value = datatype.get_container_element_type_or_variant(1);
5501
result = make_dictionary_from_element_datatype(key, value);
5502
} else {
5503
VariantInternal::initialize(&result, datatype.builtin_type);
5504
}
5505
} else if (datatype.kind == GDScriptParser::DataType::ENUM) {
5506
result = 0;
5507
}
5508
}
5509
}
5510
5511
return result;
5512
}
5513
5514
GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_value, const GDScriptParser::Node *p_source) {
5515
GDScriptParser::DataType result;
5516
result.is_constant = true;
5517
result.kind = GDScriptParser::DataType::BUILTIN;
5518
result.builtin_type = p_value.get_type();
5519
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT; // Constant has explicit type.
5520
5521
if (p_value.get_type() == Variant::ARRAY) {
5522
const Array &array = p_value;
5523
if (array.get_typed_script()) {
5524
result.set_container_element_type(0, type_from_metatype(make_script_meta_type(array.get_typed_script())));
5525
} else if (array.get_typed_class_name()) {
5526
result.set_container_element_type(0, type_from_metatype(make_native_meta_type(array.get_typed_class_name())));
5527
} else if (array.get_typed_builtin() != Variant::NIL) {
5528
result.set_container_element_type(0, type_from_metatype(make_builtin_meta_type((Variant::Type)array.get_typed_builtin())));
5529
}
5530
} else if (p_value.get_type() == Variant::DICTIONARY) {
5531
const Dictionary &dict = p_value;
5532
if (dict.get_typed_key_script()) {
5533
result.set_container_element_type(0, type_from_metatype(make_script_meta_type(dict.get_typed_key_script())));
5534
} else if (dict.get_typed_key_class_name()) {
5535
result.set_container_element_type(0, type_from_metatype(make_native_meta_type(dict.get_typed_key_class_name())));
5536
} else if (dict.get_typed_key_builtin() != Variant::NIL) {
5537
result.set_container_element_type(0, type_from_metatype(make_builtin_meta_type((Variant::Type)dict.get_typed_key_builtin())));
5538
}
5539
if (dict.get_typed_value_script()) {
5540
result.set_container_element_type(1, type_from_metatype(make_script_meta_type(dict.get_typed_value_script())));
5541
} else if (dict.get_typed_value_class_name()) {
5542
result.set_container_element_type(1, type_from_metatype(make_native_meta_type(dict.get_typed_value_class_name())));
5543
} else if (dict.get_typed_value_builtin() != Variant::NIL) {
5544
result.set_container_element_type(1, type_from_metatype(make_builtin_meta_type((Variant::Type)dict.get_typed_value_builtin())));
5545
}
5546
} else if (p_value.get_type() == Variant::OBJECT) {
5547
// Object is treated as a native type, not a builtin type.
5548
result.kind = GDScriptParser::DataType::NATIVE;
5549
5550
Object *obj = p_value;
5551
if (!obj) {
5552
return GDScriptParser::DataType();
5553
}
5554
result.native_type = obj->get_class_name();
5555
5556
Ref<Script> scr = p_value; // Check if value is a script itself.
5557
if (scr.is_valid()) {
5558
result.is_meta_type = true;
5559
} else {
5560
result.is_meta_type = false;
5561
scr = obj->get_script();
5562
}
5563
if (scr.is_valid()) {
5564
Ref<GDScript> gds = scr;
5565
if (gds.is_valid()) {
5566
// This might be an inner class, so we want to get the parser for the root.
5567
// But still get the inner class from that tree.
5568
String script_path = gds->get_script_path();
5569
Ref<GDScriptParserRef> ref = parser->get_depended_parser_for(script_path);
5570
if (ref.is_null()) {
5571
push_error(vformat(R"(Could not find script "%s".)", script_path), p_source);
5572
GDScriptParser::DataType error_type;
5573
error_type.kind = GDScriptParser::DataType::VARIANT;
5574
return error_type;
5575
}
5576
Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
5577
GDScriptParser::ClassNode *found = nullptr;
5578
if (err == OK) {
5579
found = ref->get_parser()->find_class(gds->fully_qualified_name);
5580
if (found != nullptr) {
5581
err = resolve_class_inheritance(found, p_source);
5582
}
5583
}
5584
if (err || found == nullptr) {
5585
push_error(vformat(R"(Could not resolve script "%s".)", script_path), p_source);
5586
GDScriptParser::DataType error_type;
5587
error_type.kind = GDScriptParser::DataType::VARIANT;
5588
return error_type;
5589
}
5590
5591
result.kind = GDScriptParser::DataType::CLASS;
5592
result.native_type = found->get_datatype().native_type;
5593
result.class_type = found;
5594
result.script_path = ref->get_parser()->script_path;
5595
} else {
5596
result.kind = GDScriptParser::DataType::SCRIPT;
5597
result.native_type = scr->get_instance_base_type();
5598
result.script_path = scr->get_path();
5599
}
5600
result.script_type = scr;
5601
} else {
5602
result.kind = GDScriptParser::DataType::NATIVE;
5603
if (result.native_type == GDScriptNativeClass::get_class_static()) {
5604
result.is_meta_type = true;
5605
}
5606
}
5607
}
5608
5609
return result;
5610
}
5611
5612
GDScriptParser::DataType GDScriptAnalyzer::type_from_metatype(const GDScriptParser::DataType &p_meta_type) {
5613
GDScriptParser::DataType result = p_meta_type;
5614
result.is_meta_type = false;
5615
result.is_pseudo_type = false;
5616
if (p_meta_type.kind == GDScriptParser::DataType::ENUM) {
5617
result.builtin_type = Variant::INT;
5618
} else {
5619
result.is_constant = false;
5620
}
5621
return result;
5622
}
5623
5624
GDScriptParser::DataType GDScriptAnalyzer::type_from_property(const PropertyInfo &p_property, bool p_is_arg, bool p_is_readonly) const {
5625
GDScriptParser::DataType result;
5626
result.is_read_only = p_is_readonly;
5627
result.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
5628
if (p_property.type == Variant::NIL && (p_is_arg || (p_property.usage & PROPERTY_USAGE_NIL_IS_VARIANT))) {
5629
// Variant
5630
result.kind = GDScriptParser::DataType::VARIANT;
5631
return result;
5632
}
5633
result.builtin_type = p_property.type;
5634
if (p_property.type == Variant::OBJECT) {
5635
if (ScriptServer::is_global_class(p_property.class_name)) {
5636
result.kind = GDScriptParser::DataType::SCRIPT;
5637
result.script_path = ScriptServer::get_global_class_path(p_property.class_name);
5638
result.native_type = ScriptServer::get_global_class_native_base(p_property.class_name);
5639
5640
Ref<Script> scr = ResourceLoader::load(ScriptServer::get_global_class_path(p_property.class_name));
5641
if (scr.is_valid()) {
5642
result.script_type = scr;
5643
}
5644
} else {
5645
result.kind = GDScriptParser::DataType::NATIVE;
5646
result.native_type = p_property.class_name == StringName() ? "Object" : p_property.class_name;
5647
}
5648
} else {
5649
result.kind = GDScriptParser::DataType::BUILTIN;
5650
result.builtin_type = p_property.type;
5651
if (p_property.type == Variant::ARRAY && p_property.hint == PROPERTY_HINT_ARRAY_TYPE) {
5652
// Check element type.
5653
StringName elem_type_name = p_property.hint_string;
5654
GDScriptParser::DataType elem_type;
5655
elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
5656
5657
Variant::Type elem_builtin_type = GDScriptParser::get_builtin_type(elem_type_name);
5658
if (elem_builtin_type < Variant::VARIANT_MAX) {
5659
// Builtin type.
5660
elem_type.kind = GDScriptParser::DataType::BUILTIN;
5661
elem_type.builtin_type = elem_builtin_type;
5662
} else if (class_exists(elem_type_name)) {
5663
elem_type.kind = GDScriptParser::DataType::NATIVE;
5664
elem_type.builtin_type = Variant::OBJECT;
5665
elem_type.native_type = elem_type_name;
5666
} else if (ScriptServer::is_global_class(elem_type_name)) {
5667
// Just load this as it shouldn't be a GDScript.
5668
Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(elem_type_name));
5669
elem_type.kind = GDScriptParser::DataType::SCRIPT;
5670
elem_type.builtin_type = Variant::OBJECT;
5671
elem_type.native_type = script->get_instance_base_type();
5672
elem_type.script_type = script;
5673
} else {
5674
ERR_FAIL_V_MSG(result, "Could not find element type from property hint of a typed array.");
5675
}
5676
elem_type.is_constant = false;
5677
result.set_container_element_type(0, elem_type);
5678
} else if (p_property.type == Variant::DICTIONARY && p_property.hint == PROPERTY_HINT_DICTIONARY_TYPE) {
5679
// Check element type.
5680
StringName key_elem_type_name = p_property.hint_string.get_slicec(';', 0);
5681
GDScriptParser::DataType key_elem_type;
5682
key_elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
5683
5684
Variant::Type key_elem_builtin_type = GDScriptParser::get_builtin_type(key_elem_type_name);
5685
if (key_elem_builtin_type < Variant::VARIANT_MAX) {
5686
// Builtin type.
5687
key_elem_type.kind = GDScriptParser::DataType::BUILTIN;
5688
key_elem_type.builtin_type = key_elem_builtin_type;
5689
} else if (class_exists(key_elem_type_name)) {
5690
key_elem_type.kind = GDScriptParser::DataType::NATIVE;
5691
key_elem_type.builtin_type = Variant::OBJECT;
5692
key_elem_type.native_type = key_elem_type_name;
5693
} else if (ScriptServer::is_global_class(key_elem_type_name)) {
5694
// Just load this as it shouldn't be a GDScript.
5695
Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(key_elem_type_name));
5696
key_elem_type.kind = GDScriptParser::DataType::SCRIPT;
5697
key_elem_type.builtin_type = Variant::OBJECT;
5698
key_elem_type.native_type = script->get_instance_base_type();
5699
key_elem_type.script_type = script;
5700
} else {
5701
ERR_FAIL_V_MSG(result, "Could not find element type from property hint of a typed dictionary.");
5702
}
5703
key_elem_type.is_constant = false;
5704
5705
StringName value_elem_type_name = p_property.hint_string.get_slicec(';', 1);
5706
GDScriptParser::DataType value_elem_type;
5707
value_elem_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
5708
5709
Variant::Type value_elem_builtin_type = GDScriptParser::get_builtin_type(value_elem_type_name);
5710
if (value_elem_builtin_type < Variant::VARIANT_MAX) {
5711
// Builtin type.
5712
value_elem_type.kind = GDScriptParser::DataType::BUILTIN;
5713
value_elem_type.builtin_type = value_elem_builtin_type;
5714
} else if (class_exists(value_elem_type_name)) {
5715
value_elem_type.kind = GDScriptParser::DataType::NATIVE;
5716
value_elem_type.builtin_type = Variant::OBJECT;
5717
value_elem_type.native_type = value_elem_type_name;
5718
} else if (ScriptServer::is_global_class(value_elem_type_name)) {
5719
// Just load this as it shouldn't be a GDScript.
5720
Ref<Script> script = ResourceLoader::load(ScriptServer::get_global_class_path(value_elem_type_name));
5721
value_elem_type.kind = GDScriptParser::DataType::SCRIPT;
5722
value_elem_type.builtin_type = Variant::OBJECT;
5723
value_elem_type.native_type = script->get_instance_base_type();
5724
value_elem_type.script_type = script;
5725
} else {
5726
ERR_FAIL_V_MSG(result, "Could not find element type from property hint of a typed dictionary.");
5727
}
5728
value_elem_type.is_constant = false;
5729
5730
result.set_container_element_type(0, key_elem_type);
5731
result.set_container_element_type(1, value_elem_type);
5732
} else if (p_property.type == Variant::INT) {
5733
// Check if it's enum.
5734
if ((p_property.usage & PROPERTY_USAGE_CLASS_IS_ENUM) && p_property.class_name != StringName()) {
5735
if (CoreConstants::is_global_enum(p_property.class_name)) {
5736
result = make_global_enum_type(p_property.class_name, StringName(), false);
5737
result.is_constant = false;
5738
} else {
5739
Vector<String> names = String(p_property.class_name).split(ENUM_SEPARATOR);
5740
if (names.size() == 2) {
5741
result = make_enum_type(names[1], names[0], false);
5742
result.is_constant = false;
5743
}
5744
}
5745
}
5746
// PROPERTY_USAGE_CLASS_IS_BITFIELD: BitField[T] isn't supported (yet?), use plain int.
5747
}
5748
}
5749
return result;
5750
}
5751
5752
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) {
5753
r_method_flags = METHOD_FLAGS_DEFAULT;
5754
r_default_arg_count = 0;
5755
if (r_native_class) {
5756
*r_native_class = StringName();
5757
}
5758
StringName function_name = p_function;
5759
5760
bool was_enum = false;
5761
if (p_base_type.kind == GDScriptParser::DataType::ENUM) {
5762
was_enum = true;
5763
if (p_base_type.is_meta_type) {
5764
// Enum type can be treated as a dictionary value.
5765
p_base_type.kind = GDScriptParser::DataType::BUILTIN;
5766
p_base_type.is_meta_type = false;
5767
} else {
5768
push_error("Cannot call function on enum value.", p_source);
5769
return false;
5770
}
5771
}
5772
5773
if (p_base_type.kind == GDScriptParser::DataType::BUILTIN) {
5774
// Construct a base type to get methods.
5775
Callable::CallError err;
5776
Variant dummy;
5777
Variant::construct(p_base_type.builtin_type, dummy, nullptr, 0, err);
5778
if (err.error != Callable::CallError::CALL_OK) {
5779
ERR_FAIL_V_MSG(false, "Could not construct base Variant type.");
5780
}
5781
List<MethodInfo> methods;
5782
dummy.get_method_list(&methods);
5783
5784
for (const MethodInfo &E : methods) {
5785
if (E.name == p_function) {
5786
function_signature_from_info(E, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
5787
// Cannot use non-const methods on enums.
5788
if (!r_method_flags.has_flag(METHOD_FLAG_STATIC) && was_enum && !(E.flags & METHOD_FLAG_CONST)) {
5789
push_error(vformat(R"*(Cannot call non-const Dictionary function "%s()" on enum "%s".)*", p_function, p_base_type.enum_type), p_source);
5790
}
5791
return true;
5792
}
5793
}
5794
5795
return false;
5796
}
5797
5798
StringName base_native = p_base_type.native_type;
5799
if (base_native != StringName()) {
5800
// Empty native class might happen in some Script implementations.
5801
// Just ignore it.
5802
if (!class_exists(base_native)) {
5803
push_error(vformat("Native class %s used in script doesn't exist or isn't exposed.", base_native), p_source);
5804
return false;
5805
} else if (p_is_constructor && ClassDB::is_abstract(base_native)) {
5806
if (p_base_type.kind == GDScriptParser::DataType::CLASS) {
5807
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);
5808
} else if (p_base_type.kind == GDScriptParser::DataType::SCRIPT) {
5809
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);
5810
} else {
5811
push_error(vformat(R"(Native class "%s" cannot be constructed as it is abstract.)", base_native), p_source);
5812
}
5813
return false;
5814
}
5815
}
5816
5817
if (p_is_constructor) {
5818
function_name = GDScriptLanguage::get_singleton()->strings._init;
5819
r_method_flags.set_flag(METHOD_FLAG_STATIC);
5820
}
5821
5822
GDScriptParser::ClassNode *base_class = p_base_type.class_type;
5823
GDScriptParser::FunctionNode *found_function = nullptr;
5824
5825
while (found_function == nullptr && base_class != nullptr) {
5826
if (base_class->has_member(function_name)) {
5827
if (base_class->get_member(function_name).type != GDScriptParser::ClassNode::Member::FUNCTION) {
5828
// TODO: If this is Callable it can have a better error message.
5829
push_error(vformat(R"(Member "%s" is not a function.)", function_name), p_source);
5830
return false;
5831
}
5832
5833
resolve_class_member(base_class, function_name, p_source);
5834
found_function = base_class->get_member(function_name).function;
5835
}
5836
5837
resolve_class_inheritance(base_class, p_source);
5838
base_class = base_class->base_type.class_type;
5839
}
5840
5841
if (found_function != nullptr) {
5842
if (found_function->is_abstract) {
5843
r_method_flags.set_flag(METHOD_FLAG_VIRTUAL_REQUIRED);
5844
}
5845
if (p_is_constructor || found_function->is_static) {
5846
r_method_flags.set_flag(METHOD_FLAG_STATIC);
5847
}
5848
for (int i = 0; i < found_function->parameters.size(); i++) {
5849
r_par_types.push_back(found_function->parameters[i]->get_datatype());
5850
if (found_function->parameters[i]->initializer != nullptr) {
5851
r_default_arg_count++;
5852
}
5853
}
5854
if (found_function->is_vararg()) {
5855
r_method_flags.set_flag(METHOD_FLAG_VARARG);
5856
}
5857
r_return_type = p_is_constructor ? p_base_type : found_function->get_datatype();
5858
r_return_type.is_meta_type = false;
5859
r_return_type.is_coroutine = found_function->is_coroutine;
5860
5861
return true;
5862
}
5863
5864
Ref<Script> base_script = p_base_type.script_type;
5865
5866
while (base_script.is_valid() && base_script->has_method(function_name)) {
5867
MethodInfo info = base_script->get_method_info(function_name);
5868
5869
if (!(info == MethodInfo())) {
5870
return function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
5871
}
5872
base_script = base_script->get_base_script();
5873
}
5874
5875
// If the base is a script, it might be trying to access members of the Script class itself.
5876
if (p_base_type.is_meta_type && !p_is_constructor && (p_base_type.kind == GDScriptParser::DataType::SCRIPT || p_base_type.kind == GDScriptParser::DataType::CLASS)) {
5877
MethodInfo info;
5878
StringName script_class = p_base_type.kind == GDScriptParser::DataType::SCRIPT ? p_base_type.script_type->get_class_name() : StringName(GDScript::get_class_static());
5879
5880
if (ClassDB::get_method_info(script_class, function_name, &info)) {
5881
return function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
5882
}
5883
}
5884
5885
if (p_is_constructor) {
5886
// Native types always have a default constructor.
5887
r_return_type = p_base_type;
5888
r_return_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
5889
r_return_type.is_meta_type = false;
5890
return true;
5891
}
5892
5893
MethodInfo info;
5894
if (ClassDB::get_method_info(base_native, function_name, &info)) {
5895
bool valid = function_signature_from_info(info, r_return_type, r_par_types, r_default_arg_count, r_method_flags);
5896
if (valid && Engine::get_singleton()->has_singleton(base_native)) {
5897
r_method_flags.set_flag(METHOD_FLAG_STATIC);
5898
}
5899
#ifdef DEBUG_ENABLED
5900
MethodBind *native_method = ClassDB::get_method(base_native, function_name);
5901
if (native_method && r_native_class) {
5902
*r_native_class = native_method->get_instance_class();
5903
}
5904
#endif // DEBUG_ENABLED
5905
return valid;
5906
}
5907
5908
return false;
5909
}
5910
5911
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) {
5912
r_return_type = type_from_property(p_info.return_val);
5913
r_default_arg_count = p_info.default_arguments.size();
5914
r_method_flags = p_info.flags;
5915
5916
for (const PropertyInfo &E : p_info.arguments) {
5917
r_par_types.push_back(type_from_property(E, true));
5918
}
5919
return true;
5920
}
5921
5922
void GDScriptAnalyzer::validate_call_arg(const MethodInfo &p_method, const GDScriptParser::CallNode *p_call) {
5923
List<GDScriptParser::DataType> arg_types;
5924
5925
for (const PropertyInfo &E : p_method.arguments) {
5926
arg_types.push_back(type_from_property(E, true));
5927
}
5928
5929
validate_call_arg(arg_types, p_method.default_arguments.size(), (p_method.flags & METHOD_FLAG_VARARG) != 0, p_call);
5930
}
5931
5932
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) {
5933
if (p_call->arguments.size() < p_par_types.size() - p_default_args_count) {
5934
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);
5935
}
5936
if (!p_is_vararg && p_call->arguments.size() > p_par_types.size()) {
5937
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()]);
5938
}
5939
5940
List<GDScriptParser::DataType>::ConstIterator par_itr = p_par_types.begin();
5941
for (int i = 0; i < p_call->arguments.size(); ++par_itr, ++i) {
5942
if (i >= p_par_types.size()) {
5943
// Already on vararg place.
5944
break;
5945
}
5946
GDScriptParser::DataType par_type = *par_itr;
5947
5948
if (par_type.is_hard_type() && p_call->arguments[i]->is_constant) {
5949
update_const_expression_builtin_type(p_call->arguments[i], par_type, "pass");
5950
}
5951
GDScriptParser::DataType arg_type = p_call->arguments[i]->get_datatype();
5952
5953
if (arg_type.is_variant() || !arg_type.is_hard_type()) {
5954
#ifdef DEBUG_ENABLED
5955
// Argument can be anything, so this is unsafe (unless the parameter is a hard variant).
5956
if (!(par_type.is_hard_type() && par_type.is_variant())) {
5957
mark_node_unsafe(p_call->arguments[i]);
5958
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());
5959
}
5960
#endif // DEBUG_ENABLED
5961
} else if (par_type.is_hard_type() && !is_type_compatible(par_type, arg_type, true)) {
5962
if (!is_type_compatible(arg_type, par_type)) {
5963
push_error(vformat(R"*(Invalid argument for "%s()" function: argument %d should be "%s" but is "%s".)*",
5964
p_call->function_name, i + 1, par_type.to_string(), arg_type.to_string()),
5965
p_call->arguments[i]);
5966
#ifdef DEBUG_ENABLED
5967
} else {
5968
// Supertypes are acceptable for dynamic compliance, but it's unsafe.
5969
mark_node_unsafe(p_call);
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
#endif // DEBUG_ENABLED
5972
}
5973
#ifdef DEBUG_ENABLED
5974
} 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) {
5975
parser->push_warning(p_call->arguments[i], GDScriptWarning::NARROWING_CONVERSION, p_call->function_name);
5976
#endif // DEBUG_ENABLED
5977
}
5978
}
5979
}
5980
5981
#ifdef DEBUG_ENABLED
5982
void GDScriptAnalyzer::is_shadowing(GDScriptParser::IdentifierNode *p_identifier, const String &p_context, const bool p_in_local_scope) {
5983
const StringName &name = p_identifier->name;
5984
5985
{
5986
List<MethodInfo> gdscript_funcs;
5987
GDScriptLanguage::get_singleton()->get_public_functions(&gdscript_funcs);
5988
5989
for (MethodInfo &info : gdscript_funcs) {
5990
if (info.name == name) {
5991
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function");
5992
return;
5993
}
5994
}
5995
if (Variant::has_utility_function(name)) {
5996
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in function");
5997
return;
5998
} else if (class_exists(name)) {
5999
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "native class");
6000
return;
6001
} else if (ScriptServer::is_global_class(name)) {
6002
String class_path = ScriptServer::get_global_class_path(name).get_file();
6003
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, vformat(R"(global class defined in "%s")", class_path));
6004
return;
6005
} else if (GDScriptParser::get_builtin_type(name) < Variant::VARIANT_MAX) {
6006
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_GLOBAL_IDENTIFIER, p_context, name, "built-in type");
6007
return;
6008
}
6009
}
6010
6011
const GDScriptParser::DataType current_class_type = parser->current_class->get_datatype();
6012
if (p_in_local_scope) {
6013
GDScriptParser::ClassNode *base_class = current_class_type.class_type;
6014
6015
if (base_class != nullptr) {
6016
if (base_class->has_member(name)) {
6017
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()));
6018
return;
6019
}
6020
base_class = base_class->base_type.class_type;
6021
}
6022
6023
while (base_class != nullptr) {
6024
if (base_class->has_member(name)) {
6025
String base_class_name = base_class->get_global_name();
6026
if (base_class_name.is_empty()) {
6027
base_class_name = base_class->fqcn;
6028
}
6029
6030
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);
6031
return;
6032
}
6033
base_class = base_class->base_type.class_type;
6034
}
6035
}
6036
6037
StringName native_base_class = current_class_type.native_type;
6038
while (native_base_class != StringName()) {
6039
ERR_FAIL_COND_MSG(!class_exists(native_base_class), "Non-existent native base class.");
6040
6041
if (ClassDB::has_method(native_base_class, name, true)) {
6042
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "method", native_base_class);
6043
return;
6044
} else if (ClassDB::has_signal(native_base_class, name, true)) {
6045
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "signal", native_base_class);
6046
return;
6047
} else if (ClassDB::has_property(native_base_class, name, true)) {
6048
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "property", native_base_class);
6049
return;
6050
} else if (ClassDB::has_integer_constant(native_base_class, name, true)) {
6051
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "constant", native_base_class);
6052
return;
6053
} else if (ClassDB::has_enum(native_base_class, name, true)) {
6054
parser->push_warning(p_identifier, GDScriptWarning::SHADOWED_VARIABLE_BASE_CLASS, p_context, p_identifier->name, "enum", native_base_class);
6055
return;
6056
}
6057
native_base_class = ClassDB::get_parent_class(native_base_class);
6058
}
6059
}
6060
#endif // DEBUG_ENABLED
6061
6062
GDScriptParser::DataType GDScriptAnalyzer::get_operation_type(Variant::Operator p_operation, const GDScriptParser::DataType &p_a, bool &r_valid, const GDScriptParser::Node *p_source) {
6063
// Unary version.
6064
GDScriptParser::DataType nil_type;
6065
nil_type.builtin_type = Variant::NIL;
6066
nil_type.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
6067
return get_operation_type(p_operation, p_a, nil_type, r_valid, p_source);
6068
}
6069
6070
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) {
6071
if (p_operation == Variant::OP_AND || p_operation == Variant::OP_OR) {
6072
// Those work for any type of argument and always return a boolean.
6073
// They don't use the Variant operator since they have short-circuit semantics.
6074
r_valid = true;
6075
GDScriptParser::DataType result;
6076
result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
6077
result.kind = GDScriptParser::DataType::BUILTIN;
6078
result.builtin_type = Variant::BOOL;
6079
return result;
6080
}
6081
6082
Variant::Type a_type = p_a.builtin_type;
6083
Variant::Type b_type = p_b.builtin_type;
6084
6085
if (p_a.kind == GDScriptParser::DataType::ENUM) {
6086
if (p_a.is_meta_type) {
6087
a_type = Variant::DICTIONARY;
6088
} else {
6089
a_type = Variant::INT;
6090
}
6091
}
6092
if (p_b.kind == GDScriptParser::DataType::ENUM) {
6093
if (p_b.is_meta_type) {
6094
b_type = Variant::DICTIONARY;
6095
} else {
6096
b_type = Variant::INT;
6097
}
6098
}
6099
6100
GDScriptParser::DataType result;
6101
bool hard_operation = p_a.is_hard_type() && p_b.is_hard_type();
6102
6103
if (p_operation == Variant::OP_ADD && a_type == Variant::ARRAY && b_type == Variant::ARRAY) {
6104
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)) {
6105
r_valid = true;
6106
result = p_a;
6107
result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
6108
return result;
6109
}
6110
}
6111
6112
Variant::ValidatedOperatorEvaluator op_eval = Variant::get_validated_operator_evaluator(p_operation, a_type, b_type);
6113
bool validated = op_eval != nullptr;
6114
6115
if (validated) {
6116
r_valid = true;
6117
result.type_source = hard_operation ? GDScriptParser::DataType::ANNOTATED_INFERRED : GDScriptParser::DataType::INFERRED;
6118
result.kind = GDScriptParser::DataType::BUILTIN;
6119
result.builtin_type = Variant::get_operator_return_type(p_operation, a_type, b_type);
6120
} else {
6121
r_valid = !hard_operation;
6122
result.kind = GDScriptParser::DataType::VARIANT;
6123
}
6124
6125
return result;
6126
}
6127
6128
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) {
6129
#ifdef DEBUG_ENABLED
6130
if (p_source_node) {
6131
if (p_target.kind == GDScriptParser::DataType::ENUM) {
6132
if (p_source.kind == GDScriptParser::DataType::BUILTIN && p_source.builtin_type == Variant::INT) {
6133
parser->push_warning(p_source_node, GDScriptWarning::INT_AS_ENUM_WITHOUT_CAST);
6134
}
6135
}
6136
}
6137
#endif // DEBUG_ENABLED
6138
return check_type_compatibility(p_target, p_source, p_allow_implicit_conversion, p_source_node);
6139
}
6140
6141
// TODO: Add safe/unsafe return variable (for variant cases)
6142
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) {
6143
// These return "true" so it doesn't affect users negatively.
6144
ERR_FAIL_COND_V_MSG(!p_target.is_set(), true, "Parser bug (please report): Trying to check compatibility of unset target type");
6145
ERR_FAIL_COND_V_MSG(!p_source.is_set(), true, "Parser bug (please report): Trying to check compatibility of unset value type");
6146
6147
if (p_target.kind == GDScriptParser::DataType::VARIANT) {
6148
// Variant can receive anything.
6149
return true;
6150
}
6151
6152
if (p_source.kind == GDScriptParser::DataType::VARIANT) {
6153
// TODO: This is acceptable but unsafe. Make sure unsafe line is set.
6154
return true;
6155
}
6156
6157
if (p_target.kind == GDScriptParser::DataType::BUILTIN) {
6158
bool valid = p_source.kind == GDScriptParser::DataType::BUILTIN && p_target.builtin_type == p_source.builtin_type;
6159
if (!valid && p_allow_implicit_conversion) {
6160
valid = Variant::can_convert_strict(p_source.builtin_type, p_target.builtin_type);
6161
}
6162
if (!valid && p_target.builtin_type == Variant::INT && p_source.kind == GDScriptParser::DataType::ENUM && !p_source.is_meta_type) {
6163
// Enum value is also integer.
6164
valid = true;
6165
}
6166
if (valid && p_target.builtin_type == Variant::ARRAY && p_source.builtin_type == Variant::ARRAY) {
6167
// Check the element type.
6168
if (p_target.has_container_element_type(0) && p_source.has_container_element_type(0)) {
6169
valid = p_target.get_container_element_type(0) == p_source.get_container_element_type(0);
6170
}
6171
}
6172
if (valid && p_target.builtin_type == Variant::DICTIONARY && p_source.builtin_type == Variant::DICTIONARY) {
6173
// Check the element types.
6174
if (p_target.has_container_element_type(0) && p_source.has_container_element_type(0)) {
6175
valid = p_target.get_container_element_type(0) == p_source.get_container_element_type(0);
6176
}
6177
if (valid && p_target.has_container_element_type(1) && p_source.has_container_element_type(1)) {
6178
valid = p_target.get_container_element_type(1) == p_source.get_container_element_type(1);
6179
}
6180
}
6181
return valid;
6182
}
6183
6184
if (p_target.kind == GDScriptParser::DataType::ENUM) {
6185
if (p_source.kind == GDScriptParser::DataType::BUILTIN && p_source.builtin_type == Variant::INT) {
6186
return true;
6187
}
6188
if (p_source.kind == GDScriptParser::DataType::ENUM) {
6189
if (p_source.native_type == p_target.native_type) {
6190
return true;
6191
}
6192
}
6193
return false;
6194
}
6195
6196
// From here on the target type is an object, so we have to test polymorphism.
6197
6198
if (p_source.kind == GDScriptParser::DataType::BUILTIN && p_source.builtin_type == Variant::NIL) {
6199
// null is acceptable in object.
6200
return true;
6201
}
6202
6203
StringName src_native;
6204
Ref<Script> src_script;
6205
const GDScriptParser::ClassNode *src_class = nullptr;
6206
6207
switch (p_source.kind) {
6208
case GDScriptParser::DataType::NATIVE:
6209
if (p_target.kind != GDScriptParser::DataType::NATIVE) {
6210
// Non-native class cannot be supertype of native.
6211
return false;
6212
}
6213
if (p_source.is_meta_type) {
6214
src_native = GDScriptNativeClass::get_class_static();
6215
} else {
6216
src_native = p_source.native_type;
6217
}
6218
break;
6219
case GDScriptParser::DataType::SCRIPT:
6220
if (p_target.kind == GDScriptParser::DataType::CLASS) {
6221
// A script type cannot be a subtype of a GDScript class.
6222
return false;
6223
}
6224
if (p_source.script_type.is_null()) {
6225
return false;
6226
}
6227
if (p_source.is_meta_type) {
6228
src_native = p_source.script_type->get_class_name();
6229
} else {
6230
src_script = p_source.script_type;
6231
src_native = src_script->get_instance_base_type();
6232
}
6233
break;
6234
case GDScriptParser::DataType::CLASS:
6235
if (p_source.is_meta_type) {
6236
src_native = GDScript::get_class_static();
6237
} else {
6238
src_class = p_source.class_type;
6239
const GDScriptParser::ClassNode *base = src_class;
6240
while (base->base_type.kind == GDScriptParser::DataType::CLASS) {
6241
base = base->base_type.class_type;
6242
}
6243
src_native = base->base_type.native_type;
6244
src_script = base->base_type.script_type;
6245
}
6246
break;
6247
case GDScriptParser::DataType::VARIANT:
6248
case GDScriptParser::DataType::BUILTIN:
6249
case GDScriptParser::DataType::ENUM:
6250
case GDScriptParser::DataType::RESOLVING:
6251
case GDScriptParser::DataType::UNRESOLVED:
6252
break; // Already solved before.
6253
}
6254
6255
switch (p_target.kind) {
6256
case GDScriptParser::DataType::NATIVE: {
6257
if (p_target.is_meta_type) {
6258
return ClassDB::is_parent_class(src_native, GDScriptNativeClass::get_class_static());
6259
}
6260
return ClassDB::is_parent_class(src_native, p_target.native_type);
6261
}
6262
case GDScriptParser::DataType::SCRIPT:
6263
if (p_target.is_meta_type) {
6264
return ClassDB::is_parent_class(src_native, p_target.script_type->get_class_name());
6265
}
6266
while (src_script.is_valid()) {
6267
if (src_script == p_target.script_type) {
6268
return true;
6269
}
6270
src_script = src_script->get_base_script();
6271
}
6272
return false;
6273
case GDScriptParser::DataType::CLASS:
6274
if (p_target.is_meta_type) {
6275
return ClassDB::is_parent_class(src_native, GDScript::get_class_static());
6276
}
6277
while (src_class != nullptr) {
6278
if (src_class == p_target.class_type || src_class->fqcn == p_target.class_type->fqcn) {
6279
return true;
6280
}
6281
src_class = src_class->base_type.class_type;
6282
}
6283
return false;
6284
case GDScriptParser::DataType::VARIANT:
6285
case GDScriptParser::DataType::BUILTIN:
6286
case GDScriptParser::DataType::ENUM:
6287
case GDScriptParser::DataType::RESOLVING:
6288
case GDScriptParser::DataType::UNRESOLVED:
6289
break; // Already solved before.
6290
}
6291
6292
return false;
6293
}
6294
6295
void GDScriptAnalyzer::push_error(const String &p_message, const GDScriptParser::Node *p_origin) {
6296
mark_node_unsafe(p_origin);
6297
parser->push_error(p_message, p_origin);
6298
}
6299
6300
void GDScriptAnalyzer::mark_node_unsafe(const GDScriptParser::Node *p_node) {
6301
#ifdef DEBUG_ENABLED
6302
if (p_node == nullptr) {
6303
return;
6304
}
6305
6306
for (int i = p_node->start_line; i <= p_node->end_line; i++) {
6307
parser->unsafe_lines.insert(i);
6308
}
6309
#endif // DEBUG_ENABLED
6310
}
6311
6312
void GDScriptAnalyzer::downgrade_node_type_source(GDScriptParser::Node *p_node) {
6313
GDScriptParser::IdentifierNode *identifier = nullptr;
6314
if (p_node->type == GDScriptParser::Node::IDENTIFIER) {
6315
identifier = static_cast<GDScriptParser::IdentifierNode *>(p_node);
6316
} else if (p_node->type == GDScriptParser::Node::SUBSCRIPT) {
6317
GDScriptParser::SubscriptNode *subscript = static_cast<GDScriptParser::SubscriptNode *>(p_node);
6318
if (subscript->is_attribute) {
6319
identifier = subscript->attribute;
6320
}
6321
}
6322
if (identifier == nullptr) {
6323
return;
6324
}
6325
6326
GDScriptParser::Node *source = nullptr;
6327
switch (identifier->source) {
6328
case GDScriptParser::IdentifierNode::MEMBER_VARIABLE: {
6329
source = identifier->variable_source;
6330
} break;
6331
case GDScriptParser::IdentifierNode::FUNCTION_PARAMETER: {
6332
source = identifier->parameter_source;
6333
} break;
6334
case GDScriptParser::IdentifierNode::LOCAL_VARIABLE: {
6335
source = identifier->variable_source;
6336
} break;
6337
case GDScriptParser::IdentifierNode::LOCAL_ITERATOR: {
6338
source = identifier->bind_source;
6339
} break;
6340
default:
6341
break;
6342
}
6343
if (source == nullptr) {
6344
return;
6345
}
6346
6347
GDScriptParser::DataType datatype;
6348
datatype.kind = GDScriptParser::DataType::VARIANT;
6349
source->set_datatype(datatype);
6350
}
6351
6352
void GDScriptAnalyzer::mark_lambda_use_self() {
6353
GDScriptParser::LambdaNode *lambda = current_lambda;
6354
while (lambda != nullptr) {
6355
lambda->use_self = true;
6356
lambda = lambda->parent_lambda;
6357
}
6358
}
6359
6360
void GDScriptAnalyzer::resolve_pending_lambda_bodies() {
6361
if (pending_body_resolution_lambdas.is_empty()) {
6362
return;
6363
}
6364
6365
GDScriptParser::LambdaNode *previous_lambda = current_lambda;
6366
bool previous_static_context = static_context;
6367
6368
List<GDScriptParser::LambdaNode *> lambdas = pending_body_resolution_lambdas;
6369
pending_body_resolution_lambdas.clear();
6370
6371
for (GDScriptParser::LambdaNode *lambda : lambdas) {
6372
current_lambda = lambda;
6373
static_context = lambda->function->is_static;
6374
6375
resolve_function_body(lambda->function, true);
6376
6377
int captures_amount = lambda->captures.size();
6378
if (captures_amount > 0) {
6379
// Create space for lambda parameters.
6380
// At the beginning to not mess with optional parameters.
6381
int param_count = lambda->function->parameters.size();
6382
lambda->function->parameters.resize(param_count + captures_amount);
6383
for (int i = param_count - 1; i >= 0; i--) {
6384
lambda->function->parameters.write[i + captures_amount] = lambda->function->parameters[i];
6385
lambda->function->parameters_indices[lambda->function->parameters[i]->identifier->name] = i + captures_amount;
6386
}
6387
6388
// Add captures as extra parameters at the beginning.
6389
for (int i = 0; i < lambda->captures.size(); i++) {
6390
GDScriptParser::IdentifierNode *capture = lambda->captures[i];
6391
GDScriptParser::ParameterNode *capture_param = parser->alloc_node<GDScriptParser::ParameterNode>();
6392
capture_param->identifier = capture;
6393
capture_param->usages = capture->usages;
6394
capture_param->set_datatype(capture->get_datatype());
6395
6396
lambda->function->parameters.write[i] = capture_param;
6397
lambda->function->parameters_indices[capture->name] = i;
6398
}
6399
}
6400
}
6401
6402
current_lambda = previous_lambda;
6403
static_context = previous_static_context;
6404
}
6405
6406
bool GDScriptAnalyzer::class_exists(const StringName &p_class) const {
6407
return ClassDB::class_exists(p_class) && ClassDB::is_class_exposed(p_class);
6408
}
6409
6410
Error GDScriptAnalyzer::resolve_inheritance() {
6411
return resolve_class_inheritance(parser->head, true);
6412
}
6413
6414
Error GDScriptAnalyzer::resolve_interface() {
6415
resolve_class_interface(parser->head, true);
6416
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
6417
}
6418
6419
Error GDScriptAnalyzer::resolve_body() {
6420
resolve_class_body(parser->head, true);
6421
6422
#ifdef DEBUG_ENABLED
6423
// Apply here, after all `@warning_ignore`s have been resolved and applied.
6424
parser->apply_pending_warnings();
6425
#endif // DEBUG_ENABLED
6426
6427
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
6428
}
6429
6430
Error GDScriptAnalyzer::resolve_dependencies() {
6431
for (KeyValue<String, Ref<GDScriptParserRef>> &K : parser->depended_parsers) {
6432
if (K.value.is_null()) {
6433
return ERR_PARSE_ERROR;
6434
}
6435
K.value->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
6436
}
6437
6438
return parser->errors.is_empty() ? OK : ERR_PARSE_ERROR;
6439
}
6440
6441
Error GDScriptAnalyzer::analyze() {
6442
parser->errors.clear();
6443
6444
Error err = resolve_inheritance();
6445
if (err) {
6446
return err;
6447
}
6448
6449
resolve_interface();
6450
err = resolve_body();
6451
if (err) {
6452
return err;
6453
}
6454
6455
return resolve_dependencies();
6456
}
6457
6458
GDScriptAnalyzer::GDScriptAnalyzer(GDScriptParser *p_parser) {
6459
parser = p_parser;
6460
}
6461
6462