| 1018 | } |
| 1019 | |
| 1020 | void GDScriptParser::parse_class_body(bool p_is_multiline) { |
| 1021 | bool class_end = false; |
| 1022 | bool next_is_static = false; |
| 1023 | while (!class_end && !is_at_end()) { |
| 1024 | GDScriptTokenizer::Token token = current; |
| 1025 | switch (token.type) { |
| 1026 | case GDScriptTokenizer::Token::VAR: |
| 1027 | parse_class_member(&GDScriptParser::parse_variable, AnnotationInfo::VARIABLE, "variable", next_is_static); |
| 1028 | if (next_is_static) { |
| 1029 | current_class->has_static_data = true; |
| 1030 | } |
| 1031 | break; |
| 1032 | case GDScriptTokenizer::Token::TK_CONST: |
| 1033 | parse_class_member(&GDScriptParser::parse_constant, AnnotationInfo::CONSTANT, "constant"); |
| 1034 | break; |
| 1035 | case GDScriptTokenizer::Token::SIGNAL: |
| 1036 | parse_class_member(&GDScriptParser::parse_signal, AnnotationInfo::SIGNAL, "signal"); |
| 1037 | break; |
| 1038 | case GDScriptTokenizer::Token::FUNC: |
| 1039 | parse_class_member(&GDScriptParser::parse_function, AnnotationInfo::FUNCTION, "function", next_is_static); |
| 1040 | break; |
| 1041 | case GDScriptTokenizer::Token::CLASS: |
| 1042 | parse_class_member(&GDScriptParser::parse_class, AnnotationInfo::CLASS, "class"); |
| 1043 | break; |
| 1044 | case GDScriptTokenizer::Token::ENUM: |
| 1045 | parse_class_member(&GDScriptParser::parse_enum, AnnotationInfo::NONE, "enum"); |
| 1046 | break; |
| 1047 | case GDScriptTokenizer::Token::STATIC: { |
| 1048 | advance(); |
| 1049 | next_is_static = true; |
| 1050 | if (!check(GDScriptTokenizer::Token::FUNC) && !check(GDScriptTokenizer::Token::VAR)) { |
| 1051 | push_error(R"(Expected "func" or "var" after "static".)"); |
| 1052 | } |
| 1053 | } break; |
| 1054 | case GDScriptTokenizer::Token::ANNOTATION: { |
| 1055 | advance(); |
| 1056 | |
| 1057 | // Check for class-level and standalone annotations. |
| 1058 | AnnotationNode *annotation = parse_annotation(AnnotationInfo::CLASS_LEVEL | AnnotationInfo::STANDALONE); |
| 1059 | if (annotation != nullptr) { |
| 1060 | if (annotation->applies_to(AnnotationInfo::STANDALONE)) { |
| 1061 | if (previous.type != GDScriptTokenizer::Token::NEWLINE) { |
| 1062 | push_error(R"(Expected newline after a standalone annotation.)"); |
| 1063 | } |
| 1064 | if (annotation->name == SNAME("@export_category") || annotation->name == SNAME("@export_group") || annotation->name == SNAME("@export_subgroup")) { |
| 1065 | current_class->add_member_group(annotation); |
| 1066 | } else if (annotation->name == SNAME("@warning_ignore_start") || annotation->name == SNAME("@warning_ignore_restore")) { |
| 1067 | // Some annotations need to be resolved and applied in the parser. |
| 1068 | annotation->apply(this, nullptr, nullptr); |
| 1069 | } else { |
| 1070 | push_error(R"(Unexpected standalone annotation.)"); |
| 1071 | } |
| 1072 | } else { // `AnnotationInfo::CLASS_LEVEL`. |
| 1073 | annotation_stack.push_back(annotation); |
| 1074 | } |
| 1075 | } |
| 1076 | break; |
| 1077 | } |
nothing calls this directly
no test coverage detected