Kaynağa Gözat

GDScript: Allow classes declaration to be done in single line

Incidentally, allow multiple statements in single line functions when
using semicolon as a terminator.
George Marques 4 yıl önce
ebeveyn
işleme
e5ebc9710d

+ 16 - 7
modules/gdscript/gdscript_parser.cpp

@@ -579,7 +579,7 @@ void GDScriptParser::parse_program() {
 		}
 	}
 
-	parse_class_body();
+	parse_class_body(true);
 
 #ifdef TOOLS_ENABLED
 	for (Map<int, GDScriptTokenizer::CommentData>::Element *E = tokenizer.get_comments().front(); E; E = E->next()) {
@@ -615,9 +615,10 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
 	}
 
 	consume(GDScriptTokenizer::Token::COLON, R"(Expected ":" after class declaration.)");
-	consume(GDScriptTokenizer::Token::NEWLINE, R"(Expected newline after class declaration.)");
 
-	if (!consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block after class declaration.)")) {
+	bool multiline = match(GDScriptTokenizer::Token::NEWLINE);
+
+	if (multiline && !consume(GDScriptTokenizer::Token::INDENT, R"(Expected indented block after class declaration.)")) {
 		current_class = previous_class;
 		return n_class;
 	}
@@ -630,9 +631,11 @@ GDScriptParser::ClassNode *GDScriptParser::parse_class() {
 		end_statement("superclass");
 	}
 
-	parse_class_body();
+	parse_class_body(multiline);
 
-	consume(GDScriptTokenizer::Token::DEDENT, R"(Missing unindent at the end of the class body.)");
+	if (multiline) {
+		consume(GDScriptTokenizer::Token::DEDENT, R"(Missing unindent at the end of the class body.)");
+	}
 
 	current_class = previous_class;
 	return n_class;
@@ -747,7 +750,7 @@ void GDScriptParser::parse_class_member(T *(GDScriptParser::*p_parse_function)()
 	}
 }
 
-void GDScriptParser::parse_class_body() {
+void GDScriptParser::parse_class_body(bool p_is_multiline) {
 	bool class_end = false;
 	while (!class_end && !is_at_end()) {
 		switch (current.type) {
@@ -793,6 +796,9 @@ void GDScriptParser::parse_class_body() {
 		if (panic_mode) {
 			synchronize();
 		}
+		if (!p_is_multiline) {
+			class_end = true;
+		}
 	}
 }
 
@@ -1358,6 +1364,9 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
 	int error_count = 0;
 
 	do {
+		if (!multiline && previous.type == GDScriptTokenizer::Token::SEMICOLON && check(GDScriptTokenizer::Token::NEWLINE)) {
+			break;
+		}
 		Node *statement = parse_statement();
 		if (statement == nullptr) {
 			if (error_count++ > 100) {
@@ -1398,7 +1407,7 @@ GDScriptParser::SuiteNode *GDScriptParser::parse_suite(const String &p_context,
 				break;
 		}
 
-	} while (multiline && !check(GDScriptTokenizer::Token::DEDENT) && !lambda_ended && !is_at_end());
+	} while ((multiline || previous.type == GDScriptTokenizer::Token::SEMICOLON) && !check(GDScriptTokenizer::Token::DEDENT) && !lambda_ended && !is_at_end());
 
 	if (multiline) {
 		if (!lambda_ended) {

+ 1 - 1
modules/gdscript/gdscript_parser.h

@@ -1324,7 +1324,7 @@ private:
 	ClassNode *parse_class();
 	void parse_class_name();
 	void parse_extends();
-	void parse_class_body();
+	void parse_class_body(bool p_is_multiline);
 	template <class T>
 	void parse_class_member(T *(GDScriptParser::*p_parse_function)(), AnnotationInfo::TargetKind p_target, const String &p_member_kind);
 	SignalNode *parse_signal();

+ 22 - 0
modules/gdscript/tests/scripts/parser/features/semicolon_as_terminator.gd

@@ -0,0 +1,22 @@
+#GDTEST_OK
+
+func test():
+	a();
+	b();
+	c();
+	d();
+	e();
+
+func a(): print("a");
+
+func b(): print("b1"); print("b2")
+
+func c(): print("c1"); print("c2");
+
+func d():
+	print("d1");
+	print("d2")
+
+func e():
+	print("e1");
+	print("e2");

+ 10 - 0
modules/gdscript/tests/scripts/parser/features/semicolon_as_terminator.out

@@ -0,0 +1,10 @@
+GDTEST_OK
+a
+b1
+b2
+c1
+c2
+d1
+d2
+e1
+e2

+ 11 - 0
modules/gdscript/tests/scripts/parser/features/single_line_declaration.gd

@@ -0,0 +1,11 @@
+#GDTEST_OK
+
+func test(): C.new().test("Ok"); test2()
+
+func test2(): print("Ok 2")
+
+class A: pass
+
+class B extends RefCounted: pass
+
+class C extends RefCounted: func test(x): print(x)

+ 3 - 0
modules/gdscript/tests/scripts/parser/features/single_line_declaration.out

@@ -0,0 +1,3 @@
+GDTEST_OK
+Ok
+Ok 2