GDScript: Replace abstract keyword with @abstract annotation

Co-authored-by: Danil Alexeev <dalexeev12@yandex.ru>
This commit is contained in:
Aaron Franke
2025-06-19 04:53:15 -07:00
parent 88b9932ce1
commit 1085200f51
31 changed files with 179 additions and 197 deletions

View File

@ -1540,12 +1540,12 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class, co
if (member.function->is_abstract) {
if (base_class == p_class) {
const String class_name = p_class->identifier == nullptr ? p_class->fqcn.get_file() : String(p_class->identifier->name);
push_error(vformat(R"*(Class "%s" is not abstract but contains abstract methods. Mark the class as abstract or remove "abstract" from all methods in this class.)*", class_name), p_class);
push_error(vformat(R"*(Class "%s" is not abstract but contains abstract methods. Mark the class as "@abstract" or remove "@abstract" from all methods in this class.)*", class_name), p_class);
break;
} else if (!implemented_funcs.has(member.function->identifier->name)) {
const String class_name = p_class->identifier == nullptr ? p_class->fqcn.get_file() : String(p_class->identifier->name);
const String base_class_name = base_class->identifier == nullptr ? base_class->fqcn.get_file() : String(base_class->identifier->name);
push_error(vformat(R"*(Class "%s" must implement "%s.%s()" and other inherited abstract methods or be marked as abstract.)*", class_name, base_class_name, member.function->identifier->name), p_class);
push_error(vformat(R"*(Class "%s" must implement "%s.%s()" and other inherited abstract methods or be marked as "@abstract".)*", class_name, base_class_name, member.function->identifier->name), p_class);
break;
}
} else {
@ -1987,6 +1987,20 @@ void GDScriptAnalyzer::resolve_function_body(GDScriptParser::FunctionNode *p_fun
}
p_function->resolved_body = true;
if (p_function->is_abstract) {
// Abstract functions don't have a body.
if (!p_function->body->statements.is_empty()) {
push_error(R"(Abstract function cannot have a body.)", p_function->body);
}
return;
} else {
// Non-abstract functions must have a body.
if (p_function->body->statements.is_empty()) {
push_error(R"(A function must either have a ":" followed by a body, or be marked as "@abstract".)", p_function);
return;
}
}
GDScriptParser::FunctionNode *previous_function = parser->current_function;
parser->current_function = p_function;
@ -1999,7 +2013,7 @@ void GDScriptAnalyzer::resolve_function_body(GDScriptParser::FunctionNode *p_fun
// Use the suite inferred type if return isn't explicitly set.
p_function->set_datatype(p_function->body->get_datatype());
} else if (p_function->get_datatype().is_hard_type() && (p_function->get_datatype().kind != GDScriptParser::DataType::BUILTIN || p_function->get_datatype().builtin_type != Variant::NIL)) {
if (!p_function->is_abstract && !p_function->body->has_return && (p_is_lambda || p_function->identifier->name != GDScriptLanguage::get_singleton()->strings._init)) {
if (!p_function->body->has_return && (p_is_lambda || p_function->identifier->name != GDScriptLanguage::get_singleton()->strings._init)) {
push_error(R"(Not all code paths return a value.)", p_function);
}
}