Skip to content

Commit

Permalink
Merge pull request #81808 from anvilfolk/super-virtual
Browse files Browse the repository at this point in the history
GDScript: Add check for `super()` methods not being implemented
  • Loading branch information
akien-mga committed Sep 19, 2023
2 parents 9a1b4f3 + 729c9b4 commit 3d3a9ee
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 1 deletion.
8 changes: 7 additions & 1 deletion modules/gdscript/gdscript_analyzer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3204,7 +3204,13 @@ void GDScriptAnalyzer::reduce_call(GDScriptParser::CallNode *p_call, bool p_is_a
bool is_constructor = (base_type.is_meta_type || (p_call->callee && p_call->callee->type == GDScriptParser::Node::IDENTIFIER)) && p_call->function_name == SNAME("new");

if (get_function_signature(p_call, is_constructor, base_type, p_call->function_name, return_type, par_types, default_arg_count, method_flags)) {
// If the function require typed arrays we must make literals be typed.
// If the method is implemented in the class hierarchy, the virtual flag will not be set for that MethodInfo and the search stops there.
// Virtual check only possible for super() calls because class hierarchy is known. Node/Objects may have scripts attached we don't know of at compile-time.
if (p_call->is_super && method_flags.has_flag(METHOD_FLAG_VIRTUAL)) {
push_error(vformat(R"*(Cannot call the parent class' virtual function "%s()" because it hasn't been defined.)*", p_call->function_name), p_call);
}

// If the function requires typed arrays we must make literals be typed.
for (const KeyValue<int, GDScriptParser::ArrayNode *> &E : arrays) {
int index = E.key;
if (index < par_types.size() && par_types[index].has_container_element_type()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
func _init():
super()

func test():
pass
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
GDTEST_ANALYZER_ERROR
Cannot call the parent class' virtual function "_init()" because it hasn't been defined.
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
class BaseClass:
func _get_property_list():
return {"property" : "definition"}

class SuperClassMethodsRecognized extends BaseClass:
func _init():
# Recognizes super class methods.
var _x = _get_property_list()

class SuperMethodsRecognized extends BaseClass:
func _get_property_list():
# Recognizes super method.
var result = super()
result["new"] = "new"
return result

func test():
var test1 = SuperClassMethodsRecognized.new()
print(test1._get_property_list()) # Calls base class's method.
var test2 = SuperMethodsRecognized.new()
print(test2._get_property_list())
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
GDTEST_OK
{ "property": "definition" }
{ "property": "definition", "new": "new" }

0 comments on commit 3d3a9ee

Please sign in to comment.