Skip to content

Commit 1ed9255

Browse files
supported abstract and vararg methods
1 parent 190eb09 commit 1ed9255

File tree

13 files changed

+58
-49
lines changed

13 files changed

+58
-49
lines changed

editor/editor_help.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -150,12 +150,6 @@ static void _add_qualifiers_to_rt(const String &p_qualifiers, RichTextLabel *p_r
150150
hint = TTR("This method is called by the engine.\nIt can be overridden to customize built-in behavior.");
151151
} else if (qualifier == "required") {
152152
hint = TTR("This method is required to be overridden when extending its base class.");
153-
} else if (qualifier == "virtual_annotated") {
154-
hint = TTR("This method is annotated to be allowed be overridden to customize user-defined behavior.");
155-
qualifier = "virtual";
156-
} else if (qualifier == "virtual_annotated_underscored") {
157-
hint = TTR("This method is annotated to be called by user-defined behavior.\nIt can be overridden to customize new behavior.");
158-
qualifier = "virtual";
159153
} else if (qualifier == "const") {
160154
hint = TTR("This method has no side effects.\nIt does not modify the object in any way.");
161155
} else if (qualifier == "static") {

modules/gdscript/doc_classes/@GDScript.xml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -743,7 +743,7 @@
743743
<annotation name="@override">
744744
<return type="void" />
745745
<description>
746-
Mark that the following method overrides the one annotated by [annotation @virtual] from the base class.
746+
Mark that the following method overrides the one annotated by [annotation @virtual] or modified by [code]abstract[/code] from the base class.
747747
If you override a method from the base class without this annotation, you will get a warning (or an error).
748748
[codeblock]
749749
func _init():
@@ -757,8 +757,15 @@
757757
class B extends A:
758758
func test():
759759
print("B") # Warning (or an error) about overriding a virtual method without explicit overriding.
760+
761+
abstract class C:
762+
abstract func test():
763+
764+
class D extends C:
765+
func test():
766+
print("D") # Warning (or an error) about overriding an abstract method without explicit overriding.
760767
[/codeblock]
761-
You can ignore the warning as long as you know what you are doing.
768+
Due to that this annotation improves code readability, it is recommended to use it whenever possible. You can ignore the warning as long as you know what you are doing.
762769
</description>
763770
</annotation>
764771
<annotation name="@rpc">
@@ -837,7 +844,7 @@
837844
func test():
838845
print("B") # Warning (or an error) about overriding a non-virtual method.
839846
[/codeblock]
840-
You can ignore the warning as long as you know what you are doing.
847+
Due to that this annotation improves code readability, it is recommended to use it whenever possible. You can ignore the warning as long as you know what you are doing.
841848
</description>
842849
</annotation>
843850
<annotation name="@warning_ignore" qualifiers="vararg">

modules/gdscript/editor/gdscript_docgen.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -425,7 +425,7 @@ void GDScriptDocGen::_generate_docs(GDScript *p_script, const GDP::ClassNode *p_
425425
if (!method_doc.qualifiers.is_empty()) {
426426
method_doc.qualifiers += " ";
427427
}
428-
method_doc.qualifiers += String(m_func->identifier->name).begins_with("_") ? "virtual_annotated" : "virtual_annotated_underscored";
428+
method_doc.qualifiers += String(m_func->identifier->name).begins_with("_") ? "virtual_annotated_underscored" : "virtual_annotated";
429429
}
430430
if (m_func->is_static) {
431431
if (!method_doc.qualifiers.is_empty()) {

modules/gdscript/gdscript_analyzer.cpp

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1955,23 +1955,17 @@ void GDScriptAnalyzer::resolve_function_signature(GDScriptParser::FunctionNode *
19551955
} else {
19561956
parent_signature += return_type;
19571957
}
1958-
1959-
// (Non-)virtual methods overriding warnings
1960-
if (base_type.class_type != nullptr && base_type.class_type->has_function(p_function->identifier->name)) {
1961-
GDScriptParser::FunctionNode *parent_func = base_type.class_type->get_member(p_function->identifier->name).function;
1962-
if (parent_func->is_abstract) {
1963-
push_error(R"(The usage of the annotation '@virtual' conflicts with an abstract method. Either remove the '@virtual' annotation or 'abstract' keyword from the method declaration.)");
1964-
return;
1965-
}
1966-
if (!parent_func->is_annotated_virtual) {
1967-
parser->push_warning(p_function, GDScriptWarning::OVERRIDE_NON_VIRTUAL_METHOD, function_name);
1968-
} else if (!p_function->is_annotated_overriding) {
1969-
parser->push_warning(p_function, GDScriptWarning::OVERRIDE_WITHOUT_OVERRIDE_ANNOTATION, function_name);
1970-
}
1971-
}
1972-
19731958
push_error(vformat(R"(The function signature doesn't match the parent. Parent signature is "%s".)", parent_signature), p_function);
19741959
}
1960+
// (Non-)virtual methods overriding warnings
1961+
if (base_type.class_type != nullptr && base_type.class_type->has_function(p_function->identifier->name)) {
1962+
GDScriptParser::FunctionNode *parent_func = base_type.class_type->get_member(p_function->identifier->name).function;
1963+
if (!parent_func->is_annotated_virtual && !parent_func->is_abstract) {
1964+
parser->push_warning(p_function, GDScriptWarning::OVERRIDE_NON_VIRTUAL_METHOD, function_name);
1965+
} else if (!p_function->is_annotated_overriding) {
1966+
parser->push_warning(p_function, GDScriptWarning::OVERRIDE_WITHOUT_OVERRIDE_ANNOTATION, function_name);
1967+
}
1968+
}
19751969
} else if (p_function->is_annotated_overriding) {
19761970
parser->push_warning(p_function, GDScriptWarning::OVERRIDE_INEXISTENT_METHOD_FROM_BASE, function_name);
19771971
}

modules/gdscript/gdscript_parser.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4439,7 +4439,10 @@ bool GDScriptParser::virtual_annotation(AnnotationNode *p_annotation, Node *p_ta
44394439
ERR_FAIL_COND_V_MSG(p_target->type == Node::LAMBDA, false, R"("@virtual" annotation cannot be applied to lambdas.)");
44404440

44414441
FunctionNode *method = static_cast<FunctionNode *>(p_target);
4442-
if (method->is_annotated_virtual) {
4442+
if (method->is_abstract) {
4443+
push_error(R"(The usage of "@virtual" annotation conflicts with the "abstract" keyword. Either remove the "@virtual" annotation or "abstract" keyword from the method's declaration.)", p_annotation);
4444+
return false;
4445+
} else if (method->is_annotated_virtual) {
44434446
push_error(R"("@virtual" annotation can only be used once per method.)", p_annotation);
44444447
return false;
44454448
}

modules/gdscript/gdscript_warning.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ String GDScriptWarning::get_message() const {
167167
return vformat(R"*(The method "%s()" overrides a non-virtual method from the base class. This may cause unexpected and unsafe behaviors.)*", symbols[0]);
168168
case OVERRIDE_WITHOUT_OVERRIDE_ANNOTATION:
169169
CHECK_SYMBOLS(1);
170-
return vformat(R"*(The method "%s()" overrides a virtual method from the base class without the "@override" annotation. Annotating the method with the annotation can better help you understand and clarify the code structure.)*", symbols[0]);
170+
return vformat(R"*(The method "%s()" overrides a virtual or an abstract method from the base class without the "@override" annotation. Annotating the method with the annotation can better help you understand and clarify the code structure.)*", symbols[0]);
171171
case OVERRIDE_INEXISTENT_METHOD_FROM_BASE:
172172
CHECK_SYMBOLS(1);
173173
return vformat(R"*(The method "%s()" is annotated with the "@override" annotation, but the method is not found in the base class. Consider removing the "@override" annotation in this case.)*", symbols[0]);

modules/gdscript/tests/scripts/analyzer/features/out_of_order.gd

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@ func test():
1717
var v1 := InnerA.new().fn()
1818

1919
class InnerA extends InnerAB:
20-
func fn(p2 := E1.V2) -> String:
20+
@override func fn(p2 := E1.V2) -> String:
2121
return "%s, p2=%s" % [super.fn(), p2]
2222

2323
class InnerAB:
24-
func fn(p1 := c1) -> String:
24+
@virtual func fn(p1 := c1) -> String:
2525
return "p1=%s" % p1
2626

2727
var v2 := f()

modules/gdscript/tests/scripts/analyzer/features/out_of_order.out

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
GDTEST_OK
2-
~~ WARNING at line 20: (OVERRIDE_NON_VIRTUAL_METHOD) The method "fn()" overrides a non-virtual method from the base class. This may cause unexpected and unsafe behaviors.
32
v1: p1=4, p2=3
43
v1 is String: true
54
v2: true

modules/gdscript/tests/scripts/analyzer/warnings/override_non_virtual_method.gd

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,17 @@ class ChildOverrideInexistentMethod extends ParentSafe:
2323
@override func test_():
2424
pass
2525

26+
abstract class AbstractParent:
27+
abstract func test()
28+
abstract func test2()
29+
30+
class ChildAbstract extends AbstractParent:
31+
func test():
32+
pass
33+
34+
@override func test2():
35+
pass
36+
2637

2738
func test():
2839
pass
Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
GDTEST_OK
22
~~ WARNING at line 10: (OVERRIDE_NON_VIRTUAL_METHOD) The method "test()" overrides a non-virtual method from the base class. This may cause unexpected and unsafe behaviors.
3-
~~ WARNING at line 14: (OVERRIDE_WITHOUT_OVERRIDE_ANNOTATION) The method "test()" overrides a virtual method from the base class without the "@override" annotation. Annotating the method with the annotation can better help you understand and clarify the code structure.
3+
~~ WARNING at line 14: (OVERRIDE_WITHOUT_OVERRIDE_ANNOTATION) The method "test()" overrides a virtual or an abstract method from the base class without the "@override" annotation. Annotating the method with the annotation can better help you understand and clarify the code structure.
44
~~ WARNING at line 23: (OVERRIDE_INEXISTENT_METHOD_FROM_BASE) The method "test_()" is annotated with the "@override" annotation, but the method is not found in the base class. Consider removing the "@override" annotation in this case.
5+
~~ WARNING at line 31: (OVERRIDE_WITHOUT_OVERRIDE_ANNOTATION) The method "test()" overrides a virtual or an abstract method from the base class without the "@override" annotation. Annotating the method with the annotation can better help you understand and clarify the code structure.

0 commit comments

Comments
 (0)