Allow return without expression, AST-equivalent to return None.
--
MOS_MIGRATED_REVID=100268427
diff --git a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
index 21eb2a5..8f59047 100644
--- a/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
+++ b/src/main/java/com/google/devtools/build/lib/syntax/Parser.java
@@ -84,7 +84,7 @@
}
private static final EnumSet<TokenKind> STATEMENT_TERMINATOR_SET =
- EnumSet.of(TokenKind.EOF, TokenKind.NEWLINE);
+ EnumSet.of(TokenKind.EOF, TokenKind.NEWLINE, TokenKind.SEMI);
private static final EnumSet<TokenKind> LIST_TERMINATOR_SET =
EnumSet.of(TokenKind.EOF, TokenKind.RBRACKET, TokenKind.SEMI);
@@ -1483,11 +1483,20 @@
token.right);
}
- // return_stmt ::= RETURN expr
+ // return_stmt ::= RETURN [expr]
private ReturnStatement parseReturnStatement() {
int start = token.left;
+ int end = token.right;
expect(TokenKind.RETURN);
- Expression expression = parseExpression();
+
+ Expression expression;
+ if (STATEMENT_TERMINATOR_SET.contains(token.kind)) {
+ // this None makes the AST not correspond to the source exactly anymore
+ expression = new Identifier("None");
+ setLocation(expression, start, end);
+ } else {
+ expression = parseExpression();
+ }
return setLocation(new ReturnStatement(expression), start, expression);
}
diff --git a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
index 93e14a8..a9f32c0 100644
--- a/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
+++ b/src/test/java/com/google/devtools/build/lib/syntax/ParserTest.java
@@ -967,6 +967,36 @@
List<Statement> stmts3 = parseFile("[ i for (i, j, k) in [(1, 2, 3)] ]\n");
assertThat(stmts3).hasSize(1);
}
+
+ @Test
+ public void testReturnNone() throws Exception {
+ List<Statement> defNone = parseFileForSkylark("def foo():", " return None\n");
+ assertThat(defNone).hasSize(1);
+
+ List<Statement> bodyNone = ((FunctionDefStatement) defNone.get(0)).getStatements();
+ assertThat(bodyNone).hasSize(1);
+
+ ReturnStatement returnNone = (ReturnStatement) bodyNone.get(0);
+ assertEquals("None", ((Identifier) returnNone.getReturnExpression()).getName());
+
+ int i = 0;
+ for (String end : new String[]{";", "\n"}) {
+ List<Statement> defNoExpr = parseFileForSkylark("def bar" + i + "():", " return" + end);
+ i++;
+ assertThat(defNoExpr).hasSize(1);
+
+ List<Statement> bodyNoExpr = ((FunctionDefStatement) defNoExpr.get(0)).getStatements();
+ assertThat(bodyNoExpr).hasSize(1);
+
+ ReturnStatement returnNoExpr = (ReturnStatement) bodyNoExpr.get(0);
+ Identifier none = (Identifier) returnNoExpr.getReturnExpression();
+ assertEquals("None", none.getName());
+ assertLocation(
+ returnNoExpr.getLocation().getStartOffset(),
+ returnNoExpr.getLocation().getEndOffset(),
+ none.getLocation());
+ }
+ }
@Test
public void testForLoopBadSyntax() throws Exception {