Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(119)

Side by Side Diff: pkg/analysis_server/test/services/completion/statement/statement_completion_test.dart

Issue 2824233002: Complete for-statement (Closed)
Patch Set: Replace empty with synthetic Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library test.services.completion.statement; 5 library test.services.completion.statement;
6 6
7 import 'package:analysis_server/src/protocol_server.dart'; 7 import 'package:analysis_server/src/protocol_server.dart';
8 import 'package:analysis_server/src/services/completion/statement/statement_comp letion.dart'; 8 import 'package:analysis_server/src/services/completion/statement/statement_comp letion.dart';
9 import 'package:analyzer/src/dart/analysis/driver.dart'; 9 import 'package:analyzer/src/dart/analysis/driver.dart';
10 import 'package:test/test.dart'; 10 import 'package:test/test.dart';
11 import 'package:test_reflective_loader/test_reflective_loader.dart'; 11 import 'package:test_reflective_loader/test_reflective_loader.dart';
12 12
13 import '../../../abstract_single_unit.dart'; 13 import '../../../abstract_single_unit.dart';
14 14
15 main() { 15 main() {
16 defineReflectiveSuite(() { 16 defineReflectiveSuite(() {
17 defineReflectiveTests(StatementCompletionTest); 17 defineReflectiveTests(_DoCompletionTest);
18 defineReflectiveTests(_ForCompletionTest);
19 defineReflectiveTests(_IfCompletionTest);
20 defineReflectiveTests(_SimpleCompletionTest);
21 defineReflectiveTests(_WhileCompletionTest);
18 }); 22 });
19 } 23 }
20 24
21 @reflectiveTest
22 class StatementCompletionTest extends AbstractSingleUnitTest { 25 class StatementCompletionTest extends AbstractSingleUnitTest {
23 SourceChange change; 26 SourceChange change;
24 27
25 bool get enableNewAnalysisDriver => true; 28 bool get enableNewAnalysisDriver => true;
26 29
27 test_completeDoEmptyCondition() async { 30 int _after(String source, String match) =>
31 source.indexOf(match) + match.length;
32
33 int _afterLast(String source, String match) =>
34 source.lastIndexOf(match) + match.length;
35
36 void _assertHasChange(String message, String expectedCode, [Function cmp]) {
37 if (change.message == message) {
38 if (!change.edits.isEmpty) {
39 String resultCode =
40 SourceEdit.applySequence(testCode, change.edits[0].edits);
41 expect(resultCode, expectedCode.replaceAll('////', ''));
42 if (cmp != null) {
43 int offset = cmp(resultCode);
44 expect(change.selection.offset, offset);
45 }
46 } else {
47 if (cmp != null) {
48 int offset = cmp(testCode);
49 expect(change.selection.offset, offset);
50 }
51 }
52 return;
53 }
54 fail("Expected to find |$message| but got: " + change.message);
55 }
56
57 _computeCompletion(int offset) async {
58 driver.changeFile(testFile);
59 AnalysisResult result = await driver.getResult(testFile);
60 StatementCompletionContext context = new StatementCompletionContext(
61 testFile,
62 result.lineInfo,
63 offset,
64 testUnit,
65 testUnitElement,
66 result.errors);
67 StatementCompletionProcessor processor =
68 new StatementCompletionProcessor(context);
69 StatementCompletion completion = await processor.compute();
70 change = completion.change;
71 }
72
73 _prepareCompletion(String search, String sourceCode,
74 {bool atStart: false, bool atEnd: false, int delta: 0}) async {
75 testCode = sourceCode.replaceAll('////', '');
76 int offset = findOffset(search);
77 if (atStart) {
78 delta = 0;
79 } else if (atEnd) {
80 delta = search.length;
81 }
82 await _prepareCompletionAt(offset + delta, testCode);
83 }
84
85 _prepareCompletionAt(int offset, String sourceCode) async {
86 verifyNoTestUnitErrors = false;
87 await resolveTestUnit(sourceCode);
88 await _computeCompletion(offset);
89 }
90 }
91
92 @reflectiveTest
93 class _DoCompletionTest extends StatementCompletionTest {
94 test_emptyCondition() async {
28 await _prepareCompletion( 95 await _prepareCompletion(
29 'while ()', 96 'while ()',
30 ''' 97 '''
31 main() { 98 main() {
32 do { 99 do {
33 } while () 100 } while ()
34 } 101 }
35 ''', 102 ''',
36 atEnd: true); 103 atEnd: true);
37 _assertHasChange( 104 _assertHasChange(
38 'Complete do-statement', 105 'Complete do-statement',
39 ''' 106 '''
40 main() { 107 main() {
41 do { 108 do {
42 } while (); 109 } while ();
43 } 110 }
44 ''', 111 ''',
45 (s) => s.indexOf('while (') + 'while ('.length); 112 (s) => _after(s, 'while ('));
46 } 113 }
47 114
48 test_completeDoKeywordOnly() async { 115 test_keywordOnly() async {
49 await _prepareCompletion( 116 await _prepareCompletion(
50 'do', 117 'do',
51 ''' 118 '''
52 main() { 119 main() {
53 do //// 120 do ////
54 } 121 }
55 ''', 122 ''',
56 atEnd: true); 123 atEnd: true);
57 _assertHasChange( 124 _assertHasChange(
58 'Complete do-statement', 125 'Complete do-statement',
59 ''' 126 '''
60 main() { 127 main() {
61 do { 128 do {
62 //// 129 ////
63 } while (); 130 } while ();
64 } 131 }
65 ''', 132 ''',
66 (s) => s.indexOf('while (') + 'while ('.length); 133 (s) => _after(s, 'while ('));
67 } 134 }
68 135
69 test_completeDoNoBody() async { 136 test_noBody() async {
70 await _prepareCompletion( 137 await _prepareCompletion(
71 'do', 138 'do',
72 ''' 139 '''
73 main() { 140 main() {
74 do; 141 do;
75 while 142 while
76 } 143 }
77 ''', 144 ''',
78 atEnd: true); 145 atEnd: true);
79 _assertHasChange( 146 _assertHasChange(
80 'Complete do-statement', 147 'Complete do-statement',
81 ''' 148 '''
82 main() { 149 main() {
83 do { 150 do {
84 //// 151 ////
85 } while (); 152 } while ();
86 } 153 }
87 ''', 154 ''',
88 (s) => s.indexOf('while (') + 'while ('.length); 155 (s) => _after(s, 'while ('));
89 } 156 }
90 157
91 test_completeDoNoCondition() async { 158 test_noCondition() async {
92 await _prepareCompletion( 159 await _prepareCompletion(
93 'while', 160 'while',
94 ''' 161 '''
95 main() { 162 main() {
96 do { 163 do {
97 } while 164 } while
98 } 165 }
99 ''', 166 ''',
100 atEnd: true); 167 atEnd: true);
101 _assertHasChange( 168 _assertHasChange(
102 'Complete do-statement', 169 'Complete do-statement',
103 ''' 170 '''
104 main() { 171 main() {
105 do { 172 do {
106 } while (); 173 } while ();
107 } 174 }
108 ''', 175 ''',
109 (s) => s.indexOf('while (') + 'while ('.length); 176 (s) => _after(s, 'while ('));
110 } 177 }
111 178
112 test_completeDoNoWhile() async { 179 test_noWhile() async {
113 await _prepareCompletion( 180 await _prepareCompletion(
114 '}', 181 '}',
115 ''' 182 '''
116 main() { 183 main() {
117 do { 184 do {
118 } 185 }
119 } 186 }
120 ''', 187 ''',
121 atEnd: true); 188 atEnd: true);
122 _assertHasChange( 189 _assertHasChange(
123 'Complete do-statement', 190 'Complete do-statement',
124 ''' 191 '''
125 main() { 192 main() {
126 do { 193 do {
127 } while (); 194 } while ();
128 } 195 }
129 ''', 196 ''',
130 (s) => s.indexOf('while (') + 'while ('.length); 197 (s) => _after(s, 'while ('));
198 }
199 }
200
201 @reflectiveTest
202 class _ForCompletionTest extends StatementCompletionTest {
203 test_emptyCondition() async {
204 await _prepareCompletion(
205 '}',
206 '''
207 main() {
208 for (int i = 0;) {
209 }
210 }
211 ''',
212 atEnd: true);
213 _assertHasChange(
214 'Complete for-statement',
215 '''
216 main() {
217 for (int i = 0; ) {
218 }
219 }
220 ''',
221 (s) => _after(s, '0; '));
131 } 222 }
132 223
133 test_completeIfAfterCondition_BAD() async { 224 test_emptyInitializers() async {
225 await _prepareCompletion(
226 '}',
227 '''
228 main() {
229 for () {
230 }
231 }
232 ''',
233 atEnd: true);
234 _assertHasChange(
235 'Complete for-statement',
236 '''
237 main() {
238 for () {
239 }
240 }
241 ''',
242 (s) => _after(s, 'for ('));
243 }
244
245 test_emptyInitializersEmptyCondition() async {
246 await _prepareCompletion(
247 '}',
248 '''
249 main() {
250 for (;/**/) {
251 }
252 }
253 ''',
254 atEnd: true);
255 _assertHasChange(
256 'Complete for-statement',
257 '''
258 main() {
259 for (;/**/) {
260 }
261 }
262 ''',
263 (s) => _after(s, '/**/'));
264 }
265
266 test_emptyParts() async {
267 await _prepareCompletion(
268 ';)',
269 '''
270 main() {
271 for (;;)
272 }
273 ''',
274 atEnd: true);
275 _assertHasChange(
276 'Complete for-statement',
277 '''
278 main() {
279 for (;;) {
280 ////
281 }
282 }
283 ''',
284 (s) => _after(s, ' '));
285 }
286
287 test_emptyUpdaters() async {
288 await _prepareCompletion(
289 '}',
290 '''
291 main() {
292 for (int i = 0; i < 10 /**/) {
293 }
294 }
295 ''',
296 atEnd: true);
297 _assertHasChange(
298 'Complete for-statement',
299 '''
300 main() {
301 for (int i = 0; i < 10 /**/; ) {
302 }
303 }
304 ''',
305 (s) => _after(s, '10 /**/; '));
306 }
307
308 test_keywordOnly() async {
309 await _prepareCompletion(
310 'for',
311 '''
312 main() {
313 for
314 }
315 ''',
316 atEnd: true);
317 _assertHasChange(
318 'Complete for-statement',
319 '''
320 main() {
321 for () {
322 ////
323 }
324 }
325 ''',
326 (s) => _after(s, 'for ('));
327 }
328
329 test_missingLeftSeparator() async {
330 await _prepareCompletion(
331 '}',
332 '''
333 main() {
334 for (int i = 0) {
335 }
336 }
337 ''',
338 atEnd: true);
339 _assertHasChange(
340 'Complete for-statement',
341 '''
342 main() {
343 for (int i = 0; ) {
344 }
345 }
346 ''',
347 (s) => _after(s, '0; '));
348 }
349 }
350
351 @reflectiveTest
352 class _IfCompletionTest extends StatementCompletionTest {
353 test_afterCondition_BAD() async {
134 // TODO(messick): Fix the code to make this like test_completeIfWithConditio n. 354 // TODO(messick): Fix the code to make this like test_completeIfWithConditio n.
135 // Recap: Finding the node at the selectionOffset returns the block, not the 355 // Recap: Finding the node at the selectionOffset returns the block, not the
136 // if-statement. Need to understand if that only happens when the if-stateme nt 356 // if-statement. Need to understand if that only happens when the if-stateme nt
137 // is the only statement in the block, or perhaps first or last? And what 357 // is the only statement in the block, or perhaps first or last? And what
138 // happens when it is in the middle of other statements? 358 // happens when it is in the middle of other statements?
139 await _prepareCompletion( 359 await _prepareCompletion(
140 'if (true) ', // Trigger completion after space. 360 'if (true) ', // Trigger completion after space.
141 ''' 361 '''
142 main() { 362 main() {
143 if (true) //// 363 if (true) ////
144 } 364 }
145 ''', 365 ''',
146 atEnd: true); 366 atEnd: true);
147 _assertHasChange( 367 _assertHasChange(
148 // Note: This is not what we want. 368 // Note: This is not what we want.
149 'Insert a newline at the end of the current line', 369 'Insert a newline at the end of the current line',
150 ''' 370 '''
151 main() { 371 main() {
152 if (true) //// 372 if (true) ////
153 } 373 }
154 } 374 }
155 ''', 375 ''',
156 (s) => s.indexOf('if (true) ') + 'if (true) '.length); 376 (s) => _after(s, 'if (true) '));
157 } 377 }
158 378
159 test_completeIfEmptyCondition() async { 379 test_emptyCondition() async {
160 await _prepareCompletion( 380 await _prepareCompletion(
161 'if ()', 381 'if ()',
162 ''' 382 '''
163 main() { 383 main() {
164 if () 384 if ()
165 } 385 }
166 ''', 386 ''',
167 atEnd: true); 387 atEnd: true);
168 _assertHasChange( 388 _assertHasChange(
169 'Complete if-statement', 389 'Complete if-statement',
170 ''' 390 '''
171 main() { 391 main() {
172 if () { 392 if () {
173 //// 393 ////
174 } 394 }
175 } 395 }
176 ''', 396 ''',
177 (s) => s.indexOf('if (') + 'if ('.length); 397 (s) => _after(s, 'if ('));
178 } 398 }
179 399
180 test_completeIfKeywordOnly() async { 400 test_keywordOnly() async {
181 await _prepareCompletion( 401 await _prepareCompletion(
182 'if', 402 'if',
183 ''' 403 '''
184 main() { 404 main() {
185 if //// 405 if ////
186 } 406 }
187 ''', 407 ''',
188 atEnd: true); 408 atEnd: true);
189 _assertHasChange( 409 _assertHasChange(
190 'Complete if-statement', 410 'Complete if-statement',
191 ''' 411 '''
192 main() { 412 main() {
193 if () { 413 if () {
194 //// 414 ////
195 } 415 }
196 } 416 }
197 ''', 417 ''',
198 (s) => s.indexOf('if (') + 'if ('.length); 418 (s) => _after(s, 'if ('));
199 } 419 }
200 420
201 test_completeIfWithCondition() async { 421 test_withCondition() async {
202 await _prepareCompletion( 422 await _prepareCompletion(
203 'if (tr', // Trigger completion from within expression. 423 'if (tr', // Trigger completion from within expression.
204 ''' 424 '''
205 main() { 425 main() {
206 if (true) 426 if (true)
207 } 427 }
208 ''', 428 ''',
209 atEnd: true); 429 atEnd: true);
210 _assertHasChange( 430 _assertHasChange(
211 'Complete if-statement', 431 'Complete if-statement',
212 ''' 432 '''
213 main() { 433 main() {
214 if (true) { 434 if (true) {
215 //// 435 ////
216 } 436 }
217 } 437 }
218 ''', 438 ''',
219 (s) => s.indexOf(' ') + ' '.length); 439 (s) => _after(s, ' '));
220 } 440 }
221 441
222 test_completeIfWithElse_BAD() async { 442 test_withElse_BAD() async {
223 await _prepareCompletion( 443 await _prepareCompletion(
224 'if ()', 444 'if ()',
225 ''' 445 '''
226 main() { 446 main() {
227 if () 447 if ()
228 else 448 else
229 } 449 }
230 ''', 450 ''',
231 atEnd: true); 451 atEnd: true);
232 _assertHasChange( 452 _assertHasChange(
233 // Note: if-statement completion should not trigger. 453 // Note: if-statement completion should not trigger.
234 'Insert a newline at the end of the current line', 454 'Insert a newline at the end of the current line',
235 ''' 455 '''
236 main() { 456 main() {
237 if () 457 if ()
238 else 458 else
239 } 459 }
240 } 460 }
241 ''', 461 ''',
242 (s) => s.indexOf('if ()') + 'if ()'.length); 462 (s) => _after(s, 'if ()'));
243 } 463 }
244 464
245 test_completeIfWithinEmptyCondition() async { 465 test_withinEmptyCondition() async {
246 await _prepareCompletion( 466 await _prepareCompletion(
247 'if (', 467 'if (',
248 ''' 468 '''
249 main() { 469 main() {
250 if () 470 if ()
251 } 471 }
252 ''', 472 ''',
253 atEnd: true); 473 atEnd: true);
254 _assertHasChange( 474 _assertHasChange(
255 'Complete if-statement', 475 'Complete if-statement',
256 ''' 476 '''
257 main() { 477 main() {
258 if () { 478 if () {
259 //// 479 ////
260 } 480 }
261 } 481 }
262 ''', 482 ''',
263 (s) => s.indexOf('if (') + 'if ('.length); 483 (s) => _after(s, 'if ('));
264 }
265
266 test_completeWhileKeywordOnly() async {
267 await _prepareCompletion(
268 'while',
269 '''
270 main() {
271 while ////
272 }
273 ''',
274 atEnd: true);
275 _assertHasChange(
276 'Complete while-statement',
277 '''
278 main() {
279 while () {
280 ////
281 } 484 }
282 } 485 }
283 ''',
284 (s) => s.indexOf('while (') + 'while ('.length);
285 }
286 486
287 test_simpleEnter() async { 487 @reflectiveTest
488 class _SimpleCompletionTest extends StatementCompletionTest {
489 test_enter() async {
288 await _prepareCompletion( 490 await _prepareCompletion(
289 'v = 1;', 491 'v = 1;',
290 ''' 492 '''
291 main() { 493 main() {
292 int v = 1; 494 int v = 1;
293 } 495 }
294 ''', 496 ''',
295 atEnd: true); 497 atEnd: true);
296 _assertHasChange( 498 _assertHasChange(
297 'Insert a newline at the end of the current line', 499 'Insert a newline at the end of the current line',
298 ''' 500 '''
299 main() { 501 main() {
300 int v = 1; 502 int v = 1;
301 //// 503 ////
302 } 504 }
303 '''); 505 ''');
304 } 506 }
305 507
306 test_simpleSemicolon() async { 508 test_semicolon() async {
307 await _prepareCompletion( 509 await _prepareCompletion(
308 'v = 1', 510 'v = 1',
309 ''' 511 '''
310 main() { 512 main() {
311 int v = 1 513 int v = 1
312 } 514 }
313 ''', 515 ''',
314 atEnd: true); 516 atEnd: true);
315 _assertHasChange( 517 _assertHasChange(
316 'Add a semicolon and newline', 518 'Add a semicolon and newline',
317 ''' 519 '''
318 main() { 520 main() {
319 int v = 1; 521 int v = 1;
320 //// 522 ////
321 } 523 }
322 ''', 524 ''',
323 (s) => s.lastIndexOf(' ') + ' '.length); 525 (s) => _afterLast(s, ' '));
324 }
325
326 void _assertHasChange(String message, String expectedCode, [Function cmp]) {
327 if (change.message == message) {
328 if (!change.edits.isEmpty) {
329 String resultCode =
330 SourceEdit.applySequence(testCode, change.edits[0].edits);
331 expect(resultCode, expectedCode.replaceAll('////', ''));
332 if (cmp != null) {
333 int offset = cmp(resultCode);
334 expect(change.selection.offset, offset);
335 }
336 } else {
337 if (cmp != null) {
338 int offset = cmp(testCode);
339 expect(change.selection.offset, offset);
340 }
341 }
342 return;
343 }
344 fail("Expected to find |$message| but got: " + change.message);
345 }
346
347 _computeCompletion(int offset) async {
348 driver.changeFile(testFile);
349 AnalysisResult result = await driver.getResult(testFile);
350 StatementCompletionContext context = new StatementCompletionContext(
351 testFile,
352 result.lineInfo,
353 offset,
354 testUnit,
355 testUnitElement,
356 result.errors);
357 StatementCompletionProcessor processor =
358 new StatementCompletionProcessor(context);
359 StatementCompletion completion = await processor.compute();
360 change = completion.change;
361 }
362
363 _prepareCompletion(String search, String sourceCode,
364 {bool atStart: false, bool atEnd: false, int delta: 0}) async {
365 testCode = sourceCode.replaceAll('////', '');
366 int offset = findOffset(search);
367 if (atStart) {
368 delta = 0;
369 } else if (atEnd) {
370 delta = search.length;
371 }
372 await _prepareCompletionAt(offset + delta, testCode);
373 }
374
375 _prepareCompletionAt(int offset, String sourceCode) async {
376 verifyNoTestUnitErrors = false;
377 await resolveTestUnit(sourceCode);
378 await _computeCompletion(offset);
379 } 526 }
380 } 527 }
528
529 @reflectiveTest
530 class _WhileCompletionTest extends StatementCompletionTest {
531 /*
532 The implementation of completion for while-statements is shared with
533 if-statements. Here we check that the wrapper for while-statements
534 functions as expected. The individual test cases are covered by the
535 _IfCompletionTest tests. If the implementation changes then the same
536 set of tests defined for if-statements should be duplicated here.
537 */
538 test_keywordOnly() async {
539 await _prepareCompletion(
540 'while',
541 '''
542 main() {
543 while ////
544 }
545 ''',
546 atEnd: true);
547 _assertHasChange(
548 'Complete while-statement',
549 '''
550 main() {
551 while () {
552 ////
553 }
554 }
555 ''',
556 (s) => _after(s, 'while ('));
557 }
558 }
OLDNEW
« no previous file with comments | « pkg/analysis_server/lib/src/services/completion/statement/statement_completion.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698