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

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

Issue 2852073002: Complete declarations; detect invalid blocks (Closed)
Patch Set: Created 3 years, 7 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(_DeclarationCompletionTest);
17 defineReflectiveTests(_ControlFlowCompletionTest); 18 defineReflectiveTests(_ControlFlowCompletionTest);
18 defineReflectiveTests(_DoCompletionTest); 19 defineReflectiveTests(_DoCompletionTest);
19 defineReflectiveTests(_ForCompletionTest); 20 defineReflectiveTests(_ForCompletionTest);
20 defineReflectiveTests(_ForEachCompletionTest); 21 defineReflectiveTests(_ForEachCompletionTest);
21 defineReflectiveTests(_IfCompletionTest); 22 defineReflectiveTests(_IfCompletionTest);
22 defineReflectiveTests(_SimpleCompletionTest); 23 defineReflectiveTests(_SimpleCompletionTest);
23 defineReflectiveTests(_SwitchCompletionTest); 24 defineReflectiveTests(_SwitchCompletionTest);
24 defineReflectiveTests(_TryCompletionTest); 25 defineReflectiveTests(_TryCompletionTest);
25 defineReflectiveTests(_WhileCompletionTest); 26 defineReflectiveTests(_WhileCompletionTest);
26 }); 27 });
(...skipping 14 matching lines...) Expand all
41 if (change.message == message) { 42 if (change.message == message) {
42 if (!change.edits.isEmpty) { 43 if (!change.edits.isEmpty) {
43 String resultCode = 44 String resultCode =
44 SourceEdit.applySequence(testCode, change.edits[0].edits); 45 SourceEdit.applySequence(testCode, change.edits[0].edits);
45 expect(resultCode, expectedCode.replaceAll('////', '')); 46 expect(resultCode, expectedCode.replaceAll('////', ''));
46 if (cmp != null) { 47 if (cmp != null) {
47 int offset = cmp(resultCode); 48 int offset = cmp(resultCode);
48 expect(change.selection.offset, offset); 49 expect(change.selection.offset, offset);
49 } 50 }
50 } else { 51 } else {
52 expect(testCode, expectedCode.replaceAll('////', ''));
51 if (cmp != null) { 53 if (cmp != null) {
52 int offset = cmp(testCode); 54 int offset = cmp(testCode);
53 expect(change.selection.offset, offset); 55 expect(change.selection.offset, offset);
54 } 56 }
55 } 57 }
56 return; 58 return;
57 } 59 }
58 fail("Expected to find |$message| but got: " + change.message); 60 fail("Expected to find |$message| but got: " + change.message);
59 } 61 }
60 62
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 ex(e) { 186 ex(e) {
185 for (int i = 0; i < 3; i++) { 187 for (int i = 0; i < 3; i++) {
186 throw e; 188 throw e;
187 } 189 }
188 //// 190 ////
189 } 191 }
190 ''', 192 ''',
191 (s) => _afterLast(s, ' ')); 193 (s) => _afterLast(s, ' '));
192 } 194 }
193 195
196 test_ifNoBlock() async {
197 await _prepareCompletion(
198 'return',
199 '''
200 ex(e) {
201 if (true) return 0
202 }
203 ''',
204 atEnd: true);
205 _assertHasChange(
206 'Add a semicolon and newline',
207 '''
208 ex(e) {
209 if (true) return 0;
210 ////
211 }
212 ''',
213 (s) => _afterLast(s, ' '));
214 }
215
194 test_ifThrow() async { 216 test_ifThrow() async {
195 await _prepareCompletion( 217 await _prepareCompletion(
196 'throw e;', 218 'throw e;',
197 ''' 219 '''
198 ex(e) { 220 ex(e) {
199 if (true) { 221 if (true) {
200 throw e; 222 throw e;
201 } 223 }
202 } 224 }
203 ''', 225 ''',
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
258 return 3 + 4; 280 return 3 + 4;
259 } 281 }
260 //// 282 ////
261 } 283 }
262 ''', 284 ''',
263 (s) => _afterLast(s, ' ')); 285 (s) => _afterLast(s, ' '));
264 } 286 }
265 } 287 }
266 288
267 @reflectiveTest 289 @reflectiveTest
290 class _DeclarationCompletionTest extends StatementCompletionTest {
291 test_classNameNoBody() async {
292 await _prepareCompletion(
293 'Sample',
294 '''
295 class Sample
296 ''',
297 atEnd: true);
298 _assertHasChange(
299 'Complete class declaration',
300 '''
301 class Sample {
302 ////
303 }
304 ''',
305 (s) => _afterLast(s, ' '));
306 }
Brian Wilkerson 2017/05/01 15:28:32 Perhaps add a test where there are other clauses,
messick 2017/05/01 15:45:00 Acknowledged.
307
308 test_functionDeclNoBody() async {
309 await _prepareCompletion(
310 'source()',
311 '''
312 String source()
313 ''',
314 atEnd: true);
315 _assertHasChange(
316 'Complete function declaration',
317 '''
318 String source() {
319 ////
320 }
321 ''',
322 (s) => _after(s, ' '));
323 }
324
325 test_methodDeclNoBody() async {
326 await _prepareCompletion(
327 'source()',
328 '''
329 class Sample {
330 String source()
331 }
332 ''',
333 atEnd: true);
334 _assertHasChange(
335 'Complete function declaration',
336 '''
337 class Sample {
338 String source() {
339 ////
340 }
341 }
342 ''',
343 (s) => _after(s, ' '));
344 }
345
346 test_variableDeclNoBody() async {
347 await _prepareCompletion(
348 'source',
349 '''
350 String source
351 ''',
352 atEnd: true);
353 _assertHasChange(
354 'Complete variable declaration',
355 '''
356 String source;
357 ////
358 ''',
359 (s) => _after(s, ';\n'));
360 }
361 }
362
363 @reflectiveTest
268 class _DoCompletionTest extends StatementCompletionTest { 364 class _DoCompletionTest extends StatementCompletionTest {
269 test_emptyCondition() async { 365 test_emptyCondition() async {
270 await _prepareCompletion( 366 await _prepareCompletion(
271 'while ()', 367 'while ()',
272 ''' 368 '''
273 main() { 369 main() {
274 do { 370 do {
275 } while () 371 } while ()
276 } 372 }
277 ''', 373 ''',
(...skipping 23 matching lines...) Expand all
301 ''' 397 '''
302 main() { 398 main() {
303 do { 399 do {
304 //// 400 ////
305 } while (); 401 } while ();
306 } 402 }
307 ''', 403 ''',
308 (s) => _after(s, 'while (')); 404 (s) => _after(s, 'while ('));
309 } 405 }
310 406
407 test_keywordStatement() async {
408 await _prepareCompletion(
409 'do',
410 '''
411 main() {
412 do ////
413 return;
414 }
415 ''',
416 atEnd: true);
417 _assertHasChange(
418 'Complete do-statement',
419 '''
420 main() {
421 do {
422 ////
423 } while ();
424 return;
425 }
426 ''',
427 (s) => _after(s, 'while ('));
428 }
429
311 test_noBody() async { 430 test_noBody() async {
312 await _prepareCompletion( 431 await _prepareCompletion(
313 'do', 432 'do',
314 ''' 433 '''
315 main() { 434 main() {
316 do; 435 do;
317 while 436 while
318 } 437 }
319 ''', 438 ''',
320 atEnd: true); 439 atEnd: true);
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 ''' 509 '''
391 main() { 510 main() {
392 for (int i = 0; ; ) { 511 for (int i = 0; ; ) {
393 } 512 }
394 } 513 }
395 ''', 514 ''',
396 (s) => _after(s, '0; ')); 515 (s) => _after(s, '0; '));
397 } 516 }
398 517
399 test_emptyInitializers() async { 518 test_emptyInitializers() async {
519 // TODO(messick) This should insert a newline and move the cursor there.
Brian Wilkerson 2017/05/01 15:28:32 Consider updating the expectations as appropriate
messick 2017/05/01 15:45:00 Acknowledged.
400 await _prepareCompletion( 520 await _prepareCompletion(
401 '}', 521 '}',
402 ''' 522 '''
403 main() { 523 main() {
404 for () { 524 for () {
405 } 525 }
406 } 526 }
407 ''', 527 ''',
408 atEnd: true); 528 atEnd: true);
409 _assertHasChange( 529 _assertHasChange(
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 _assertHasChange( 634 _assertHasChange(
515 'Complete for-statement', 635 'Complete for-statement',
516 ''' 636 '''
517 main() { 637 main() {
518 for (int i = 0; ) { 638 for (int i = 0; ) {
519 } 639 }
520 } 640 }
521 ''', 641 ''',
522 (s) => _after(s, '0; ')); 642 (s) => _after(s, '0; '));
523 } 643 }
644
645 test_noError() async {
646 await _prepareCompletion(
647 ';)',
648 '''
649 main() {
650 for (;;)
651 return;
652 }
653 ''',
654 atEnd: true);
655 _assertHasChange(
656 'Complete for-statement',
657 '''
658 main() {
659 for (;;) {
660 ////
661 }
662 return;
663 }
664 ''',
665 (s) => _after(s, ' '));
666 }
524 } 667 }
525 668
526 @reflectiveTest 669 @reflectiveTest
527 class _ForEachCompletionTest extends StatementCompletionTest { 670 class _ForEachCompletionTest extends StatementCompletionTest {
528 test_emptyIdentifier() async { 671 test_emptyIdentifier() async {
529 await _prepareCompletion( 672 await _prepareCompletion(
530 'in xs)', 673 'in xs)',
531 ''' 674 '''
532 main() { 675 main() {
533 for (in xs) 676 for (in xs)
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
580 'Complete for-each-statement', 723 'Complete for-each-statement',
581 ''' 724 '''
582 main() { 725 main() {
583 for (var x in ) { 726 for (var x in ) {
584 //// 727 ////
585 } 728 }
586 } 729 }
587 ''', 730 ''',
588 (s) => _after(s, 'in ')); 731 (s) => _after(s, 'in '));
589 } 732 }
733
734 test_noError() async {
735 await _prepareCompletion(
736 '])',
737 '''
738 main() {
739 for (var x in [1,2])
740 return;
741 }
742 ''',
743 atEnd: true);
744 _assertHasChange(
745 'Complete for-each-statement',
746 '''
747 main() {
748 for (var x in [1,2]) {
749 ////
750 }
751 return;
752 }
753 ''',
754 (s) => _after(s, ' '));
755 }
590 } 756 }
591 757
592 @reflectiveTest 758 @reflectiveTest
593 class _IfCompletionTest extends StatementCompletionTest { 759 class _IfCompletionTest extends StatementCompletionTest {
594 test_afterCondition_BAD() async { 760 test_afterCondition_BAD() async {
595 // TODO(messick) Stop inserting the space after the closing brace. 761 // TODO(messick) Stop inserting the space after the closing brace.
596 await _prepareCompletion( 762 await _prepareCompletion(
597 'if (true) ', // Trigger completion after space. 763 'if (true) ', // Trigger completion after space.
598 ''' 764 '''
599 main() { 765 main() {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
648 ''' 814 '''
649 main() { 815 main() {
650 if () { 816 if () {
651 //// 817 ////
652 } 818 }
653 } 819 }
654 ''', 820 ''',
655 (s) => _after(s, 'if (')); 821 (s) => _after(s, 'if ('));
656 } 822 }
657 823
824 test_noError() async {
825 await _prepareCompletion(
826 'if (true)',
827 '''
828 main() {
829 if (true)
830 return;
831 }
832 ''',
833 atEnd: true);
834 _assertHasChange(
835 'Complete if-statement',
836 '''
837 main() {
838 if (true) {
839 ////
840 }
841 return;
842 }
843 ''',
844 (s) => _after(s, ' '));
845 }
846
658 test_withCondition() async { 847 test_withCondition() async {
659 await _prepareCompletion( 848 await _prepareCompletion(
660 'if (tr', // Trigger completion from within expression. 849 'if (tr', // Trigger completion from within expression.
661 ''' 850 '''
662 main() { 851 main() {
663 if (true) 852 if (true)
664 } 853 }
665 ''', 854 ''',
666 atEnd: true); 855 atEnd: true);
667 _assertHasChange( 856 _assertHasChange(
(...skipping 18 matching lines...) Expand all
686 } 875 }
687 ''', 876 ''',
688 atEnd: true); 877 atEnd: true);
689 _assertHasChange( 878 _assertHasChange(
690 // Note: if-statement completion should not trigger. 879 // Note: if-statement completion should not trigger.
691 'Insert a newline at the end of the current line', 880 'Insert a newline at the end of the current line',
692 ''' 881 '''
693 main() { 882 main() {
694 if () 883 if ()
695 else 884 else
696 }
697 } 885 }
698 ''', 886 ''',
699 (s) => _after(s, 'if ()')); 887 (s) => _after(s, 'if ()'));
700 } 888 }
701 889
702 test_withinEmptyCondition() async { 890 test_withinEmptyCondition() async {
703 await _prepareCompletion( 891 await _prepareCompletion(
704 'if (', 892 'if (',
705 ''' 893 '''
706 main() { 894 main() {
(...skipping 28 matching lines...) Expand all
735 _assertHasChange( 923 _assertHasChange(
736 'Insert a newline at the end of the current line', 924 'Insert a newline at the end of the current line',
737 ''' 925 '''
738 main() { 926 main() {
739 int v = 1; 927 int v = 1;
740 //// 928 ////
741 } 929 }
742 '''); 930 ''');
743 } 931 }
744 932
745 test_semicolon() async { 933 test_noCloseParen() async {
934 await _prepareCompletion(
935 'ing(3',
936 '''
937 main() {
938 var s = 'sample'.substring(3
939 }
940 ''',
941 atEnd: true);
942 _assertHasChange(
943 'Insert a newline at the end of the current line',
944 '''
945 main() {
946 var s = 'sample'.substring(3);
947 ////
948 }
949 ''',
950 (s) => _afterLast(s, ' '));
951 }
952
953 test_noCloseParenWithSemicolon() async {
954 String before = '''
955 main() {
956 var s = 'sample'.substring(3;
957 }
958 ''';
959 String after = '''
960 main() {
961 var s = 'sample'.substring(3);
962 ////
963 }
964 ''';
965 // Check completion both before and after the semicolon.
966 await _prepareCompletion('ing(3', before, atEnd: true);
967 _assertHasChange('Insert a newline at the end of the current line', after,
968 (s) => _afterLast(s, ' '));
969 await _prepareCompletion('ing(3;', before, atEnd: true);
970 _assertHasChange('Insert a newline at the end of the current line', after,
971 (s) => _afterLast(s, ' '));
972 }
973
974 test_semicolonFn() async {
975 await _prepareCompletion(
976 '=> 3',
977 '''
978 main() {
979 int f() => 3
980 }
981 ''',
982 atEnd: true);
983 _assertHasChange(
984 'Add a semicolon and newline',
985 '''
986 main() {
987 int f() => 3;
988 ////
989 }
990 ''',
991 (s) => _afterLast(s, ' '));
992 }
993
994 test_semicolonFnBody() async {
995 // It would be reasonable to add braces in this case. Unfortunately,
996 // the incomplete line parses as two statements ['int;', 'f();'], not one.
997 await _prepareCompletion(
998 'f()',
999 '''
1000 main() {
1001 int f()
1002 }
1003 ''',
1004 atEnd: true);
1005 _assertHasChange(
1006 'Insert a newline at the end of the current line',
1007 '''
1008 main() {
1009 int f()
1010 }
1011 ''',
1012 (s) => _afterLast(s, '()'));
1013 }
1014
1015 test_semicolonFnBodyWithDef() async {
1016 // This ought to be the same as test_semicolonFnBody() but the definition
1017 // of f() removes an error and it appears to be a different case.
1018 // Suggestions for unifying the two are welcome.
1019 await _prepareCompletion(
1020 'f()',
1021 '''
1022 main() {
1023 int f()
1024 }
1025 f() {}
1026 ''',
1027 atEnd: true);
1028 _assertHasChange(
1029 'Add a semicolon and newline',
1030 '''
1031 main() {
1032 int f();
1033 ////
1034 }
1035 f() {}
1036 ''',
1037 (s) => _afterLast(s, ' '));
1038 }
1039
1040 test_semicolonFnExpr() async {
1041 await _prepareCompletion(
1042 '=>',
1043 '''
1044 main() {
1045 int f() =>
1046 }
1047 ''',
1048 atEnd: true);
1049 _assertHasChange(
1050 'Add a semicolon and newline',
1051 '''
1052 main() {
1053 int f() => ;
1054 ////
1055 }
1056 ''',
1057 (s) => _afterLast(s, '=> '));
1058 }
1059
1060 test_semicolonFnSpaceExpr() async {
1061 await _prepareCompletion(
1062 '=>',
1063 '''
1064 main() {
1065 int f() => ////
1066 }
1067 ''',
1068 atEnd: true);
1069 _assertHasChange(
1070 'Add a semicolon and newline',
1071 '''
1072 main() {
1073 int f() => ;
1074 ////
1075 }
1076 ''',
1077 (s) => _afterLast(s, '=> '));
1078 }
1079
1080 test_semicolonVar() async {
746 await _prepareCompletion( 1081 await _prepareCompletion(
747 'v = 1', 1082 'v = 1',
748 ''' 1083 '''
749 main() { 1084 main() {
750 int v = 1 1085 int v = 1
751 } 1086 }
752 ''', 1087 ''',
753 atEnd: true); 1088 atEnd: true);
754 _assertHasChange( 1089 _assertHasChange(
755 'Add a semicolon and newline', 1090 'Add a semicolon and newline',
(...skipping 376 matching lines...) Expand 10 before | Expand all | Expand 10 after
1132 ''' 1467 '''
1133 main() { 1468 main() {
1134 while () { 1469 while () {
1135 //// 1470 ////
1136 } 1471 }
1137 } 1472 }
1138 ''', 1473 ''',
1139 (s) => _after(s, 'while (')); 1474 (s) => _after(s, 'while ('));
1140 } 1475 }
1141 } 1476 }
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