فهرست منبع

GDScript: Add check for `super()` methods not being implemented

ocean (they/them) 2 سال پیش
والد
کامیت
729c9b4d4b

+ 7 - 1
modules/gdscript/gdscript_analyzer.cpp

@@ -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()) {

+ 5 - 0
modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.gd

@@ -0,0 +1,5 @@
+func _init():
+	super()
+
+func test():
+	pass

+ 2 - 0
modules/gdscript/tests/scripts/analyzer/errors/virtual_super_not_implemented.out

@@ -0,0 +1,2 @@
+GDTEST_ANALYZER_ERROR
+Cannot call the parent class' virtual function "_init()" because it hasn't been defined.

+ 21 - 0
modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.gd

@@ -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())

+ 3 - 0
modules/gdscript/tests/scripts/analyzer/features/virtual_method_implemented.out

@@ -0,0 +1,3 @@
+GDTEST_OK
+{ "property": "definition" }
+{ "property": "definition", "new": "new" }