Skip to content

Commit 4e34cf2

Browse files
committed
GDScript: Change parser representation of class extends
1 parent 550a779 commit 4e34cf2

File tree

10 files changed

+43
-26
lines changed

10 files changed

+43
-26
lines changed

modules/gdscript/gdscript.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2483,7 +2483,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
24832483
subclass = nullptr;
24842484
break;
24852485
} else {
2486-
Vector<StringName> extend_classes = subclass->extends;
2486+
Vector<GDScriptParser::IdentifierNode *> extend_classes = subclass->extends;
24872487

24882488
Ref<FileAccess> subfile = FileAccess::open(subclass->extends_path, FileAccess::READ);
24892489
if (subfile.is_null()) {
@@ -2513,7 +2513,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
25132513
}
25142514

25152515
const GDScriptParser::ClassNode *inner_class = subclass->members[i].m_class;
2516-
if (inner_class->identifier->name == extend_classes[0]) {
2516+
if (inner_class->identifier->name == extend_classes[0]->name) {
25172517
extend_classes.remove_at(0);
25182518
found = true;
25192519
subclass = inner_class;
@@ -2527,7 +2527,7 @@ String GDScriptLanguage::get_global_class_name(const String &p_path, String *r_b
25272527
}
25282528
}
25292529
} else if (subclass->extends.size() == 1) {
2530-
*r_base_type = subclass->extends[0];
2530+
*r_base_type = subclass->extends[0]->name;
25312531
subclass = nullptr;
25322532
} else {
25332533
break;

modules/gdscript/gdscript_analyzer.cpp

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -415,7 +415,8 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
415415
push_error("Could not resolve an empty super class path.", p_class);
416416
return ERR_PARSE_ERROR;
417417
}
418-
const StringName &name = p_class->extends[extends_index++];
418+
GDScriptParser::IdentifierNode *id = p_class->extends[extends_index++];
419+
const StringName &name = id->name;
419420
base.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
420421

421422
if (ScriptServer::is_global_class(name)) {
@@ -426,33 +427,33 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
426427
} else {
427428
Ref<GDScriptParserRef> base_parser = get_parser_for(base_path);
428429
if (base_parser.is_null()) {
429-
push_error(vformat(R"(Could not resolve super class "%s".)", name), p_class);
430+
push_error(vformat(R"(Could not resolve super class "%s".)", name), id);
430431
return ERR_PARSE_ERROR;
431432
}
432433

433434
Error err = base_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
434435
if (err != OK) {
435-
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class);
436+
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), id);
436437
return err;
437438
}
438439
base = base_parser->get_parser()->head->get_datatype();
439440
}
440441
} else if (ProjectSettings::get_singleton()->has_autoload(name) && ProjectSettings::get_singleton()->get_autoload(name).is_singleton) {
441442
const ProjectSettings::AutoloadInfo &info = ProjectSettings::get_singleton()->get_autoload(name);
442443
if (info.path.get_extension().to_lower() != GDScriptLanguage::get_singleton()->get_extension()) {
443-
push_error(vformat(R"(Singleton %s is not a GDScript.)", info.name), p_class);
444+
push_error(vformat(R"(Singleton %s is not a GDScript.)", info.name), id);
444445
return ERR_PARSE_ERROR;
445446
}
446447

447448
Ref<GDScriptParserRef> info_parser = get_parser_for(info.path);
448449
if (info_parser.is_null()) {
449-
push_error(vformat(R"(Could not parse singleton from "%s".)", info.path), p_class);
450+
push_error(vformat(R"(Could not parse singleton from "%s".)", info.path), id);
450451
return ERR_PARSE_ERROR;
451452
}
452453

453454
Error err = info_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
454455
if (err != OK) {
455-
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class);
456+
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), id);
456457
return err;
457458
}
458459
base = info_parser->get_parser()->head->get_datatype();
@@ -467,7 +468,7 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
467468
for (GDScriptParser::ClassNode *look_class : script_classes) {
468469
if (look_class->identifier && look_class->identifier->name == name) {
469470
if (!look_class->get_datatype().is_set()) {
470-
Error err = resolve_class_inheritance(look_class, p_class);
471+
Error err = resolve_class_inheritance(look_class, id);
471472
if (err) {
472473
return err;
473474
}
@@ -477,35 +478,34 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
477478
break;
478479
}
479480
if (look_class->has_member(name)) {
480-
resolve_class_member(look_class, name, p_class);
481+
resolve_class_member(look_class, name, id);
481482
base = look_class->get_member(name).get_datatype();
482483
found = true;
483484
break;
484485
}
485486
}
486487

487488
if (!found) {
488-
push_error(vformat(R"(Could not find base class "%s".)", name), p_class);
489+
push_error(vformat(R"(Could not find base class "%s".)", name), id);
489490
return ERR_PARSE_ERROR;
490491
}
491492
}
492493
}
493494

