diff options
| author | Aaron Franke <arnfranke@yahoo.com> | 2022-10-22 18:32:21 -0500 |
|---|---|---|
| committer | Aaron Franke <arnfranke@yahoo.com> | 2022-12-19 22:01:29 -0600 |
| commit | 6590e1fd8a0770894626d012c2391f2ae1efa497 (patch) | |
| tree | 1046f111aaa78cc14f69dbfe73f6a79b480a76a3 /modules/gdscript/gdscript_parser.cpp | |
| parent | dcb3754db09b7b8c35aae1fedbc485b91e9f9508 (diff) | |
| download | redot-engine-6590e1fd8a0770894626d012c2391f2ae1efa497.tar.gz | |
Make script annotations placed before class_name and extends
Diffstat (limited to 'modules/gdscript/gdscript_parser.cpp')
| -rw-r--r-- | modules/gdscript/gdscript_parser.cpp | 54 |
1 files changed, 11 insertions, 43 deletions
diff --git a/modules/gdscript/gdscript_parser.cpp b/modules/gdscript/gdscript_parser.cpp index 103269f0f5..9b55d6663c 100644 --- a/modules/gdscript/gdscript_parser.cpp +++ b/modules/gdscript/gdscript_parser.cpp @@ -540,43 +540,28 @@ void GDScriptParser::parse_program() { head = alloc_node<ClassNode>(); head->fqcn = script_path; current_class = head; + bool can_have_class_or_extends = true; - // If we happen to parse an annotation before extends or class_name keywords, track it. - // @tool is allowed, but others should fail. - AnnotationNode *premature_annotation = nullptr; - - if (match(GDScriptTokenizer::Token::ANNOTATION)) { - // Check for @tool, script-level, or standalone annotation. + while (match(GDScriptTokenizer::Token::ANNOTATION)) { AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL); if (annotation != nullptr) { - if (annotation->name == SNAME("@tool")) { - // TODO: don't allow @tool anywhere else. (Should all script annotations be the first thing?). - _is_tool = true; - if (previous.type != GDScriptTokenizer::Token::NEWLINE) { - push_error(R"(Expected newline after "@tool" annotation.)"); - } - // @tool annotation has no specific target. - annotation->apply(this, nullptr); - } else if (annotation->applies_to(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE)) { - premature_annotation = annotation; - if (previous.type != GDScriptTokenizer::Token::NEWLINE) { - push_error(R"(Expected newline after a standalone annotation.)"); - } + if (annotation->applies_to(AnnotationInfo::SCRIPT)) { annotation->apply(this, head); } else { - premature_annotation = annotation; annotation_stack.push_back(annotation); + // This annotation must appear after script-level annotations + // and class_name/extends (ex: could be @onready or @export), + // so we stop looking for script-level stuff. + can_have_class_or_extends = false; + break; } } } - for (bool should_break = false; !should_break;) { + while (can_have_class_or_extends) { // Order here doesn't matter, but there should be only one of each at most. switch (current.type) { case GDScriptTokenizer::Token::CLASS_NAME: - if (premature_annotation != nullptr) { - push_error(R"("class_name" should be used before annotations (except @tool).)"); - } advance(); if (head->identifier != nullptr) { push_error(R"("class_name" can only be used once.)"); @@ -585,9 +570,6 @@ void GDScriptParser::parse_program() { } break; case GDScriptTokenizer::Token::EXTENDS: - if (premature_annotation != nullptr) { - push_error(R"("extends" should be used before annotations (except @tool).)"); - } advance(); if (head->extends_used) { push_error(R"("extends" can only be used once.)"); @@ -597,7 +579,8 @@ void GDScriptParser::parse_program() { } break; default: - should_break = true; + // No tokens are allowed between script annotations and class/extends. + can_have_class_or_extends = false; break; } @@ -606,21 +589,6 @@ void GDScriptParser::parse_program() { } } - if (match(GDScriptTokenizer::Token::ANNOTATION)) { - // Check for a script-level, or standalone annotation. - AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL); - if (annotation != nullptr) { - if (annotation->applies_to(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE)) { - if (previous.type != GDScriptTokenizer::Token::NEWLINE) { - push_error(R"(Expected newline after a standalone annotation.)"); - } - annotation->apply(this, head); - } else { - annotation_stack.push_back(annotation); - } - } - } - parse_class_body(true); complete_extents(head); |
