mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 16:03:29 +00:00
GDScript: Allow out of order member resolution
This commit is contained in:
parent
97df6de4a7
commit
2dfc6d5b69
30 changed files with 797 additions and 233 deletions
|
@ -642,6 +642,53 @@ void GDScriptParser::parse_program() {
|
|||
clear_unused_annotations();
|
||||
}
|
||||
|
||||
GDScriptParser::ClassNode *GDScriptParser::find_class(const String &p_qualified_name) const {
|
||||
String first = p_qualified_name.get_slice("::", 0);
|
||||
|
||||
Vector<String> class_names;
|
||||
GDScriptParser::ClassNode *result = nullptr;
|
||||
// Empty initial name means start at the head.
|
||||
if (first.is_empty() || (head->identifier && first == head->identifier->name)) {
|
||||
class_names = p_qualified_name.split("::");
|
||||
result = head;
|
||||
} else if (p_qualified_name.begins_with(script_path)) {
|
||||
// Script path could have a class path separator("::") in it.
|
||||
class_names = p_qualified_name.trim_prefix(script_path).split("::");
|
||||
result = head;
|
||||
} else if (head->has_member(first)) {
|
||||
class_names = p_qualified_name.split("::");
|
||||
GDScriptParser::ClassNode::Member member = head->get_member(first);
|
||||
if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
|
||||
result = member.m_class;
|
||||
}
|
||||
}
|
||||
|
||||
// Starts at index 1 because index 0 was handled above.
|
||||
for (int i = 1; result != nullptr && i < class_names.size(); i++) {
|
||||
String current_name = class_names[i];
|
||||
GDScriptParser::ClassNode *next = nullptr;
|
||||
if (result->has_member(current_name)) {
|
||||
GDScriptParser::ClassNode::Member member = result->get_member(current_name);
|
||||
if (member.type == GDScriptParser::ClassNode::Member::CLASS) {
|
||||
next = member.m_class;
|
||||
}
|
||||
}
|
||||
result = next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool GDScriptParser::has_class(const GDScriptParser::ClassNode *p_class) const {
|
||||
if (head->fqcn.is_empty() && p_class->fqcn.get_slice("::", 0).is_empty()) {
|
||||
return p_class == head;
|
||||
} else if (p_class->fqcn.begins_with(head->fqcn)) {
|
||||
return find_class(p_class->fqcn.trim_prefix(head->fqcn)) == p_class;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
GDScriptParser::ClassNode *GDScriptParser::parse_class() {
|
||||
ClassNode *n_class = alloc_node<ClassNode>();
|
||||
|
||||
|
@ -2240,7 +2287,7 @@ GDScriptParser::IdentifierNode *GDScriptParser::parse_identifier() {
|
|||
|
||||
GDScriptParser::ExpressionNode *GDScriptParser::parse_identifier(ExpressionNode *p_previous_operand, bool p_can_assign) {
|
||||
if (!previous.is_identifier()) {
|
||||
ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing literal node without literal token.");
|
||||
ERR_FAIL_V_MSG(nullptr, "Parser bug: parsing identifier node without identifier token.");
|
||||
}
|
||||
IdentifierNode *identifier = alloc_node<IdentifierNode>();
|
||||
complete_extents(identifier);
|
||||
|
@ -4042,11 +4089,12 @@ String GDScriptParser::DataType::to_string() const {
|
|||
}
|
||||
case ENUM:
|
||||
return enum_type.operator String() + " (enum)";
|
||||
case RESOLVING:
|
||||
case UNRESOLVED:
|
||||
return "<unresolved type>";
|
||||
}
|
||||
|
||||
ERR_FAIL_V_MSG("<unresolved type", "Kind set outside the enum range.");
|
||||
ERR_FAIL_V_MSG("<unresolved type>", "Kind set outside the enum range.");
|
||||
}
|
||||
|
||||
static Variant::Type _variant_type_to_typed_array_element_type(Variant::Type p_type) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue