blob: 784b0a79267c1778f0925db0f417d966c8b6295d [file] [log] [blame]
Damien Martin-Guillerezf88f4d82015-09-25 13:56:55 +00001// Copyright 2014 The Bazel Authors. All rights reserved.
Ulf Adams89f012d2015-02-26 13:39:28 +00002//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14package com.google.devtools.build.lib.syntax;
15
16import static com.google.common.truth.Truth.assertThat;
17import static com.google.common.truth.Truth.assertWithMessage;
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000018import static org.junit.Assert.fail;
Ulf Adams89f012d2015-02-26 13:39:28 +000019
Francois-Rene Rideau4feb1602015-03-18 19:49:13 +000020import com.google.common.collect.ImmutableList;
John Field1ea7fc32015-12-22 19:37:19 +000021import com.google.devtools.build.lib.cmdline.Label;
Ulf Adams89f012d2015-02-26 13:39:28 +000022import com.google.devtools.build.lib.events.Location;
23import com.google.devtools.build.lib.syntax.DictionaryLiteral.DictionaryEntryLiteral;
Miguel Alcon Pinto927f3b22016-08-22 14:21:30 +000024import com.google.devtools.build.lib.syntax.SkylarkImports.SkylarkImportSyntaxException;
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +000025import com.google.devtools.build.lib.syntax.util.EvaluationTestCase;
John Field1ea7fc32015-12-22 19:37:19 +000026import com.google.devtools.build.lib.vfs.PathFragment;
Vladimir Moskva8d610c62016-09-15 14:36:41 +000027import java.util.LinkedList;
28import java.util.List;
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000029import org.junit.Test;
30import org.junit.runner.RunWith;
31import org.junit.runners.JUnit4;
32
Ulf Adams89f012d2015-02-26 13:39:28 +000033/**
34 * Tests of parser behaviour.
Ulf Adams89f012d2015-02-26 13:39:28 +000035 */
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000036@RunWith(JUnit4.class)
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +000037public class ParserTest extends EvaluationTestCase {
38
Laurent Le Brun8e965b82016-08-03 11:50:24 +000039 private BuildFileAST parseFileWithComments(String... input) {
Laurent Le Brun2c52dab2016-11-23 16:50:23 +000040 return BuildFileAST.parseBuildString(getEventHandler(), input);
Francois-Rene Rideau5a94e592015-09-04 19:13:47 +000041 }
42
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +000043 /** Parses build code (not Skylark) */
44 @Override
45 protected List<Statement> parseFile(String... input) {
Laurent Le Brun8e965b82016-08-03 11:50:24 +000046 return parseFileWithComments(input).getStatements();
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +000047 }
48
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +000049 /** Parses Skylark code */
50 private List<Statement> parseFileForSkylark(String... input) {
Laurent Le Brun2c52dab2016-11-23 16:50:23 +000051 BuildFileAST ast = BuildFileAST.parseSkylarkString(getEventHandler(), input);
laurentlbbde7c412017-06-12 15:22:37 +020052 ast = ast.validate(env, getEventHandler());
Laurent Le Brun2c52dab2016-11-23 16:50:23 +000053 return ast.getStatements();
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +000054 }
Ulf Adams89f012d2015-02-26 13:39:28 +000055
56 private static String getText(String text, ASTNode node) {
57 return text.substring(node.getLocation().getStartOffset(),
58 node.getLocation().getEndOffset());
59 }
60
brandjonf2ed8582017-06-27 15:05:35 +020061 private void assertLocation(int start, int end, Location location)
62 throws Exception {
63 int actualStart = location.getStartOffset();
64 int actualEnd = location.getEndOffset();
65
66 if (actualStart != start || actualEnd != end) {
67 fail("Expected location = [" + start + ", " + end + "), found ["
68 + actualStart + ", " + actualEnd + ")");
69 }
70 }
71
Ulf Adams89f012d2015-02-26 13:39:28 +000072 // helper func for testListLiterals:
73 private static int getIntElem(DictionaryEntryLiteral entry, boolean key) {
74 return ((IntegerLiteral) (key ? entry.getKey() : entry.getValue())).getValue();
75 }
76
77 // helper func for testListLiterals:
78 private static DictionaryEntryLiteral getElem(DictionaryLiteral list, int index) {
79 return list.getEntries().get(index);
80 }
81
82 // helper func for testListLiterals:
83 private static int getIntElem(ListLiteral list, int index) {
84 return ((IntegerLiteral) list.getElements().get(index)).getValue();
85 }
86
87 // helper func for testListLiterals:
88 private static Expression getElem(ListLiteral list, int index) {
89 return list.getElements().get(index);
90 }
91
92 // helper func for testing arguments:
93 private static Expression getArg(FuncallExpression f, int index) {
94 return f.getArguments().get(index).getValue();
95 }
96
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +000097 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +000098 public void testPrecedence1() throws Exception {
99 BinaryOperatorExpression e =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000100 (BinaryOperatorExpression) parseExpression("'%sx' % 'foo' + 'bar'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000101
lberkiaea56b32017-05-30 12:35:33 +0200102 assertThat(e.getOperator()).isEqualTo(Operator.PLUS);
Ulf Adams89f012d2015-02-26 13:39:28 +0000103 }
104
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000105 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000106 public void testPrecedence2() throws Exception {
107 BinaryOperatorExpression e =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000108 (BinaryOperatorExpression) parseExpression("('%sx' % 'foo') + 'bar'");
lberkiaea56b32017-05-30 12:35:33 +0200109 assertThat(e.getOperator()).isEqualTo(Operator.PLUS);
Ulf Adams89f012d2015-02-26 13:39:28 +0000110 }
111
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000112 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000113 public void testPrecedence3() throws Exception {
114 BinaryOperatorExpression e =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000115 (BinaryOperatorExpression) parseExpression("'%sx' % ('foo' + 'bar')");
lberkiaea56b32017-05-30 12:35:33 +0200116 assertThat(e.getOperator()).isEqualTo(Operator.PERCENT);
Ulf Adams89f012d2015-02-26 13:39:28 +0000117 }
118
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000119 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000120 public void testPrecedence4() throws Exception {
121 BinaryOperatorExpression e =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000122 (BinaryOperatorExpression) parseExpression("1 + - (2 - 3)");
lberkiaea56b32017-05-30 12:35:33 +0200123 assertThat(e.getOperator()).isEqualTo(Operator.PLUS);
Ulf Adams89f012d2015-02-26 13:39:28 +0000124 }
125
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000126 @Test
Laurent Le Brun7bda87e2015-08-24 15:13:53 +0000127 public void testPrecedence5() throws Exception {
128 BinaryOperatorExpression e =
129 (BinaryOperatorExpression) parseExpression("2 * x | y + 1");
lberkiaea56b32017-05-30 12:35:33 +0200130 assertThat(e.getOperator()).isEqualTo(Operator.PIPE);
Laurent Le Brun7bda87e2015-08-24 15:13:53 +0000131 }
132
133 @Test
laurentlb1fcea382017-06-19 16:02:42 +0200134 public void testNonAssociativeOperators() throws Exception {
135 setFailFast(false);
136
137 parseExpression("0 < 2 < 4");
138 assertContainsError("Operator '<' is not associative with operator '<'");
139 clearEvents();
140
141 parseExpression("0 == 2 < 4");
142 assertContainsError("Operator '==' is not associative with operator '<'");
143 clearEvents();
144
145 parseExpression("1 in [1, 2] == True");
146 assertContainsError("Operator 'in' is not associative with operator '=='");
147 clearEvents();
148
149 parseExpression("1 >= 2 <= 3");
150 assertContainsError("Operator '>=' is not associative with operator '<='");
151 clearEvents();
152 }
153
154 @Test
155 public void testNonAssociativeOperatorsWithParens() throws Exception {
156 parseExpression("(0 < 2) < 4");
157 parseExpression("(0 == 2) < 4");
158 parseExpression("(1 in [1, 2]) == True");
159 parseExpression("1 >= (2 <= 3)");
160 }
161
162 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000163 public void testUnaryMinusExpr() throws Exception {
brandjonf2ed8582017-06-27 15:05:35 +0200164 UnaryOperatorExpression e = (UnaryOperatorExpression) parseExpression("-5");
165 UnaryOperatorExpression e2 = (UnaryOperatorExpression) parseExpression("- 5");
Ulf Adams89f012d2015-02-26 13:39:28 +0000166
brandjonf2ed8582017-06-27 15:05:35 +0200167 IntegerLiteral i = (IntegerLiteral) e.getOperand();
168 assertThat(i.getValue()).isEqualTo(5);
169 IntegerLiteral i2 = (IntegerLiteral) e2.getOperand();
170 assertThat(i2.getValue()).isEqualTo(5);
171 assertLocation(0, 2, e.getLocation());
172 assertLocation(0, 3, e2.getLocation());
Ulf Adams89f012d2015-02-26 13:39:28 +0000173 }
174
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000175 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000176 public void testFuncallExpr() throws Exception {
fzaisere0f13332017-08-14 12:00:51 +0200177 FuncallExpression e = (FuncallExpression) parseExpression("foo[0](1, 2, bar=wiz)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000178
fzaisere0f13332017-08-14 12:00:51 +0200179 IndexExpression function = (IndexExpression) e.getFunction();
180 Identifier functionList = (Identifier) function.getObject();
181 assertThat(functionList.getName()).isEqualTo("foo");
182 IntegerLiteral listIndex = (IntegerLiteral) function.getKey();
183 assertThat(listIndex.getValue()).isEqualTo(0);
Ulf Adams89f012d2015-02-26 13:39:28 +0000184
185 assertThat(e.getArguments()).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200186 assertThat(e.getNumPositionalArguments()).isEqualTo(2);
Ulf Adams89f012d2015-02-26 13:39:28 +0000187
188 IntegerLiteral arg0 = (IntegerLiteral) e.getArguments().get(0).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200189 assertThat((int) arg0.getValue()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000190
191 IntegerLiteral arg1 = (IntegerLiteral) e.getArguments().get(1).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200192 assertThat((int) arg1.getValue()).isEqualTo(2);
Ulf Adams89f012d2015-02-26 13:39:28 +0000193
194 Argument.Passed arg2 = e.getArguments().get(2);
lberkiaea56b32017-05-30 12:35:33 +0200195 assertThat(arg2.getName()).isEqualTo("bar");
Florian Weikert6f864c32015-07-23 11:26:39 +0000196 Identifier arg2val = (Identifier) arg2.getValue();
lberkiaea56b32017-05-30 12:35:33 +0200197 assertThat(arg2val.getName()).isEqualTo("wiz");
Ulf Adams89f012d2015-02-26 13:39:28 +0000198 }
199
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000200 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000201 public void testMethCallExpr() throws Exception {
202 FuncallExpression e =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000203 (FuncallExpression) parseExpression("foo.foo(1, 2, bar=wiz)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000204
fzaiser8c27a892017-08-11 17:26:44 +0200205 DotExpression dotExpression = (DotExpression) e.getFunction();
206 assertThat(dotExpression.getField().getName()).isEqualTo("foo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000207
208 assertThat(e.getArguments()).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200209 assertThat(e.getNumPositionalArguments()).isEqualTo(2);
Ulf Adams89f012d2015-02-26 13:39:28 +0000210
211 IntegerLiteral arg0 = (IntegerLiteral) e.getArguments().get(0).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200212 assertThat((int) arg0.getValue()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000213
214 IntegerLiteral arg1 = (IntegerLiteral) e.getArguments().get(1).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200215 assertThat((int) arg1.getValue()).isEqualTo(2);
Ulf Adams89f012d2015-02-26 13:39:28 +0000216
217 Argument.Passed arg2 = e.getArguments().get(2);
lberkiaea56b32017-05-30 12:35:33 +0200218 assertThat(arg2.getName()).isEqualTo("bar");
Florian Weikert6f864c32015-07-23 11:26:39 +0000219 Identifier arg2val = (Identifier) arg2.getValue();
lberkiaea56b32017-05-30 12:35:33 +0200220 assertThat(arg2val.getName()).isEqualTo("wiz");
Ulf Adams89f012d2015-02-26 13:39:28 +0000221 }
222
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000223 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000224 public void testChainedMethCallExpr() throws Exception {
225 FuncallExpression e =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000226 (FuncallExpression) parseExpression("foo.replace().split(1)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000227
fzaiser8c27a892017-08-11 17:26:44 +0200228 DotExpression dotExpr = (DotExpression) e.getFunction();
229 assertThat(dotExpr.getField().getName()).isEqualTo("split");
Ulf Adams89f012d2015-02-26 13:39:28 +0000230
231 assertThat(e.getArguments()).hasSize(1);
lberkiaea56b32017-05-30 12:35:33 +0200232 assertThat(e.getNumPositionalArguments()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000233
234 IntegerLiteral arg0 = (IntegerLiteral) e.getArguments().get(0).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200235 assertThat((int) arg0.getValue()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000236 }
237
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000238 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000239 public void testPropRefExpr() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000240 DotExpression e = (DotExpression) parseExpression("foo.foo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000241
Florian Weikert6f864c32015-07-23 11:26:39 +0000242 Identifier ident = e.getField();
lberkiaea56b32017-05-30 12:35:33 +0200243 assertThat(ident.getName()).isEqualTo("foo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000244 }
245
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000246 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000247 public void testStringMethExpr() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000248 FuncallExpression e = (FuncallExpression) parseExpression("'foo'.foo()");
Ulf Adams89f012d2015-02-26 13:39:28 +0000249
fzaiser8c27a892017-08-11 17:26:44 +0200250 DotExpression dotExpression = (DotExpression) e.getFunction();
251 assertThat(dotExpression.getField().getName()).isEqualTo("foo");
Ulf Adams89f012d2015-02-26 13:39:28 +0000252
253 assertThat(e.getArguments()).isEmpty();
254 }
255
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000256 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000257 public void testStringLiteralOptimizationValue() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000258 StringLiteral l = (StringLiteral) parseExpression("'abc' + 'def'");
lberkiaea56b32017-05-30 12:35:33 +0200259 assertThat(l.value).isEqualTo("abcdef");
Ulf Adams89f012d2015-02-26 13:39:28 +0000260 }
261
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000262 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000263 public void testStringLiteralOptimizationToString() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000264 StringLiteral l = (StringLiteral) parseExpression("'abc' + 'def'");
lberkiaea56b32017-05-30 12:35:33 +0200265 assertThat(l.toString()).isEqualTo("\"abcdef\"");
Ulf Adams89f012d2015-02-26 13:39:28 +0000266 }
267
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000268 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000269 public void testStringLiteralOptimizationLocation() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000270 StringLiteral l = (StringLiteral) parseExpression("'abc' + 'def'");
lberkiaea56b32017-05-30 12:35:33 +0200271 assertThat(l.getLocation().getStartOffset()).isEqualTo(0);
272 assertThat(l.getLocation().getEndOffset()).isEqualTo(13);
Ulf Adams89f012d2015-02-26 13:39:28 +0000273 }
274
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000275 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000276 public void testStringLiteralOptimizationDifferentQuote() throws Exception {
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +0000277 StringLiteral l = (StringLiteral) parseExpression("'abc' + \"def\"");
lberkiaea56b32017-05-30 12:35:33 +0200278 assertThat(l.getLocation().getStartOffset()).isEqualTo(0);
279 assertThat(l.getLocation().getEndOffset()).isEqualTo(13);
Ulf Adams89f012d2015-02-26 13:39:28 +0000280 }
281
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000282 @Test
brandjonf2ed8582017-06-27 15:05:35 +0200283 public void testIndex() throws Exception {
284 IndexExpression e = (IndexExpression) parseExpression("a[i]");
285 assertThat(e.getObject().toString()).isEqualTo("a");
286 assertThat(e.getKey().toString()).isEqualTo("i");
287 assertLocation(0, 4, e.getLocation());
288 }
289
290 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000291 public void testSubstring() throws Exception {
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000292 SliceExpression s = (SliceExpression) parseExpression("'FOO.CC'[:].lower()[1:]");
laurentlbf2854bd2017-08-16 12:43:15 +0200293 assertThat(((IntegerLiteral) s.getStart()).getValue()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000294
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000295 FuncallExpression e = (FuncallExpression) parseExpression(
296 "'FOO.CC'.lower()[1:].startswith('oo')");
fzaiser8c27a892017-08-11 17:26:44 +0200297 DotExpression dotExpression = (DotExpression) e.getFunction();
298 assertThat(dotExpression.getField().getName()).isEqualTo("startswith");
Ulf Adams89f012d2015-02-26 13:39:28 +0000299 assertThat(e.getArguments()).hasSize(1);
300
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000301 s = (SliceExpression) parseExpression("'FOO.CC'[1:][:2]");
laurentlbf2854bd2017-08-16 12:43:15 +0200302 assertThat(((IntegerLiteral) s.getEnd()).getValue()).isEqualTo(2);
Florian Weikerte3421962015-12-17 12:46:08 +0000303 }
304
305 @Test
306 public void testSlice() throws Exception {
307 evalSlice("'0123'[:]", Runtime.NONE, Runtime.NONE, 1);
308 evalSlice("'0123'[1:]", 1, Runtime.NONE, 1);
309 evalSlice("'0123'[:3]", Runtime.NONE, 3, 1);
310 evalSlice("'0123'[::]", Runtime.NONE, Runtime.NONE, 1);
311 evalSlice("'0123'[1::]", 1, Runtime.NONE, 1);
312 evalSlice("'0123'[:3:]", Runtime.NONE, 3, 1);
313 evalSlice("'0123'[::-1]", Runtime.NONE, Runtime.NONE, -1);
314 evalSlice("'0123'[1:3:]", 1, 3, 1);
315 evalSlice("'0123'[1::-1]", 1, Runtime.NONE, -1);
316 evalSlice("'0123'[:3:-1]", Runtime.NONE, 3, -1);
317 evalSlice("'0123'[1:3:-1]", 1, 3, -1);
brandjonf2ed8582017-06-27 15:05:35 +0200318
319 Expression slice = parseExpression("'0123'[1:3:-1]");
320 assertLocation(0, 14, slice.getLocation());
Florian Weikerte3421962015-12-17 12:46:08 +0000321 }
322
323 private void evalSlice(String statement, Object... expectedArgs) {
Vladimir Moskva8d610c62016-09-15 14:36:41 +0000324 SliceExpression e = (SliceExpression) parseExpression(statement);
325
326 // There is no way to evaluate the expression here, so we rely on string comparison.
brandjonf2ed8582017-06-27 15:05:35 +0200327 assertThat(e.getStart().toString()).isEqualTo(expectedArgs[0].toString());
328 assertThat(e.getEnd().toString()).isEqualTo(expectedArgs[1].toString());
329 assertThat(e.getStep().toString()).isEqualTo(expectedArgs[2].toString());
Ulf Adams89f012d2015-02-26 13:39:28 +0000330 }
331
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000332 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000333 public void testErrorRecovery() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000334 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000335
Laurent Le Brun443aaae2015-04-21 19:49:49 +0000336 String expr = "f(1, [x for foo foo foo foo], 3)";
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000337 FuncallExpression e = (FuncallExpression) parseExpression(expr);
Ulf Adams89f012d2015-02-26 13:39:28 +0000338
Ulf Adamsc708f962015-10-22 12:02:28 +0000339 assertContainsError("syntax error at 'foo'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000340
341 // Test that the actual parameters are: (1, $error$, 3):
342
fzaiser8c27a892017-08-11 17:26:44 +0200343 Identifier ident = (Identifier) e.getFunction();
lberkiaea56b32017-05-30 12:35:33 +0200344 assertThat(ident.getName()).isEqualTo("f");
Ulf Adams89f012d2015-02-26 13:39:28 +0000345
346 assertThat(e.getArguments()).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200347 assertThat(e.getNumPositionalArguments()).isEqualTo(3);
Ulf Adams89f012d2015-02-26 13:39:28 +0000348
349 IntegerLiteral arg0 = (IntegerLiteral) e.getArguments().get(0).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200350 assertThat((int) arg0.getValue()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000351
352 Argument.Passed arg1 = e.getArguments().get(1);
Florian Weikert6f864c32015-07-23 11:26:39 +0000353 Identifier arg1val = ((Identifier) arg1.getValue());
lberkiaea56b32017-05-30 12:35:33 +0200354 assertThat(arg1val.getName()).isEqualTo("$error$");
Ulf Adams89f012d2015-02-26 13:39:28 +0000355
Laurent Le Brun443aaae2015-04-21 19:49:49 +0000356 assertLocation(5, 29, arg1val.getLocation());
lberkiaea56b32017-05-30 12:35:33 +0200357 assertThat(expr.substring(5, 28)).isEqualTo("[x for foo foo foo foo]");
358 assertThat(arg1val.getLocation().getEndLineAndColumn().getColumn()).isEqualTo(30);
Ulf Adams89f012d2015-02-26 13:39:28 +0000359
360 IntegerLiteral arg2 = (IntegerLiteral) e.getArguments().get(2).getValue();
lberkiaea56b32017-05-30 12:35:33 +0200361 assertThat((int) arg2.getValue()).isEqualTo(3);
Ulf Adams89f012d2015-02-26 13:39:28 +0000362 }
363
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000364 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000365 public void testDoesntGetStuck() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000366 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000367
368 // Make sure the parser does not get stuck when trying
369 // to parse an expression containing a syntax error.
370 // This usually results in OutOfMemoryError because the
371 // parser keeps filling up the error log.
372 // We need to make sure that we will always advance
373 // in the token stream.
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000374 parseExpression("f(1, ], 3)");
375 parseExpression("f(1, ), 3)");
376 parseExpression("[ ) for v in 3)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000377
Ulf Adamsc708f962015-10-22 12:02:28 +0000378 assertContainsError(""); // "" matches any, i.e., there were some events
Ulf Adams89f012d2015-02-26 13:39:28 +0000379 }
380
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000381 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000382 public void testSecondaryLocation() {
383 String expr = "f(1 % 2)";
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000384 FuncallExpression call = (FuncallExpression) parseExpression(expr);
Ulf Adams89f012d2015-02-26 13:39:28 +0000385 Argument.Passed arg = call.getArguments().get(0);
Francois-Rene Rideauc673a822015-03-02 19:52:39 +0000386 assertThat(arg.getLocation().getEndOffset()).isLessThan(call.getLocation().getEndOffset());
Ulf Adams89f012d2015-02-26 13:39:28 +0000387 }
388
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000389 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000390 public void testPrimaryLocation() {
391 String expr = "f(1 + 2)";
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000392 FuncallExpression call = (FuncallExpression) parseExpression(expr);
Ulf Adams89f012d2015-02-26 13:39:28 +0000393 Argument.Passed arg = call.getArguments().get(0);
Francois-Rene Rideauc673a822015-03-02 19:52:39 +0000394 assertThat(arg.getLocation().getEndOffset()).isLessThan(call.getLocation().getEndOffset());
Ulf Adams89f012d2015-02-26 13:39:28 +0000395 }
396
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000397 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000398 public void testAssignLocation() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000399 List<Statement> statements = parseFile("a = b;c = d\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000400 Statement statement = statements.get(0);
lberkiaea56b32017-05-30 12:35:33 +0200401 assertThat(statement.getLocation().getEndOffset()).isEqualTo(5);
Ulf Adams89f012d2015-02-26 13:39:28 +0000402 }
403
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000404 @Test
Laurent Le Brunc9041bf2015-03-23 15:34:12 +0000405 public void testAssignKeyword() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000406 setFailFast(false);
407 parseExpression("with = 4");
Ulf Adamsc708f962015-10-22 12:02:28 +0000408 assertContainsError("keyword 'with' not supported");
409 assertContainsError("syntax error at 'with': expected expression");
Laurent Le Brun0ddcba22015-03-23 16:48:01 +0000410 }
411
412 @Test
Laurent Le Brunee991a12015-06-16 10:56:46 +0000413 public void testBreak() {
414 setFailFast(false);
415 parseExpression("break");
Ulf Adamsc708f962015-10-22 12:02:28 +0000416 assertContainsError("syntax error at 'break': expected expression");
Laurent Le Brunee991a12015-06-16 10:56:46 +0000417 }
418
419 @Test
Laurent Le Brun0ddcba22015-03-23 16:48:01 +0000420 public void testTry() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000421 setFailFast(false);
422 parseExpression("try: 1 + 1");
Ulf Adamsc708f962015-10-22 12:02:28 +0000423 assertContainsError("'try' not supported, all exceptions are fatal");
424 assertContainsError("syntax error at 'try': expected expression");
Laurent Le Brunc9041bf2015-03-23 15:34:12 +0000425 }
426
427 @Test
Laurent Le Brun44ad7fa2016-10-11 12:09:05 +0000428 public void testDel() {
429 setFailFast(false);
430 parseExpression("del d['a']");
431 assertContainsError("'del' not supported, use '.pop()' to delete");
432 }
433
434 @Test
Laurent Le Brun56093892015-03-20 13:01:58 +0000435 public void testTupleAssign() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000436 List<Statement> statements = parseFile("list[0] = 5; dict['key'] = value\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000437 assertThat(statements).hasSize(2);
Laurent Le Brun56093892015-03-20 13:01:58 +0000438 assertThat(statements.get(0)).isInstanceOf(AssignmentStatement.class);
439 assertThat(statements.get(1)).isInstanceOf(AssignmentStatement.class);
440 }
441
442 @Test
443 public void testAssign() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000444 List<Statement> statements = parseFile("a, b = 5\n");
Laurent Le Brun56093892015-03-20 13:01:58 +0000445 assertThat(statements).hasSize(1);
446 assertThat(statements.get(0)).isInstanceOf(AssignmentStatement.class);
447 AssignmentStatement assign = (AssignmentStatement) statements.get(0);
448 assertThat(assign.getLValue().getExpression()).isInstanceOf(ListLiteral.class);
Ulf Adams89f012d2015-02-26 13:39:28 +0000449 }
450
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000451 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000452 public void testInvalidAssign() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000453 setFailFast(false);
454 parseExpression("1 + (b = c)");
Ulf Adamsc708f962015-10-22 12:02:28 +0000455 assertContainsError("syntax error");
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000456 clearEvents();
Ulf Adams89f012d2015-02-26 13:39:28 +0000457 }
458
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000459 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000460 public void testAugmentedAssign() throws Exception {
lberkiaea56b32017-05-30 12:35:33 +0200461 assertThat(parseFile("x += 1").toString()).isEqualTo("[x += 1\n]");
462 assertThat(parseFile("x -= 1").toString()).isEqualTo("[x -= 1\n]");
463 assertThat(parseFile("x *= 1").toString()).isEqualTo("[x *= 1\n]");
464 assertThat(parseFile("x /= 1").toString()).isEqualTo("[x /= 1\n]");
465 assertThat(parseFile("x %= 1").toString()).isEqualTo("[x %= 1\n]");
Ulf Adams89f012d2015-02-26 13:39:28 +0000466 }
467
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000468 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000469 public void testPrettyPrintFunctions() throws Exception {
lberkiaea56b32017-05-30 12:35:33 +0200470 assertThat(parseFile("x[1:3]").toString()).isEqualTo("[x[1:3]\n]");
471 assertThat(parseFile("x[1:3:1]").toString()).isEqualTo("[x[1:3]\n]");
472 assertThat(parseFile("x[1:3:2]").toString()).isEqualTo("[x[1:3:2]\n]");
473 assertThat(parseFile("x[1::2]").toString()).isEqualTo("[x[1::2]\n]");
474 assertThat(parseFile("x[1:]").toString()).isEqualTo("[x[1:]\n]");
475 assertThat(parseFile("str[42]").toString()).isEqualTo("[str[42]\n]");
dslomov2e84e7c2017-06-27 14:38:45 +0200476 assertThat(parseFile("ctx.actions.declare_file('hello')").toString())
477 .isEqualTo("[ctx.actions.declare_file(\"hello\")\n]");
lberkiaea56b32017-05-30 12:35:33 +0200478 assertThat(parseFile("new_file(\"hello\")").toString()).isEqualTo("[new_file(\"hello\")\n]");
Ulf Adams89f012d2015-02-26 13:39:28 +0000479 }
480
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000481 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000482 public void testFuncallLocation() {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000483 List<Statement> statements = parseFile("a(b);c = d\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000484 Statement statement = statements.get(0);
lberkiaea56b32017-05-30 12:35:33 +0200485 assertThat(statement.getLocation().getEndOffset()).isEqualTo(4);
Ulf Adams89f012d2015-02-26 13:39:28 +0000486 }
487
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000488 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000489 public void testListPositions() throws Exception {
490 String expr = "[0,f(1),2]";
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000491 ListLiteral list = (ListLiteral) parseExpression(expr);
lberkiaea56b32017-05-30 12:35:33 +0200492 assertThat(getText(expr, list)).isEqualTo("[0,f(1),2]");
493 assertThat(getText(expr, getElem(list, 0))).isEqualTo("0");
494 assertThat(getText(expr, getElem(list, 1))).isEqualTo("f(1)");
495 assertThat(getText(expr, getElem(list, 2))).isEqualTo("2");
Ulf Adams89f012d2015-02-26 13:39:28 +0000496 }
497
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000498 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000499 public void testDictPositions() throws Exception {
500 String expr = "{1:2,2:f(1),3:4}";
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000501 DictionaryLiteral list = (DictionaryLiteral) parseExpression(expr);
lberkiaea56b32017-05-30 12:35:33 +0200502 assertThat(getText(expr, list)).isEqualTo("{1:2,2:f(1),3:4}");
503 assertThat(getText(expr, getElem(list, 0))).isEqualTo("1:2");
504 assertThat(getText(expr, getElem(list, 1))).isEqualTo("2:f(1)");
505 assertThat(getText(expr, getElem(list, 2))).isEqualTo("3:4");
Ulf Adams89f012d2015-02-26 13:39:28 +0000506 }
507
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000508 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000509 public void testArgumentPositions() throws Exception {
510 String stmt = "f(0,g(1,2),2)";
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000511 FuncallExpression f = (FuncallExpression) parseExpression(stmt);
lberkiaea56b32017-05-30 12:35:33 +0200512 assertThat(getText(stmt, f)).isEqualTo(stmt);
513 assertThat(getText(stmt, getArg(f, 0))).isEqualTo("0");
514 assertThat(getText(stmt, getArg(f, 1))).isEqualTo("g(1,2)");
515 assertThat(getText(stmt, getArg(f, 2))).isEqualTo("2");
Ulf Adams89f012d2015-02-26 13:39:28 +0000516 }
517
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000518 @Test
Laurent Le Brund412c8f2015-06-16 11:12:54 +0000519 public void testForBreakContinue() throws Exception {
520 List<Statement> file = parseFileForSkylark(
521 "def foo():",
522 " for i in [1, 2]:",
523 " break",
Laurent Le Brun7d6a3812015-10-26 12:07:12 +0000524 " continue",
525 " break");
Laurent Le Brund412c8f2015-06-16 11:12:54 +0000526 assertThat(file).hasSize(1);
527 List<Statement> body = ((FunctionDefStatement) file.get(0)).getStatements();
528 assertThat(body).hasSize(1);
529
brandjon990622b2017-07-11 19:56:45 +0200530 List<Statement> loop = ((ForStatement) body.get(0)).getBlock();
Laurent Le Brun7d6a3812015-10-26 12:07:12 +0000531 assertThat(loop).hasSize(3);
Laurent Le Brund412c8f2015-06-16 11:12:54 +0000532
Laurent Le Brun7d6a3812015-10-26 12:07:12 +0000533 assertThat(((FlowStatement) loop.get(0)).getKind()).isEqualTo(FlowStatement.Kind.BREAK);
Laurent Le Bruna3c25a62016-10-26 10:59:09 +0000534 assertLocation(34, 39, loop.get(0).getLocation());
Laurent Le Brund412c8f2015-06-16 11:12:54 +0000535
Laurent Le Brun7d6a3812015-10-26 12:07:12 +0000536 assertThat(((FlowStatement) loop.get(1)).getKind()).isEqualTo(FlowStatement.Kind.CONTINUE);
Laurent Le Bruna3c25a62016-10-26 10:59:09 +0000537 assertLocation(44, 52, loop.get(1).getLocation());
Laurent Le Brun7d6a3812015-10-26 12:07:12 +0000538
539 assertThat(((FlowStatement) loop.get(2)).getKind()).isEqualTo(FlowStatement.Kind.BREAK);
540 assertLocation(57, 62, loop.get(2).getLocation());
Laurent Le Brund412c8f2015-06-16 11:12:54 +0000541 }
542
543 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000544 public void testListLiterals1() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000545 ListLiteral list = (ListLiteral) parseExpression("[0,1,2]");
lberkiaea56b32017-05-30 12:35:33 +0200546 assertThat(list.isTuple()).isFalse();
Ulf Adams89f012d2015-02-26 13:39:28 +0000547 assertThat(list.getElements()).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200548 assertThat(list.isTuple()).isFalse();
Ulf Adams89f012d2015-02-26 13:39:28 +0000549 for (int i = 0; i < 3; ++i) {
lberkiaea56b32017-05-30 12:35:33 +0200550 assertThat(getIntElem(list, i)).isEqualTo(i);
Ulf Adams89f012d2015-02-26 13:39:28 +0000551 }
552 }
553
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000554 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000555 public void testTupleLiterals2() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000556 ListLiteral tuple = (ListLiteral) parseExpression("(0,1,2)");
lberkiaea56b32017-05-30 12:35:33 +0200557 assertThat(tuple.isTuple()).isTrue();
Ulf Adams89f012d2015-02-26 13:39:28 +0000558 assertThat(tuple.getElements()).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200559 assertThat(tuple.isTuple()).isTrue();
Ulf Adams89f012d2015-02-26 13:39:28 +0000560 for (int i = 0; i < 3; ++i) {
lberkiaea56b32017-05-30 12:35:33 +0200561 assertThat(getIntElem(tuple, i)).isEqualTo(i);
Ulf Adams89f012d2015-02-26 13:39:28 +0000562 }
563 }
564
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000565 @Test
Laurent Le Brun56093892015-03-20 13:01:58 +0000566 public void testTupleWithoutParens() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000567 ListLiteral tuple = (ListLiteral) parseExpression("0, 1, 2");
lberkiaea56b32017-05-30 12:35:33 +0200568 assertThat(tuple.isTuple()).isTrue();
Laurent Le Brun56093892015-03-20 13:01:58 +0000569 assertThat(tuple.getElements()).hasSize(3);
lberkiaea56b32017-05-30 12:35:33 +0200570 assertThat(tuple.isTuple()).isTrue();
Laurent Le Brun56093892015-03-20 13:01:58 +0000571 for (int i = 0; i < 3; ++i) {
lberkiaea56b32017-05-30 12:35:33 +0200572 assertThat(getIntElem(tuple, i)).isEqualTo(i);
Laurent Le Brun56093892015-03-20 13:01:58 +0000573 }
574 }
575
576 @Test
Laurent Le Brunb639ca82017-01-17 11:18:23 +0000577 public void testTupleWithTrailingComma() throws Exception {
578 setFailFast(false);
579
580 // Unlike Python, we require parens here.
581 parseExpression("0, 1, 2, 3,");
582 assertContainsError("Trailing comma");
583 clearEvents();
584
585 parseExpression("1 + 2,");
586 assertContainsError("Trailing comma");
587 clearEvents();
588
589 ListLiteral tuple = (ListLiteral) parseExpression("(0, 1, 2, 3,)");
lberkiaea56b32017-05-30 12:35:33 +0200590 assertThat(tuple.isTuple()).isTrue();
Laurent Le Brun56093892015-03-20 13:01:58 +0000591 assertThat(tuple.getElements()).hasSize(4);
lberkiaea56b32017-05-30 12:35:33 +0200592 assertThat(tuple.isTuple()).isTrue();
Laurent Le Brun56093892015-03-20 13:01:58 +0000593 for (int i = 0; i < 4; ++i) {
lberkiaea56b32017-05-30 12:35:33 +0200594 assertThat(getIntElem(tuple, i)).isEqualTo(i);
Laurent Le Brun56093892015-03-20 13:01:58 +0000595 }
596 }
597
598 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000599 public void testTupleLiterals3() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000600 ListLiteral emptyTuple = (ListLiteral) parseExpression("()");
lberkiaea56b32017-05-30 12:35:33 +0200601 assertThat(emptyTuple.isTuple()).isTrue();
Ulf Adams89f012d2015-02-26 13:39:28 +0000602 assertThat(emptyTuple.getElements()).isEmpty();
603 }
604
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000605 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000606 public void testTupleLiterals4() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000607 ListLiteral singletonTuple = (ListLiteral) parseExpression("(42,)");
lberkiaea56b32017-05-30 12:35:33 +0200608 assertThat(singletonTuple.isTuple()).isTrue();
Ulf Adams89f012d2015-02-26 13:39:28 +0000609 assertThat(singletonTuple.getElements()).hasSize(1);
lberkiaea56b32017-05-30 12:35:33 +0200610 assertThat(getIntElem(singletonTuple, 0)).isEqualTo(42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000611 }
612
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000613 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000614 public void testTupleLiterals5() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000615 IntegerLiteral intLit = (IntegerLiteral) parseExpression("(42)"); // not a tuple!
lberkiaea56b32017-05-30 12:35:33 +0200616 assertThat((int) intLit.getValue()).isEqualTo(42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000617 }
618
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000619 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000620 public void testListLiterals6() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000621 ListLiteral emptyList = (ListLiteral) parseExpression("[]");
lberkiaea56b32017-05-30 12:35:33 +0200622 assertThat(emptyList.isTuple()).isFalse();
Ulf Adams89f012d2015-02-26 13:39:28 +0000623 assertThat(emptyList.getElements()).isEmpty();
624 }
625
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000626 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000627 public void testListLiterals7() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000628 ListLiteral singletonList = (ListLiteral) parseExpression("[42,]");
lberkiaea56b32017-05-30 12:35:33 +0200629 assertThat(singletonList.isTuple()).isFalse();
Ulf Adams89f012d2015-02-26 13:39:28 +0000630 assertThat(singletonList.getElements()).hasSize(1);
lberkiaea56b32017-05-30 12:35:33 +0200631 assertThat(getIntElem(singletonList, 0)).isEqualTo(42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000632 }
633
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000634 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000635 public void testListLiterals8() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000636 ListLiteral singletonList = (ListLiteral) parseExpression("[42]"); // a singleton
lberkiaea56b32017-05-30 12:35:33 +0200637 assertThat(singletonList.isTuple()).isFalse();
Ulf Adams89f012d2015-02-26 13:39:28 +0000638 assertThat(singletonList.getElements()).hasSize(1);
lberkiaea56b32017-05-30 12:35:33 +0200639 assertThat(getIntElem(singletonList, 0)).isEqualTo(42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000640 }
641
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000642 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000643 public void testDictionaryLiterals() throws Exception {
644 DictionaryLiteral dictionaryList =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000645 (DictionaryLiteral) parseExpression("{1:42}"); // a singleton dictionary
Ulf Adams89f012d2015-02-26 13:39:28 +0000646 assertThat(dictionaryList.getEntries()).hasSize(1);
647 DictionaryEntryLiteral tuple = getElem(dictionaryList, 0);
lberkiaea56b32017-05-30 12:35:33 +0200648 assertThat(getIntElem(tuple, true)).isEqualTo(1);
649 assertThat(getIntElem(tuple, false)).isEqualTo(42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000650 }
651
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000652 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000653 public void testDictionaryLiterals1() throws Exception {
654 DictionaryLiteral dictionaryList =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000655 (DictionaryLiteral) parseExpression("{}"); // an empty dictionary
Ulf Adams89f012d2015-02-26 13:39:28 +0000656 assertThat(dictionaryList.getEntries()).isEmpty();
657 }
658
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000659 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000660 public void testDictionaryLiterals2() throws Exception {
661 DictionaryLiteral dictionaryList =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000662 (DictionaryLiteral) parseExpression("{1:42,}"); // a singleton dictionary
Ulf Adams89f012d2015-02-26 13:39:28 +0000663 assertThat(dictionaryList.getEntries()).hasSize(1);
664 DictionaryEntryLiteral tuple = getElem(dictionaryList, 0);
lberkiaea56b32017-05-30 12:35:33 +0200665 assertThat(getIntElem(tuple, true)).isEqualTo(1);
666 assertThat(getIntElem(tuple, false)).isEqualTo(42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000667 }
668
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000669 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000670 public void testDictionaryLiterals3() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000671 DictionaryLiteral dictionaryList = (DictionaryLiteral) parseExpression("{1:42,2:43,3:44}");
Ulf Adams89f012d2015-02-26 13:39:28 +0000672 assertThat(dictionaryList.getEntries()).hasSize(3);
673 for (int i = 0; i < 3; i++) {
674 DictionaryEntryLiteral tuple = getElem(dictionaryList, i);
lberkiaea56b32017-05-30 12:35:33 +0200675 assertThat(getIntElem(tuple, true)).isEqualTo(i + 1);
676 assertThat(getIntElem(tuple, false)).isEqualTo(i + 42);
Ulf Adams89f012d2015-02-26 13:39:28 +0000677 }
678 }
679
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000680 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000681 public void testListLiterals9() throws Exception {
682 ListLiteral singletonList =
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000683 (ListLiteral) parseExpression("[ abi + opt_level + \'/include\' ]");
lberkiaea56b32017-05-30 12:35:33 +0200684 assertThat(singletonList.isTuple()).isFalse();
Ulf Adams89f012d2015-02-26 13:39:28 +0000685 assertThat(singletonList.getElements()).hasSize(1);
686 }
687
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000688 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000689 public void testListComprehensionSyntax() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000690 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000691
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000692 parseExpression("[x for");
Ulf Adamsc708f962015-10-22 12:02:28 +0000693 assertContainsError("syntax error at 'newline'");
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000694 clearEvents();
Ulf Adams89f012d2015-02-26 13:39:28 +0000695
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000696 parseExpression("[x for x");
Ulf Adamsc708f962015-10-22 12:02:28 +0000697 assertContainsError("syntax error at 'newline'");
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000698 clearEvents();
Ulf Adams89f012d2015-02-26 13:39:28 +0000699
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000700 parseExpression("[x for x in");
Ulf Adamsc708f962015-10-22 12:02:28 +0000701 assertContainsError("syntax error at 'newline'");
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000702 clearEvents();
Ulf Adams89f012d2015-02-26 13:39:28 +0000703
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000704 parseExpression("[x for x in []");
Ulf Adamsc708f962015-10-22 12:02:28 +0000705 assertContainsError("syntax error at 'newline'");
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000706 clearEvents();
Ulf Adams89f012d2015-02-26 13:39:28 +0000707
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000708 parseExpression("[x for x for y in ['a']]");
Ulf Adamsc708f962015-10-22 12:02:28 +0000709 assertContainsError("syntax error at 'for'");
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000710 clearEvents();
laurentlbc3a1af62017-06-16 14:37:43 +0200711
712 parseExpression("[x for x for y in 1, 2]");
713 assertContainsError("syntax error at 'for'");
714 clearEvents();
Ulf Adams89f012d2015-02-26 13:39:28 +0000715 }
716
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000717 @Test
Laurent Le Brun52021662015-05-18 09:28:26 +0000718 public void testListComprehensionEmptyList() throws Exception {
719 List<ListComprehension.Clause> clauses = ((ListComprehension) parseExpression(
720 "['foo/%s.java' % x for x in []]")).getClauses();
721 assertThat(clauses).hasSize(1);
722 assertThat(clauses.get(0).getExpression().toString()).isEqualTo("[]");
723 assertThat(clauses.get(0).getLValue().getExpression().toString()).isEqualTo("x");
724 }
725
726 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000727 public void testListComprehension() throws Exception {
Laurent Le Brun52021662015-05-18 09:28:26 +0000728 List<ListComprehension.Clause> clauses = ((ListComprehension) parseExpression(
729 "['foo/%s.java' % x for x in ['bar', 'wiz', 'quux']]")).getClauses();
730 assertThat(clauses).hasSize(1);
731 assertThat(clauses.get(0).getLValue().getExpression().toString()).isEqualTo("x");
732 assertThat(clauses.get(0).getExpression()).isInstanceOf(ListLiteral.class);
733 }
Ulf Adams89f012d2015-02-26 13:39:28 +0000734
Laurent Le Brun52021662015-05-18 09:28:26 +0000735 @Test
736 public void testForForListComprehension() throws Exception {
737 List<ListComprehension.Clause> clauses = ((ListComprehension) parseExpression(
738 "['%s/%s.java' % (x, y) for x in ['foo', 'bar'] for y in list]")).getClauses();
739 assertThat(clauses).hasSize(2);
740 assertThat(clauses.get(0).getLValue().getExpression().toString()).isEqualTo("x");
741 assertThat(clauses.get(0).getExpression()).isInstanceOf(ListLiteral.class);
742 assertThat(clauses.get(1).getLValue().getExpression().toString()).isEqualTo("y");
Florian Weikert6f864c32015-07-23 11:26:39 +0000743 assertThat(clauses.get(1).getExpression()).isInstanceOf(Identifier.class);
Ulf Adams89f012d2015-02-26 13:39:28 +0000744 }
745
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000746 @Test
Laurent Le Brun9060e162015-04-02 10:07:28 +0000747 public void testParserRecovery() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000748 setFailFast(false);
749 List<Statement> statements = parseFileForSkylark(
Laurent Le Brun9060e162015-04-02 10:07:28 +0000750 "def foo():",
Laurent Le Brune3f4ed72015-05-08 14:47:26 +0000751 " a = 2 for 4", // parse error
Laurent Le Brun9060e162015-04-02 10:07:28 +0000752 " b = [3, 4]",
753 "",
754 "d = 4 ada", // parse error
755 "",
756 "def bar():",
757 " a = [3, 4]",
758 " b = 2 + + 5", // parse error
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000759 "");
Laurent Le Brun9060e162015-04-02 10:07:28 +0000760
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000761 assertThat(getEventCollector()).hasSize(3);
Ulf Adamsc708f962015-10-22 12:02:28 +0000762 assertContainsError("syntax error at 'for': expected newline");
763 assertContainsError("syntax error at 'ada': expected newline");
764 assertContainsError("syntax error at '+': expected expression");
Laurent Le Brun9060e162015-04-02 10:07:28 +0000765 assertThat(statements).hasSize(3);
766 }
767
768 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000769 public void testParserContainsErrorsIfSyntaxException() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000770 setFailFast(false);
771 parseExpression("'foo' %%");
Ulf Adamsc708f962015-10-22 12:02:28 +0000772 assertContainsError("syntax error at '%'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000773 }
774
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000775 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000776 public void testParserDoesNotContainErrorsIfSuccess() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000777 parseExpression("'foo'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000778 }
779
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000780 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000781 public void testParserContainsErrors() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000782 setFailFast(false);
Francois-Rene Rideau89312fb2015-09-10 18:53:03 +0000783 parseFile("+");
Ulf Adamsc708f962015-10-22 12:02:28 +0000784 assertContainsError("syntax error at '+'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000785 }
786
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000787 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000788 public void testSemicolonAndNewline() throws Exception {
789 List<Statement> stmts = parseFile(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000790 "foo='bar'; foo(bar)",
791 "",
792 "foo='bar'; foo(bar)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000793 assertThat(stmts).hasSize(4);
794 }
795
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000796 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000797 public void testSemicolonAndNewline2() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000798 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000799 List<Statement> stmts = parseFile(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000800 "foo='foo' error(bar)",
801 "",
802 "");
Ulf Adamsc708f962015-10-22 12:02:28 +0000803 assertContainsError("syntax error at 'error'");
Laurent Le Brun9060e162015-04-02 10:07:28 +0000804 assertThat(stmts).hasSize(1);
Ulf Adams89f012d2015-02-26 13:39:28 +0000805 }
806
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000807 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000808 public void testExprAsStatement() throws Exception {
809 List<Statement> stmts = parseFile(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000810 "li = []",
811 "li.append('a.c')",
812 "\"\"\" string comment \"\"\"",
813 "foo(bar)");
Ulf Adams89f012d2015-02-26 13:39:28 +0000814 assertThat(stmts).hasSize(4);
815 }
816
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000817 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000818 public void testParseBuildFileWithSingeRule() throws Exception {
819 List<Statement> stmts = parseFile(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000820 "genrule(name = 'foo',",
821 " srcs = ['input.csv'],",
822 " outs = [ 'result.txt',",
823 " 'result.log'],",
824 " cmd = 'touch result.txt result.log')",
825 "");
Ulf Adams89f012d2015-02-26 13:39:28 +0000826 assertThat(stmts).hasSize(1);
827 }
828
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000829 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000830 public void testParseBuildFileWithMultipleRules() throws Exception {
831 List<Statement> stmts = parseFile(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000832 "genrule(name = 'foo',",
833 " srcs = ['input.csv'],",
834 " outs = [ 'result.txt',",
835 " 'result.log'],",
836 " cmd = 'touch result.txt result.log')",
837 "",
838 "genrule(name = 'bar',",
839 " srcs = ['input.csv'],",
840 " outs = [ 'graph.svg'],",
841 " cmd = 'touch graph.svg')");
Ulf Adams89f012d2015-02-26 13:39:28 +0000842 assertThat(stmts).hasSize(2);
843 }
844
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000845 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000846 public void testParseBuildFileWithComments() throws Exception {
Laurent Le Brun8e965b82016-08-03 11:50:24 +0000847 BuildFileAST result = parseFileWithComments(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000848 "# Test BUILD file",
849 "# with multi-line comment",
850 "",
851 "genrule(name = 'foo',",
852 " srcs = ['input.csv'],",
853 " outs = [ 'result.txt',",
854 " 'result.log'],",
855 " cmd = 'touch result.txt result.log')");
Laurent Le Brun8e965b82016-08-03 11:50:24 +0000856 assertThat(result.getStatements()).hasSize(1);
857 assertThat(result.getComments()).hasSize(2);
Ulf Adams89f012d2015-02-26 13:39:28 +0000858 }
859
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000860 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000861 public void testParseBuildFileWithManyComments() throws Exception {
Laurent Le Brun8e965b82016-08-03 11:50:24 +0000862 BuildFileAST result = parseFileWithComments(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000863 "# 1",
864 "# 2",
865 "",
866 "# 4 ",
867 "# 5",
868 "#", // 6 - find empty comment for syntax highlighting
869 "# 7 ",
870 "# 8",
871 "genrule(name = 'foo',",
872 " srcs = ['input.csv'],",
873 " # 11",
874 " outs = [ 'result.txt',",
875 " 'result.log'], # 13",
876 " cmd = 'touch result.txt result.log')",
877 "# 15");
Laurent Le Brun8e965b82016-08-03 11:50:24 +0000878 assertThat(result.getStatements()).hasSize(1); // Single genrule
Ulf Adams89f012d2015-02-26 13:39:28 +0000879 StringBuilder commentLines = new StringBuilder();
Laurent Le Brun8e965b82016-08-03 11:50:24 +0000880 for (Comment comment : result.getComments()) {
Ulf Adams89f012d2015-02-26 13:39:28 +0000881 // Comments start and end on the same line
lberkiaea56b32017-05-30 12:35:33 +0200882 assertWithMessage(
883 comment.getLocation().getStartLineAndColumn().getLine()
884 + " ends on "
885 + comment.getLocation().getEndLineAndColumn().getLine())
886 .that(comment.getLocation().getEndLineAndColumn().getLine())
887 .isEqualTo(comment.getLocation().getStartLineAndColumn().getLine());
Ulf Adams89f012d2015-02-26 13:39:28 +0000888 commentLines.append('(');
889 commentLines.append(comment.getLocation().getStartLineAndColumn().getLine());
890 commentLines.append(',');
891 commentLines.append(comment.getLocation().getStartLineAndColumn().getColumn());
892 commentLines.append(") ");
893 }
894 assertWithMessage("Found: " + commentLines)
Laurent Le Brun8e965b82016-08-03 11:50:24 +0000895 .that(result.getComments().size()).isEqualTo(10); // One per '#'
Ulf Adams89f012d2015-02-26 13:39:28 +0000896 }
897
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000898 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000899 public void testMissingComma() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000900 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000901 // Regression test.
902 // Note: missing comma after name='foo'
903 parseFile("genrule(name = 'foo'\n"
904 + " srcs = ['in'])");
Ulf Adamsc708f962015-10-22 12:02:28 +0000905 assertContainsError("syntax error at 'srcs'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000906 }
907
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000908 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000909 public void testDoubleSemicolon() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000910 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000911 // Regression test.
912 parseFile("x = 1; ; x = 2;");
Ulf Adamsc708f962015-10-22 12:02:28 +0000913 assertContainsError("syntax error at ';'");
Ulf Adams89f012d2015-02-26 13:39:28 +0000914 }
915
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000916 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000917 public void testFunctionDefinitionErrorRecovery() throws Exception {
918 // Parser skips over entire function definitions, and reports a meaningful
919 // error.
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000920 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000921 List<Statement> stmts = parseFile(
922 "x = 1;\n"
923 + "def foo(x, y, **z):\n"
924 + " # a comment\n"
925 + " x = 2\n"
926 + " foo(bar)\n"
927 + " return z\n"
928 + "x = 3");
929 assertThat(stmts).hasSize(2);
930 }
931
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000932 @Test
Laurent Le Brun5f674452015-03-17 19:29:13 +0000933 public void testDefSingleLine() throws Exception {
934 List<Statement> statements = parseFileForSkylark(
935 "def foo(): x = 1; y = 2\n");
936 FunctionDefStatement stmt = (FunctionDefStatement) statements.get(0);
937 assertThat(stmt.getStatements()).hasSize(2);
938 }
939
940 @Test
Laurent Le Brun0942ee92015-03-17 20:22:16 +0000941 public void testPass() throws Exception {
942 List<Statement> statements = parseFileForSkylark("pass\n");
943 assertThat(statements).isEmpty();
944 }
945
946 @Test
947 public void testForPass() throws Exception {
948 List<Statement> statements = parseFileForSkylark(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000949 "def foo():",
950 " pass\n");
Laurent Le Brun0942ee92015-03-17 20:22:16 +0000951
952 assertThat(statements).hasSize(1);
953 FunctionDefStatement stmt = (FunctionDefStatement) statements.get(0);
954 assertThat(stmt.getStatements()).isEmpty();
955 }
956
957 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000958 public void testSkipIfBlockFail() throws Exception {
959 // Do not parse 'if' blocks, when parsePython is not set
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000960 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +0000961 List<Statement> stmts = parseFile(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +0000962 "x = 1;",
963 "if x == 1:",
964 " x = 2",
965 "x = 3;\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000966 assertThat(stmts).hasSize(2);
Ulf Adamsc708f962015-10-22 12:02:28 +0000967 assertContainsError("This is not supported in BUILD files");
Ulf Adams89f012d2015-02-26 13:39:28 +0000968 }
969
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +0000970 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +0000971 public void testForLoopMultipleVariables() throws Exception {
Laurent Le Brun185392d2015-03-20 14:41:25 +0000972 List<Statement> stmts1 = parseFile("[ i for i, j, k in [(1, 2, 3)] ]\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000973 assertThat(stmts1).hasSize(1);
974
Laurent Le Brun185392d2015-03-20 14:41:25 +0000975 List<Statement> stmts2 = parseFile("[ i for i, j in [(1, 2, 3)] ]\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000976 assertThat(stmts2).hasSize(1);
977
Laurent Le Brun185392d2015-03-20 14:41:25 +0000978 List<Statement> stmts3 = parseFile("[ i for (i, j, k) in [(1, 2, 3)] ]\n");
Ulf Adams89f012d2015-02-26 13:39:28 +0000979 assertThat(stmts3).hasSize(1);
980 }
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000981
Googlercc0d9952015-08-10 12:01:34 +0000982 @Test
983 public void testReturnNone() throws Exception {
984 List<Statement> defNone = parseFileForSkylark("def foo():", " return None\n");
985 assertThat(defNone).hasSize(1);
986
987 List<Statement> bodyNone = ((FunctionDefStatement) defNone.get(0)).getStatements();
988 assertThat(bodyNone).hasSize(1);
989
990 ReturnStatement returnNone = (ReturnStatement) bodyNone.get(0);
lberkiaea56b32017-05-30 12:35:33 +0200991 assertThat(((Identifier) returnNone.getReturnExpression()).getName()).isEqualTo("None");
Googlercc0d9952015-08-10 12:01:34 +0000992
993 int i = 0;
994 for (String end : new String[]{";", "\n"}) {
995 List<Statement> defNoExpr = parseFileForSkylark("def bar" + i + "():", " return" + end);
996 i++;
997 assertThat(defNoExpr).hasSize(1);
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +0000998
Googlercc0d9952015-08-10 12:01:34 +0000999 List<Statement> bodyNoExpr = ((FunctionDefStatement) defNoExpr.get(0)).getStatements();
1000 assertThat(bodyNoExpr).hasSize(1);
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +00001001
Googlercc0d9952015-08-10 12:01:34 +00001002 ReturnStatement returnNoExpr = (ReturnStatement) bodyNoExpr.get(0);
1003 Identifier none = (Identifier) returnNoExpr.getReturnExpression();
lberkiaea56b32017-05-30 12:35:33 +02001004 assertThat(none.getName()).isEqualTo("None");
Googlercc0d9952015-08-10 12:01:34 +00001005 assertLocation(
1006 returnNoExpr.getLocation().getStartOffset(),
1007 returnNoExpr.getLocation().getEndOffset(),
1008 none.getLocation());
1009 }
1010 }
Ulf Adams89f012d2015-02-26 13:39:28 +00001011
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001012 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001013 public void testForLoopBadSyntax() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001014 setFailFast(false);
Laurent Le Brun185392d2015-03-20 14:41:25 +00001015 parseFile("[1 for (a, b, c in var]\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001016 assertContainsError("syntax error");
Ulf Adams89f012d2015-02-26 13:39:28 +00001017 }
1018
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001019 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001020 public void testForLoopBadSyntax2() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001021 setFailFast(false);
Laurent Le Brun185392d2015-03-20 14:41:25 +00001022 parseFile("[1 for in var]\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001023 assertContainsError("syntax error");
Ulf Adams89f012d2015-02-26 13:39:28 +00001024 }
1025
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001026 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001027 public void testFunCallBadSyntax() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001028 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001029 parseFile("f(1,\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001030 assertContainsError("syntax error");
Ulf Adams89f012d2015-02-26 13:39:28 +00001031 }
1032
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001033 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001034 public void testFunCallBadSyntax2() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001035 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001036 parseFile("f(1, 5, ,)\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001037 assertContainsError("syntax error");
Ulf Adams89f012d2015-02-26 13:39:28 +00001038 }
1039
Florian Weikert308c0bf2015-07-10 10:46:56 +00001040 @Test
Miguel Alcon Pinto927f3b22016-08-22 14:21:30 +00001041 public void testValidAbsoluteImportPath() throws SkylarkImportSyntaxException {
John Field9201fda2015-12-30 19:30:34 +00001042 String importString = "/some/skylark/file";
John Field1ea7fc32015-12-22 19:37:19 +00001043 List<Statement> statements =
John Field9201fda2015-12-30 19:30:34 +00001044 parseFileForSkylark("load('" + importString + "', 'fun_test')\n");
John Field1ea7fc32015-12-22 19:37:19 +00001045 LoadStatement stmt = (LoadStatement) statements.get(0);
Laurent Le Brun7b1708c2016-10-13 10:05:12 +00001046 SkylarkImport imp = SkylarkImports.create(stmt.getImport().getValue());
John Field9201fda2015-12-30 19:30:34 +00001047
1048 assertThat(imp.getImportString()).named("getImportString()").isEqualTo("/some/skylark/file");
1049 assertThat(imp.hasAbsolutePath()).named("hasAbsolutePath()").isTrue();
1050 assertThat(imp.getAbsolutePath()).named("getAbsolutePath()")
nharmatab4060b62017-04-04 17:11:39 +00001051 .isEqualTo(PathFragment.create("/some/skylark/file.bzl"));
John Field9201fda2015-12-30 19:30:34 +00001052
Laurent Le Brun7b1708c2016-10-13 10:05:12 +00001053 int startOffset = stmt.getImport().getLocation().getStartOffset();
1054 int endOffset = stmt.getImport().getLocation().getEndOffset();
John Field9201fda2015-12-30 19:30:34 +00001055 assertThat(startOffset).named("getStartOffset()").isEqualTo(5);
1056 assertThat(endOffset).named("getEndOffset()")
1057 .isEqualTo(startOffset + importString.length() + 2);
John Field1ea7fc32015-12-22 19:37:19 +00001058 }
1059
1060 private void validNonAbsoluteImportTest(String importString, String containingFileLabelString,
Miguel Alcon Pinto927f3b22016-08-22 14:21:30 +00001061 String expectedLabelString) throws SkylarkImportSyntaxException {
John Field1ea7fc32015-12-22 19:37:19 +00001062 List<Statement> statements =
1063 parseFileForSkylark("load('" + importString + "', 'fun_test')\n");
1064 LoadStatement stmt = (LoadStatement) statements.get(0);
Laurent Le Brun7b1708c2016-10-13 10:05:12 +00001065 SkylarkImport imp = SkylarkImports.create(stmt.getImport().getValue());
John Field9201fda2015-12-30 19:30:34 +00001066
1067 assertThat(imp.getImportString()).named("getImportString()").isEqualTo(importString);
1068 assertThat(imp.hasAbsolutePath()).named("hasAbsolutePath()").isFalse();
1069
John Field1ea7fc32015-12-22 19:37:19 +00001070 Label containingFileLabel = Label.parseAbsoluteUnchecked(containingFileLabelString);
John Field9201fda2015-12-30 19:30:34 +00001071 assertThat(imp.getLabel(containingFileLabel)).named("containingFileLabel()")
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +00001072 .isEqualTo(Label.parseAbsoluteUnchecked(expectedLabelString));
John Field9201fda2015-12-30 19:30:34 +00001073
Laurent Le Brun7b1708c2016-10-13 10:05:12 +00001074 int startOffset = stmt.getImport().getLocation().getStartOffset();
1075 int endOffset = stmt.getImport().getLocation().getEndOffset();
John Field9201fda2015-12-30 19:30:34 +00001076 assertThat(startOffset).named("getStartOffset()").isEqualTo(5);
1077 assertThat(endOffset).named("getEndOffset()")
1078 .isEqualTo(startOffset + importString.length() + 2);
John Field1ea7fc32015-12-22 19:37:19 +00001079 }
1080
1081 private void invalidImportTest(String importString, String expectedMsg) {
Florian Weikert308c0bf2015-07-10 10:46:56 +00001082 setFailFast(false);
Michajlo Matijkiw8c539ea2017-02-22 23:02:46 +00001083 parseFileForSkylark("load('" + importString + "', 'fun_test')\n");
Jon Brandveinee8b7aa2016-07-28 15:01:26 +00001084 assertContainsError(expectedMsg);
Florian Weikert308c0bf2015-07-10 10:46:56 +00001085 }
1086
1087 @Test
John Field1ea7fc32015-12-22 19:37:19 +00001088 public void testValidRelativeImportPathInPackageDir() throws Exception {
1089 validNonAbsoluteImportTest("file", /*containing*/ "//some/skylark:BUILD",
1090 /*expected*/ "//some/skylark:file.bzl");
Florian Weikert308c0bf2015-07-10 10:46:56 +00001091 }
1092
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001093 @Test
John Field1ea7fc32015-12-22 19:37:19 +00001094 public void testValidRelativeImportPathInPackageSubdir() throws Exception {
1095 validNonAbsoluteImportTest("file", /*containing*/ "//some/path/to:skylark/parent.bzl",
1096 /*expected*/ "//some/path/to:skylark/file.bzl");
1097 }
1098
1099 @Test
1100 public void testInvalidRelativePathBzlExtImplicit() throws Exception {
Laurent Le Brun226321c2016-03-31 09:56:49 +00001101 invalidImportTest("file.bzl", SkylarkImports.INVALID_PATH_SYNTAX);
John Field1ea7fc32015-12-22 19:37:19 +00001102 }
1103
1104 @Test
1105 public void testInvalidRelativePathNoSubdirs() throws Exception {
Laurent Le Brun226321c2016-03-31 09:56:49 +00001106 invalidImportTest("path/to/file", SkylarkImports.INVALID_PATH_SYNTAX);
John Field1ea7fc32015-12-22 19:37:19 +00001107 }
1108
1109 @Test
1110 public void testInvalidRelativePathInvalidFilename() throws Exception {
1111 invalidImportTest("\tfile", SkylarkImports.INVALID_FILENAME_PREFIX);
1112 }
1113
Miguel Alcon Pinto927f3b22016-08-22 14:21:30 +00001114 private void validAbsoluteImportLabelTest(String importString)
1115 throws SkylarkImportSyntaxException {
John Field1ea7fc32015-12-22 19:37:19 +00001116 validNonAbsoluteImportTest(importString, /*irrelevant*/ "//another/path:BUILD",
1117 /*expected*/ importString);
1118 }
1119
1120 @Test
1121 public void testValidAbsoluteImportLabel() throws Exception {
1122 validAbsoluteImportLabelTest("//some/skylark:file.bzl");
1123 }
1124
1125 @Test
1126 public void testValidAbsoluteImportLabelWithRepo() throws Exception {
1127 validAbsoluteImportLabelTest("@my_repo//some/skylark:file.bzl");
1128 }
1129
1130 @Test
1131 public void testInvalidAbsoluteImportLabel() throws Exception {
1132 invalidImportTest("//some/skylark/:file.bzl", SkylarkImports.INVALID_LABEL_PREFIX);
1133 }
1134
1135 @Test
1136 public void testInvalidAbsoluteImportLabelWithRepo() throws Exception {
1137 invalidImportTest("@my_repo//some/skylark/:file.bzl",
1138 SkylarkImports.INVALID_LABEL_PREFIX);
1139 }
1140
1141 @Test
1142 public void testInvalidAbsoluteImportLabelMissingBzlExt() throws Exception {
1143 invalidImportTest("//some/skylark:file", SkylarkImports.MUST_HAVE_BZL_EXT_MSG);
1144 }
1145
1146 @Test
1147 public void testInvalidAbsoluteImportReferencesExternalPkg() throws Exception {
1148 invalidImportTest("//external:file.bzl", SkylarkImports.EXTERNAL_PKG_NOT_ALLOWED_MSG);
1149 }
1150
1151 @Test
1152 public void testValidRelativeImportSimpleLabelInPackageDir() throws Exception {
1153 validNonAbsoluteImportTest(":file.bzl", /*containing*/ "//some/skylark:BUILD",
1154 /*expected*/ "//some/skylark:file.bzl");
1155 }
1156
1157 @Test
1158 public void testValidRelativeImportSimpleLabelInPackageSubdir() throws Exception {
1159 validNonAbsoluteImportTest(":file.bzl", /*containing*/ "//some/path/to:skylark/parent.bzl",
1160 /*expected*/ "//some/path/to:file.bzl");
1161 }
1162
1163 @Test
1164 public void testValidRelativeImportComplexLabelInPackageDir() throws Exception {
1165 validNonAbsoluteImportTest(":subdir/containing/file.bzl", /*containing*/ "//some/skylark:BUILD",
1166 /*expected*/ "//some/skylark:subdir/containing/file.bzl");
1167 }
1168
1169 @Test
1170 public void testValidRelativeImportComplexLabelInPackageSubdir() throws Exception {
1171 validNonAbsoluteImportTest(":subdir/containing/file.bzl",
1172 /*containing*/ "//some/path/to:skylark/parent.bzl",
1173 /*expected*/ "//some/path/to:subdir/containing/file.bzl");
1174 }
1175
1176 @Test
1177 public void testInvalidRelativeImportLabelMissingBzlExt() throws Exception {
1178 invalidImportTest(":file", SkylarkImports.MUST_HAVE_BZL_EXT_MSG);
1179 }
1180
1181 @Test
1182 public void testInvalidRelativeImportLabelSyntax() throws Exception {
1183 invalidImportTest("::file.bzl", SkylarkImports.INVALID_TARGET_PREFIX);
1184 }
1185
1186 @Test
Laurent Le Brun73a98492015-03-17 15:46:19 +00001187 public void testLoadNoSymbol() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001188 setFailFast(false);
Laurent Le Brun73a98492015-03-17 15:46:19 +00001189 parseFileForSkylark("load('/foo/bar/file')\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001190 assertContainsError("syntax error");
Laurent Le Brun73a98492015-03-17 15:46:19 +00001191 }
1192
1193 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001194 public void testLoadOneSymbol() throws Exception {
1195 List<Statement> statements = parseFileForSkylark(
1196 "load('/foo/bar/file', 'fun_test')\n");
1197 LoadStatement stmt = (LoadStatement) statements.get(0);
lberkiaea56b32017-05-30 12:35:33 +02001198 assertThat(stmt.getImport().getValue()).isEqualTo("/foo/bar/file");
Ulf Adams89f012d2015-02-26 13:39:28 +00001199 assertThat(stmt.getSymbols()).hasSize(1);
Jon Brandveinee8b7aa2016-07-28 15:01:26 +00001200 Identifier sym = stmt.getSymbols().get(0);
1201 int startOffset = sym.getLocation().getStartOffset();
1202 int endOffset = sym.getLocation().getEndOffset();
1203 assertThat(startOffset).named("getStartOffset()").isEqualTo(22);
1204 assertThat(endOffset).named("getEndOffset()").isEqualTo(startOffset + 10);
Ulf Adams89f012d2015-02-26 13:39:28 +00001205 }
1206
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001207 @Test
Laurent Le Brun59f587a2015-03-16 14:51:36 +00001208 public void testLoadOneSymbolWithTrailingComma() throws Exception {
1209 List<Statement> statements = parseFileForSkylark(
1210 "load('/foo/bar/file', 'fun_test',)\n");
1211 LoadStatement stmt = (LoadStatement) statements.get(0);
lberkiaea56b32017-05-30 12:35:33 +02001212 assertThat(stmt.getImport().getValue()).isEqualTo("/foo/bar/file");
Laurent Le Brun59f587a2015-03-16 14:51:36 +00001213 assertThat(stmt.getSymbols()).hasSize(1);
1214 }
1215
1216 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001217 public void testLoadMultipleSymbols() throws Exception {
1218 List<Statement> statements = parseFileForSkylark(
1219 "load('file', 'foo', 'bar')\n");
1220 LoadStatement stmt = (LoadStatement) statements.get(0);
lberkiaea56b32017-05-30 12:35:33 +02001221 assertThat(stmt.getImport().getValue()).isEqualTo("file");
Ulf Adams89f012d2015-02-26 13:39:28 +00001222 assertThat(stmt.getSymbols()).hasSize(2);
1223 }
1224
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001225 @Test
brandjon09771fd2017-07-06 08:54:29 -04001226 public void testLoadLabelQuoteError() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001227 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001228 parseFileForSkylark("load(non_quoted, 'a')\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001229 assertContainsError("syntax error");
Ulf Adams89f012d2015-02-26 13:39:28 +00001230 }
1231
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001232 @Test
brandjon09771fd2017-07-06 08:54:29 -04001233 public void testLoadSymbolQuoteError() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001234 setFailFast(false);
brandjon09771fd2017-07-06 08:54:29 -04001235 parseFileForSkylark("load('label', non_quoted)\n");
1236 assertContainsError("syntax error");
1237 }
1238
1239 @Test
1240 public void testLoadDisallowSameLine() throws Exception {
1241 setFailFast(false);
1242 parseFileForSkylark("load('foo.bzl', 'foo') load('bar.bzl', 'bar')");
Ulf Adamsc708f962015-10-22 12:02:28 +00001243 assertContainsError("syntax error");
Ulf Adams89f012d2015-02-26 13:39:28 +00001244 }
1245
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001246 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001247 public void testLoadNotAtTopLevel() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001248 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001249 parseFileForSkylark("if 1: load(8)\n");
laurentlb2843ead2017-07-05 07:20:45 -04001250 assertContainsError("syntax error at 'load': expected expression");
Ulf Adams89f012d2015-02-26 13:39:28 +00001251 }
1252
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001253 @Test
Florian Weikert9d659ad2015-07-23 14:44:36 +00001254 public void testLoadAlias() throws Exception {
Jon Brandveinee8b7aa2016-07-28 15:01:26 +00001255 List<Statement> statements = parseFileForSkylark(
1256 "load('/foo/bar/file', my_alias = 'lawl')\n");
1257 LoadStatement stmt = (LoadStatement) statements.get(0);
1258 ImmutableList<Identifier> actualSymbols = stmt.getSymbols();
1259
1260 assertThat(actualSymbols).hasSize(1);
1261 Identifier sym = actualSymbols.get(0);
1262 assertThat(sym.getName()).isEqualTo("my_alias");
1263 int startOffset = sym.getLocation().getStartOffset();
1264 int endOffset = sym.getLocation().getEndOffset();
1265 assertThat(startOffset).named("getStartOffset()").isEqualTo(22);
1266 assertThat(endOffset).named("getEndOffset()").isEqualTo(startOffset + 8);
Florian Weikert9d659ad2015-07-23 14:44:36 +00001267 }
1268
1269 @Test
1270 public void testLoadAliasMultiple() throws Exception {
1271 runLoadAliasTestForSymbols(
1272 "my_alias = 'lawl', 'lol', next_alias = 'rofl'", "my_alias", "lol", "next_alias");
1273 }
1274
1275 private void runLoadAliasTestForSymbols(String loadSymbolString, String... expectedSymbols) {
1276 List<Statement> statements =
1277 parseFileForSkylark(String.format("load('/foo/bar/file', %s)\n", loadSymbolString));
1278 LoadStatement stmt = (LoadStatement) statements.get(0);
1279 ImmutableList<Identifier> actualSymbols = stmt.getSymbols();
1280
1281 assertThat(actualSymbols).hasSize(expectedSymbols.length);
1282
1283 List<String> actualSymbolNames = new LinkedList<>();
1284
1285 for (Identifier identifier : actualSymbols) {
1286 actualSymbolNames.add(identifier.getName());
1287 }
1288
1289 assertThat(actualSymbolNames).containsExactly((Object[]) expectedSymbols);
1290 }
1291
1292 @Test
1293 public void testLoadAliasSyntaxError() throws Exception {
1294 setFailFast(false);
1295 parseFileForSkylark("load('/foo', test1 = )\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001296 assertContainsError("syntax error at ')': expected string");
Florian Weikert9d659ad2015-07-23 14:44:36 +00001297
1298 parseFileForSkylark("load('/foo', test2 = 1)\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001299 assertContainsError("syntax error at '1': expected string");
Florian Weikert9d659ad2015-07-23 14:44:36 +00001300
1301 parseFileForSkylark("load('/foo', test3 = old)\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001302 assertContainsError("syntax error at 'old': expected string");
Florian Weikert9d659ad2015-07-23 14:44:36 +00001303 }
Han-Wen Nienhuysceae8c52015-09-22 16:24:45 +00001304
Florian Weikert9d659ad2015-07-23 14:44:36 +00001305 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001306 public void testParseErrorNotComparison() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001307 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001308 parseFile("2 < not 3");
Ulf Adamsc708f962015-10-22 12:02:28 +00001309 assertContainsError("syntax error at 'not'");
Ulf Adams89f012d2015-02-26 13:39:28 +00001310 }
1311
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001312 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001313 public void testNotWithArithmeticOperatorsBadSyntax() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001314 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001315 parseFile("0 + not 0");
Ulf Adamsc708f962015-10-22 12:02:28 +00001316 assertContainsError("syntax error at 'not'");
Ulf Adams89f012d2015-02-26 13:39:28 +00001317 }
1318
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001319 @Test
Laurent Le Brunb3266382015-05-27 16:14:43 +00001320 public void testKwargsForbidden() throws Exception {
1321 setFailFast(false);
1322 parseFile("func(**dict)");
Ulf Adamsc708f962015-10-22 12:02:28 +00001323 assertContainsError("**kwargs arguments are not allowed in BUILD files");
Laurent Le Brunb3266382015-05-27 16:14:43 +00001324 }
1325
1326 @Test
1327 public void testArgsForbidden() throws Exception {
1328 setFailFast(false);
1329 parseFile("func(*array)");
Ulf Adamsc708f962015-10-22 12:02:28 +00001330 assertContainsError("*args arguments are not allowed in BUILD files");
Laurent Le Brunb3266382015-05-27 16:14:43 +00001331 }
1332
1333 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001334 public void testOptionalArgBeforeMandatoryArgInFuncDef() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001335 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001336 parseFileForSkylark("def func(a, b = 'a', c):\n return 0\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001337 assertContainsError(
Ulf Adams89f012d2015-02-26 13:39:28 +00001338 "a mandatory positional parameter must not follow an optional parameter");
1339 }
1340
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001341 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001342 public void testKwargBeforePositionalArg() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001343 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001344 parseFileForSkylark(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001345 "def func(a, b): return a + b",
1346 "func(**{'b': 1}, 'a')");
Ulf Adamsc708f962015-10-22 12:02:28 +00001347 assertContainsError("unexpected tokens after kwarg");
Ulf Adams89f012d2015-02-26 13:39:28 +00001348 }
1349
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001350 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001351 public void testDuplicateKwarg() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001352 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001353 parseFileForSkylark(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001354 "def func(a, b): return a + b",
1355 "func(**{'b': 1}, **{'a': 2})");
Ulf Adamsc708f962015-10-22 12:02:28 +00001356 assertContainsError("unexpected tokens after kwarg");
Ulf Adams89f012d2015-02-26 13:39:28 +00001357 }
1358
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001359 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001360 public void testUnnamedStar() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001361 setFailFast(false);
Francois-Rene Rideau4feb1602015-03-18 19:49:13 +00001362 List<Statement> statements = parseFileForSkylark(
1363 "def func(a, b1=2, b2=3, *, c1, d=4, c2): return a + b1 + b2 + c1 + c2 + d\n");
1364 assertThat(statements).hasSize(1);
1365 assertThat(statements.get(0)).isInstanceOf(FunctionDefStatement.class);
1366 FunctionDefStatement stmt = (FunctionDefStatement) statements.get(0);
Laurent Le Brun4baefdc2015-09-04 11:27:46 +00001367 FunctionSignature sig = stmt.getSignature().getSignature();
Francois-Rene Rideau012f7892015-03-31 17:27:01 +00001368 // Note the reordering of optional named-only at the end.
Francois-Rene Rideau4feb1602015-03-18 19:49:13 +00001369 assertThat(sig.getNames()).isEqualTo(ImmutableList.<String>of(
Francois-Rene Rideau012f7892015-03-31 17:27:01 +00001370 "a", "b1", "b2", "c1", "c2", "d"));
Francois-Rene Rideau4feb1602015-03-18 19:49:13 +00001371 FunctionSignature.Shape shape = sig.getShape();
1372 assertThat(shape.getMandatoryPositionals()).isEqualTo(1);
1373 assertThat(shape.getOptionalPositionals()).isEqualTo(2);
1374 assertThat(shape.getMandatoryNamedOnly()).isEqualTo(2);
1375 assertThat(shape.getOptionalNamedOnly()).isEqualTo(1);
Ulf Adams89f012d2015-02-26 13:39:28 +00001376 }
1377
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001378 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001379 public void testTopLevelForFails() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001380 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001381 parseFileForSkylark("for i in []: 0\n");
Ulf Adamsc708f962015-10-22 12:02:28 +00001382 assertContainsError(
Ulf Adams89f012d2015-02-26 13:39:28 +00001383 "for loops are not allowed on top-level. Put it into a function");
1384 }
1385
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001386 @Test
Ulf Adams89f012d2015-02-26 13:39:28 +00001387 public void testNestedFunctionFails() throws Exception {
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001388 setFailFast(false);
Ulf Adams89f012d2015-02-26 13:39:28 +00001389 parseFileForSkylark(
Francois-Rene Rideau5f3e30c2015-04-10 19:08:39 +00001390 "def func(a):",
1391 " def bar(): return 0",
1392 " return bar()",
1393 "");
Ulf Adamsc708f962015-10-22 12:02:28 +00001394 assertContainsError(
Ulf Adams89f012d2015-02-26 13:39:28 +00001395 "nested functions are not allowed. Move the function to top-level");
1396 }
1397
Han-Wen Nienhuysccf19ea2015-02-27 15:53:24 +00001398 @Test
Laurent Le Brun3bc8e9a2015-09-10 11:00:37 +00001399 public void testElseWithoutIf() throws Exception {
1400 setFailFast(false);
1401 parseFileForSkylark(
1402 "def func(a):",
1403 // no if
1404 " else: return a");
Yue Gan4866e152016-04-07 13:07:08 +00001405 assertContainsError("syntax error at 'else': not allowed here.");
1406 }
1407
1408 @Test
1409 public void testForElse() throws Exception {
1410 setFailFast(false);
1411 parseFileForSkylark(
1412 "def func(a):",
1413 " for i in range(a):",
1414 " print(i)",
1415 " else: return a");
1416 assertContainsError("syntax error at 'else': not allowed here.");
Laurent Le Brun3bc8e9a2015-09-10 11:00:37 +00001417 }
Florian Weikert1f004e52015-10-16 09:43:48 +00001418
1419 @Test
1420 public void testTryStatementInBuild() throws Exception {
1421 setFailFast(false);
1422 parseFile("try: pass");
Ulf Adamsc708f962015-10-22 12:02:28 +00001423 assertContainsError("syntax error at 'try': Try statements are not supported.");
Florian Weikert1f004e52015-10-16 09:43:48 +00001424 }
1425
1426 @Test
1427 public void testTryStatementInSkylark() throws Exception {
1428 setFailFast(false);
1429 parseFileForSkylark("try: pass");
Ulf Adamsc708f962015-10-22 12:02:28 +00001430 assertContainsError("syntax error at 'try': Try statements are not supported.");
Florian Weikert1f004e52015-10-16 09:43:48 +00001431 }
1432
1433 @Test
1434 public void testClassDefinitionInBuild() throws Exception {
1435 setFailFast(false);
1436 parseFile("class test(object): pass");
Ulf Adamsc708f962015-10-22 12:02:28 +00001437 assertContainsError("syntax error at 'class': Class definitions are not supported.");
Florian Weikert1f004e52015-10-16 09:43:48 +00001438 }
1439
1440 @Test
1441 public void testClassDefinitionInSkylark() throws Exception {
1442 setFailFast(false);
1443 parseFileForSkylark("class test(object): pass");
Ulf Adamsc708f962015-10-22 12:02:28 +00001444 assertContainsError("syntax error at 'class': Class definitions are not supported.");
Florian Weikert1f004e52015-10-16 09:43:48 +00001445 }
1446
1447 @Test
1448 public void testDefInBuild() throws Exception {
1449 setFailFast(false);
1450 parseFile("def func(): pass");
Ulf Adamsc708f962015-10-22 12:02:28 +00001451 assertContainsError("syntax error at 'def': This is not supported in BUILD files. "
Florian Weikert1f004e52015-10-16 09:43:48 +00001452 + "Move the block to a .bzl file and load it");
1453 }
Ulf Adams89f012d2015-02-26 13:39:28 +00001454}