Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
rune-scape committed Dec 18, 2022
1 parent 0bb94df commit d68870b
Show file tree
Hide file tree
Showing 10 changed files with 80 additions and 60 deletions.
82 changes: 24 additions & 58 deletions modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -243,11 +243,11 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
}

if (p_class->base_type.is_resolving()) {
push_error(vformat(R"(Could not resolve class "%s": Cyclic reference.)", type_from_metatype(p_class->get_datatype()).to_string()), p_source);
push_error(vformat(R"(Could not resolve class "%s": Cyclic inheritance.)", type_from_metatype(p_class->get_datatype()).to_string()), p_source);
return ERR_PARSE_ERROR;
}

if (!p_class->base_type.has_no_type()) {
if (p_class->base_type.is_hard_type()) {
// Already resolved.
return OK;
}
Expand Down Expand Up @@ -284,34 +284,10 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
GDScriptParser::ClassNode *previous_class = parser->current_class;
parser->current_class = p_class;

if (p_class->identifier) {
StringName class_name = p_class->identifier->name;
if (GDScriptParser::get_builtin_type(class_name) < Variant::VARIANT_MAX) {
push_error(vformat(R"(Class "%s" hides a built-in type.)", class_name), p_class->identifier);
} else if (class_exists(class_name)) {
push_error(vformat(R"(Class "%s" hides a native class.)", class_name), p_class->identifier);
} else if (ScriptServer::is_global_class(class_name) && (ScriptServer::get_global_class_path(class_name) != parser->script_path || p_class != parser->head)) {
push_error(vformat(R"(Class "%s" hides a global script class.)", class_name), p_class->identifier);
} else if (ProjectSettings::get_singleton()->has_autoload(class_name) && ProjectSettings::get_singleton()->get_autoload(class_name).is_singleton) {
push_error(vformat(R"(Class "%s" hides an autoload singleton.)", class_name), p_class->identifier);
}
}

GDScriptParser::DataType resolving_datatype;
resolving_datatype.kind = GDScriptParser::DataType::RESOLVING;
p_class->base_type = resolving_datatype;

// Set datatype for class.
GDScriptParser::DataType class_type;
class_type.is_constant = true;
class_type.is_meta_type = true;
class_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
class_type.kind = GDScriptParser::DataType::CLASS;
class_type.class_type = p_class;
class_type.script_path = parser->script_path;
class_type.builtin_type = Variant::OBJECT;
p_class->set_datatype(class_type);

GDScriptParser::DataType result;
if (!p_class->extends_used) {
result.type_source = GDScriptParser::DataType::ANNOTATED_INFERRED;
Expand All @@ -326,15 +302,15 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c

if (!p_class->extends_path.is_empty()) {
if (p_class->extends_path.is_relative_path()) {
p_class->extends_path = class_type.script_path.get_base_dir().path_join(p_class->extends_path).simplify_path();
p_class->extends_path = parser->script_path.get_base_dir().path_join(p_class->extends_path).simplify_path();
}
Ref<GDScriptParserRef> ext_parser = get_parser_for(p_class->extends_path);
if (ext_parser.is_null()) {
push_error(vformat(R"(Could not resolve super class path "%s".)", p_class->extends_path), p_class);
return ERR_PARSE_ERROR;
}

Error err = ext_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = ext_parser->raise_status(GDScriptParserRef::PARSED);
if (err != OK) {
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", p_class->extends_path), p_class);
return err;
Expand All @@ -361,7 +337,7 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
return ERR_PARSE_ERROR;
}

Error err = base_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = base_parser->raise_status(GDScriptParserRef::PARSED);
if (err != OK) {
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class);
return err;
Expand All @@ -381,7 +357,7 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
return ERR_PARSE_ERROR;
}

Error err = info_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = info_parser->raise_status(GDScriptParserRef::PARSED);
if (err != OK) {
push_error(vformat(R"(Could not resolve super class inheritance from "%s".)", name), p_class);
return err;
Expand All @@ -397,12 +373,6 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
get_class_node_current_scope_classes(p_class, &script_classes);
for (GDScriptParser::ClassNode *look_class : script_classes) {
if (look_class->identifier && look_class->identifier->name == name) {
if (!look_class->get_datatype().is_set()) {
Error err = resolve_class_inheritance(look_class, p_class);
if (err) {
return err;
}
}
base = look_class->get_datatype();
found = true;
break;
Expand Down Expand Up @@ -442,6 +412,10 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
base = id_type;
}

if (base.class_type != nullptr) {
resolve_class_inheritance(base.class_type, p_class);
}

result = base;
}

Expand All @@ -462,6 +436,8 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
}

p_class->base_type = result;

GDScriptParser::DataType class_type = p_class->get_datatype();
class_type.native_type = result.native_type;
p_class->set_datatype(class_type);

Expand Down Expand Up @@ -567,7 +543,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
String ext = path.get_extension();
if (ext == GDScriptLanguage::get_singleton()->get_extension()) {
Ref<GDScriptParserRef> ref = get_parser_for(path);
if (!ref.is_valid() || ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
if (!ref.is_valid() || ref->raise_status(GDScriptParserRef::PARSED) != OK) {
push_error(vformat(R"(Could not parse global class "%s" from "%s".)", first, ScriptServer::get_global_class_path(first)), p_type);
return bad_type;
}
Expand All @@ -584,7 +560,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
} else if (ProjectSettings::get_singleton()->has_autoload(first) && ProjectSettings::get_singleton()->get_autoload(first).is_singleton) {
const ProjectSettings::AutoloadInfo &autoload = ProjectSettings::get_singleton()->get_autoload(first);
Ref<GDScriptParserRef> ref = get_parser_for(autoload.path);
if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
if (ref->raise_status(GDScriptParserRef::PARSED) != OK) {
push_error(vformat(R"(Could not parse singleton "%s" from "%s".)", first, autoload.path), p_type);
return bad_type;
}
Expand Down Expand Up @@ -621,7 +597,7 @@ GDScriptParser::DataType GDScriptAnalyzer::resolve_datatype(GDScriptParser::Type
Ref<GDScript> gdscript = member.constant->initializer->reduced_value;
if (gdscript.is_valid()) {
Ref<GDScriptParserRef> ref = get_parser_for(gdscript->get_script_path());
if (ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED) != OK) {
if (ref->raise_status(GDScriptParserRef::PARSED) != OK) {
push_error(vformat(R"(Could not parse script from "%s".)", gdscript->get_script_path()), p_type);
return bad_type;
}
Expand Down Expand Up @@ -740,14 +716,6 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
return;
}

// If it's already resolving, that's ok.
if (!p_class->base_type.is_resolving()) {
Error err = resolve_class_inheritance(p_class);
if (err) {
return;
}
}

GDScriptParser::ClassNode *previous_class = parser->current_class;
parser->current_class = p_class;

Expand Down Expand Up @@ -1016,10 +984,6 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
} break;
case GDScriptParser::ClassNode::Member::CLASS:
check_class_member_name_conflict(p_class, member.m_class->identifier->name, member.m_class);
// If it's already resolving, that's ok.
if (!member.m_class->base_type.is_resolving()) {
resolve_class_inheritance(member.m_class, p_source);
}
break;
case GDScriptParser::ClassNode::Member::GROUP:
// No-op, but needed to silence warnings.
Expand Down Expand Up @@ -3000,7 +2964,7 @@ GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const Str
return type;
}

Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = ref->raise_status(GDScriptParserRef::PARSED);
if (err) {
push_error(vformat(R"(Could not resolve class "%s", because of a parser error.)", p_class_name), p_source);
type.type_source = GDScriptParser::DataType::UNDETECTED;
Expand Down Expand Up @@ -3199,6 +3163,11 @@ void GDScriptAnalyzer::reduce_identifier_from_base(GDScriptParser::IdentifierNod
}
}

Error err = resolve_class_inheritance(base_class);
if (err) {
break;
}

base_class = base_class->base_type.class_type;
}

Expand Down Expand Up @@ -3397,7 +3366,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
if (ResourceLoader::get_resource_type(autoload.path) == "GDScript") {
Ref<GDScriptParserRef> singl_parser = get_parser_for(autoload.path);
if (singl_parser.is_valid()) {
Error err = singl_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = singl_parser->raise_status(GDScriptParserRef::PARSED);
if (err == OK) {
result = type_from_metatype(singl_parser->get_parser()->head->get_datatype());
}
Expand All @@ -3411,7 +3380,7 @@ void GDScriptAnalyzer::reduce_identifier(GDScriptParser::IdentifierNode *p_ident
if (scr.is_valid()) {
Ref<GDScriptParserRef> singl_parser = get_parser_for(scr->get_script_path());
if (singl_parser.is_valid()) {
Error err = singl_parser->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = singl_parser->raise_status(GDScriptParserRef::PARSED);
if (err == OK) {
result = type_from_metatype(singl_parser->get_parser()->head->get_datatype());
}
Expand Down Expand Up @@ -4014,13 +3983,10 @@ GDScriptParser::DataType GDScriptAnalyzer::type_from_variant(const Variant &p_va
error_type.kind = GDScriptParser::DataType::VARIANT;
return error_type;
}
Error err = ref->raise_status(GDScriptParserRef::INHERITANCE_SOLVED);
Error err = ref->raise_status(GDScriptParserRef::PARSED);
GDScriptParser::ClassNode *found = nullptr;
if (err == OK) {
found = ref->get_parser()->find_class(gds->fully_qualified_name);
if (found != nullptr) {
err = resolve_class_inheritance(found, p_source);
}
}
if (err || found == nullptr) {
push_error(vformat(R"(Could not resolve script "%s".)", script_path), p_source);
Expand Down
28 changes: 28 additions & 0 deletions modules/gdscript/gdscript_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,31 @@ void GDScriptParser::end_statement(const String &p_context) {
}
}

void GDScriptParser::init_class_datatype(ClassNode *p_class) {
if (p_class->identifier) {
StringName class_name = p_class->identifier->name;
if (GDScriptParser::get_builtin_type(class_name) < Variant::VARIANT_MAX) {
push_error(vformat(R"(Class "%s" hides a built-in type.)", class_name), p_class->identifier);
} else if (ClassDB::class_exists(class_name) && ClassDB::is_class_exposed(class_name)) {
push_error(vformat(R"(Class "%s" hides a native class.)", class_name), p_class->identifier);
} else if (ScriptServer::is_global_class(class_name) && (ScriptServer::get_global_class_path(class_name) != script_path || p_class != head)) {
push_error(vformat(R"(Class "%s" hides a global script class.)", class_name), p_class->identifier);
} else if (ProjectSettings::get_singleton()->has_autoload(class_name) && ProjectSettings::get_singleton()->get_autoload(class_name).is_singleton) {
push_error(vformat(R"(Class "%s" hides an autoload singleton.)", class_name), p_class->identifier);
}
}

GDScriptParser::DataType class_type;
class_type.is_constant = true;
class_type.is_meta_type = true;
class_type.type_source = GDScriptParser::DataType::ANNOTATED_EXPLICIT;
class_type.kind = GDScriptParser::DataType::CLASS;
class_type.class_type = p_class;
class_type.script_path = script_path;
class_type.builtin_type = Variant::OBJECT;
p_class->set_datatype(class_type);
}

void GDScriptParser::parse_program() {
head = alloc_node<ClassNode>();
head->fqcn = script_path;
Expand Down Expand Up @@ -621,6 +646,7 @@ void GDScriptParser::parse_program() {
}
}

init_class_datatype(head);
parse_class_body(true);
complete_extents(head);

Expand Down Expand Up @@ -713,6 +739,8 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
parse_extends();
}

init_class_datatype(n_class);

consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after class declaration.)");

bool multiline = match(GDScriptTokenizer::Token::NEWLINE);
Expand Down
1 change: 1 addition & 0 deletions modules/gdscript/gdscript_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -1387,6 +1387,7 @@ class GDScriptParser {

// Main blocks.
void parse_program();
void init_class_datatype(ClassNode *p_class);
ClassNode *parse_class();
void parse_class_name();
void parse_extends();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
Cyclic inheritance.
Could not resolve class "InnerA": Cyclic inheritance.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
func test():
print("test")
var t = preload("out_of_order_inheritance_a.notest.gd").new()
print(t.test_val)
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_OK
waiting for godot
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
extends "out_of_order_inheritance_b.notest.gd"

var test_val = test_val_base % test_fn()

class AA extends BA:
const test_val_aa = test_val_a

class AB:
const test_val_base = test_val_ba

func test_fn():
return "godot"

const test_val_a = "waiting for %s"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
extends "out_of_order_inheritance_a.notest.gd".AA


class BA extends "out_of_order_inheritance_a.notest.gd".AB:
const test_val_ba = test_val_aa
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
GDTEST_ANALYZER_ERROR
GDTEST_PARSER_ERROR
Class "Vector2" hides a built-in type.

0 comments on commit d68870b

Please sign in to comment.