494495
for (int index = extends_index; index < p_class->extends.size(); index++) {
496+
GDScriptParser::IdentifierNode *id = p_class->extends[index];
497+
495498
if (base.kind != GDScriptParser::DataType::CLASS) {
496-
push_error(R"(Super type "%s" is not a GDScript. Cannot get nested types.)", p_class);
499+
push_error(vformat(R"(Cannot get nested types for extension from non-GDScript type "%s".)", base.to_string()), id);
497500
return ERR_PARSE_ERROR;
498501
}
499502

500-
// TODO: Extends could use identifier nodes. That way errors can be pointed out properly and it can be used here.
501-
GDScriptParser::IdentifierNode *id = parser->alloc_node<GDScriptParser::IdentifierNode>();
502-
id->name = p_class->extends[index];
503-
504503
reduce_identifier_from_base(id, &base);
505-
506504
GDScriptParser::DataType id_type = id->get_datatype();
505+
507506
if (!id_type.is_set()) {
508-
push_error(vformat(R"(Could not find type "%s" under base "%s".)", id->name, base.to_string()), p_class);
507+
push_error(vformat(R"(Could not find nested type "%s".)", id->name), id);
508+
return ERR_PARSE_ERROR;
509509
}
510510

511511
base = id_type;

modules/gdscript/gdscript_editor.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3368,10 +3368,10 @@ ::Error GDScriptLanguage::lookup_code(const String &p_code, const String &p_symb
33683368

33693369
if (context.current_class && context.current_class->extends.size() > 0) {
33703370
bool success = false;
3371-
ClassDB::get_integer_constant(context.current_class->extends[0], p_symbol, &success);
3371+
ClassDB::get_integer_constant(context.current_class->extends[0]->name, p_symbol, &success);
33723372
if (success) {
33733373
r_result.type = ScriptLanguage::LOOKUP_RESULT_CLASS_CONSTANT;
3374-
r_result.class_name = context.current_class->extends[0];
3374+
r_result.class_name = context.current_class->extends[0]->name;
33753375
r_result.class_member = p_symbol;
33763376
return OK;
33773377
}

modules/gdscript/gdscript_parser.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -712,14 +712,14 @@ void GDScriptParser::parse_extends() {
712712
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected superclass name after "extends".)")) {
713713
return;
714714
}
715-
current_class->extends.push_back(previous.literal);
715+
current_class->extends.push_back(parse_identifier());
716716

717717
while (match(GDScriptTokenizer::Token::PERIOD)) {
718718
make_completion_context(COMPLETION_INHERIT_TYPE, current_class, chain_index++);
719719
if (!consume(GDScriptTokenizer::Token::IDENTIFIER, R"(Expected superclass name after ".".)")) {
720720
return;
721721
}
722-
current_class->extends.push_back(previous.literal);
722+
current_class->extends.push_back(parse_identifier());
723723
}
724724
}
725725

@@ -4479,7 +4479,7 @@ void GDScriptParser::TreePrinter::print_class(ClassNode *p_class) {
44794479
} else {
44804480
first = false;
44814481
}
4482-
push_text(p_class->extends[i]);
4482+
push_text(p_class->extends[i]->name);
44834483
}
44844484
}
44854485

modules/gdscript/gdscript_parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ class GDScriptParser {
710710
bool extends_used = false;
711711
bool onready_used = false;
712712
String extends_path;
713-
Vector<StringName> extends; // List for indexing: extends A.B.C
713+
Vector<IdentifierNode *> extends; // List for indexing: extends A.B.C
714714
DataType base_type;
715715
String fqcn; // Fully-qualified class name. Identifies uniquely any class in the project.
716716
#ifdef TOOLS_ENABLED

modules/gdscript/language_server/gdscript_extend_parser.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -717,7 +717,7 @@ Dictionary ExtendGDScriptParser::dump_class_api(const GDScriptParser::ClassNode
717717
class_api["path"] = path;
718718
Array extends_class;
719719
for (int i = 0; i < p_class->extends.size(); i++) {
720-
extends_class.append(String(p_class->extends[i]));
720+
extends_class.append(String(p_class->extends[i]->name));
721721
}
722722
class_api["extends_class"] = extends_class;
723723
class_api["extends_file"] = String(p_class->extends_path);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Foo extends RefCounted.Bar:
2+
pass
3+
4+
func test():
5+
print('not ok')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GDTEST_ANALYZER_ERROR
2+
Cannot get nested types for extension from non-GDScript type "RefCounted".
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
class Foo:
2+
pass
3+
4+
class Bar extends Foo.Baz:
5+
pass
6+
7+
func test():
8+
print('not ok')
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
GDTEST_ANALYZER_ERROR
2+
Could not find nested type "Baz".

0 commit comments

Comments
 (0)