Browse Source

Merge pull request #72971 from vnen/gdscript-multiline-comment

GDScript: Allow strings as multiline comments
Rémi Verschelde 2 years ago
parent
commit
dc7f08b556

+ 51 - 15
modules/gdscript/gdscript_parser.cpp

@@ -483,24 +483,34 @@ void GDScriptParser::parse_program() {
 	current_class = head;
 	bool can_have_class_or_extends = true;
 
-	while (match(GDScriptTokenizer::Token::ANNOTATION)) {
-		AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL);
-		if (annotation != nullptr) {
-			if (annotation->applies_to(AnnotationInfo::SCRIPT)) {
-				// `@icon` needs to be applied in the parser. See GH-72444.
-				if (annotation->name == SNAME("@icon")) {
-					annotation->apply(this, head);
+	while (!check(GDScriptTokenizer::Token::TK_EOF)) {
+		if (match(GDScriptTokenizer::Token::ANNOTATION)) {
+			AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::STANDALONE | AnnotationInfo::CLASS_LEVEL);
+			if (annotation != nullptr) {
+				if (annotation->applies_to(AnnotationInfo::SCRIPT)) {
+					// `@icon` needs to be applied in the parser. See GH-72444.
+					if (annotation->name == SNAME("@icon")) {
+						annotation->apply(this, head);
+					} else {
+						head->annotations.push_back(annotation);
+					}
 				} else {
-					head->annotations.push_back(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;
 				}
-			} else {
-				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;
 			}
+		} else if (check(GDScriptTokenizer::Token::LITERAL) && current.literal.get_type() == Variant::STRING) {
+			// Allow strings in class body as multiline comments.
+			advance();
+			if (!match(GDScriptTokenizer::Token::NEWLINE)) {
+				push_error("Expected newline after comment string.");
+			}
+		} else {
+			break;
 		}
 	}
 
@@ -524,6 +534,16 @@ void GDScriptParser::parse_program() {
 					end_statement("superclass");
 				}
 				break;
+			case GDScriptTokenizer::Token::LITERAL:
+				if (current.literal.get_type() == Variant::STRING) {
+					// Allow strings in class body as multiline comments.
+					advance();
+					if (!match(GDScriptTokenizer::Token::NEWLINE)) {
+						push_error("Expected newline after comment string.");
+					}
+					break;
+				}
+				[[fallthrough]];
 			default:
 				// No tokens are allowed between script annotations and class/extends.
 				can_have_class_or_extends = false;
@@ -829,6 +849,16 @@ void GDScriptParser::parse_class_body(bool p_is_multiline) {
 			case GDScriptTokenizer::Token::DEDENT:
 				class_end = true;
 				break;
+			case GDScriptTokenizer::Token::LITERAL:
+				if (current.literal.get_type() == Variant::STRING) {
+					// Allow strings in class body as multiline comments.
+					advance();
+					if (!match(GDScriptTokenizer::Token::NEWLINE)) {
+						push_error("Expected newline after comment string.");
+					}
+					break;
+				}
+				[[fallthrough]];
 			default:
 				// Display a completion with identifiers.
 				make_completion_context(COMPLETION_IDENTIFIER, nullptr);
@@ -1675,6 +1705,12 @@ GDScriptParser::Node *GDScriptParser::parse_statement() {
 						// Standalone lambdas can't be used, so make this an error.
 						push_error("Standalone lambdas cannot be accessed. Consider assigning it to a variable.", expression);
 						break;
+					case Node::LITERAL:
+						if (static_cast<GDScriptParser::LiteralNode *>(expression)->value.get_type() == Variant::STRING) {
+							// Allow strings as multiline comments.
+							break;
+						}
+						[[fallthrough]];
 					default:
 						push_warning(expression, GDScriptWarning::STANDALONE_EXPRESSION);
 				}

+ 21 - 0
modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.gd

@@ -0,0 +1,21 @@
+"""
+This is a comment.
+"""
+
+@tool
+
+"""
+This is also a comment.
+"""
+
+extends RefCounted
+
+'''
+This is a comment too.
+'''
+
+func test():
+	"""
+	This too is a comment.
+	"""
+	print("ok")

+ 2 - 0
modules/gdscript/tests/scripts/parser/features/allow_strings_as_comments.out

@@ -0,0 +1,2 @@
+GDTEST_OK
+ok

+ 0 - 1
modules/gdscript/tests/scripts/parser/warnings/standalone_expression.gd

@@ -1,6 +1,5 @@
 func test():
 	# The following statements should all be reported as standalone expressions:
-	"This is a standalone expression"
 	1234
 	0.0 + 0.0
 	Color(1, 1, 1)

+ 1 - 5
modules/gdscript/tests/scripts/parser/warnings/standalone_expression.out

@@ -8,14 +8,10 @@ GDTEST_OK
 >> STANDALONE_EXPRESSION
 >> Standalone expression (the line has no effect).
 >> WARNING
->> Line: 5
+>> Line: 6
 >> STANDALONE_EXPRESSION
 >> Standalone expression (the line has no effect).
 >> WARNING
 >> Line: 7
 >> STANDALONE_EXPRESSION
 >> Standalone expression (the line has no effect).
->> WARNING
->> Line: 8
->> STANDALONE_EXPRESSION
->> Standalone expression (the line has no effect).