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

Side by Side Diff: pkg/analyzer/test/generated/incremental_resolver_test.dart

Issue 2884853002: cleanup unused incremental resolution (Closed)
Patch Set: rebase 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
OLDNEW
(Empty)
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
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.
4
5 library analyzer.test.generated.incremental_resolver_test;
6
7 import 'package:analyzer/dart/ast/ast.dart';
8 import 'package:analyzer/dart/ast/token.dart';
9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/error/error.dart';
11 import 'package:analyzer/error/listener.dart';
12 import 'package:analyzer/exception/exception.dart';
13 import 'package:analyzer/src/context/cache.dart';
14 import 'package:analyzer/src/dart/ast/utilities.dart';
15 import 'package:analyzer/src/dart/element/element.dart';
16 import 'package:analyzer/src/dart/scanner/reader.dart';
17 import 'package:analyzer/src/dart/scanner/scanner.dart';
18 import 'package:analyzer/src/generated/engine.dart';
19 import 'package:analyzer/src/generated/incremental_logger.dart' as logging;
20 import 'package:analyzer/src/generated/incremental_resolution_validator.dart';
21 import 'package:analyzer/src/generated/incremental_resolver.dart';
22 import 'package:analyzer/src/generated/java_engine.dart';
23 import 'package:analyzer/src/generated/parser.dart';
24 import 'package:analyzer/src/generated/resolver.dart';
25 import 'package:analyzer/src/generated/source_io.dart';
26 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
27 import 'package:analyzer/src/generated/testing/element_factory.dart';
28 import 'package:analyzer/src/generated/utilities_collection.dart';
29 import 'package:analyzer/src/task/dart.dart';
30 import 'package:analyzer/task/dart.dart';
31 import 'package:analyzer/task/model.dart';
32 import 'package:test/test.dart';
33 import 'package:test_reflective_loader/test_reflective_loader.dart';
34
35 import 'analysis_context_factory.dart';
36 import 'resolver_test_case.dart';
37 import 'test_support.dart';
38
39 main() {
40 initializeTestEnvironment();
41 defineReflectiveSuite(() {
42 defineReflectiveTests(IncrementalResolverTest);
43 defineReflectiveTests(PoorMansIncrementalResolutionTest);
44 defineReflectiveTests(ResolutionContextBuilderTest);
45 });
46 }
47
48 void initializeTestEnvironment() {}
49
50 void _assertEqualError(AnalysisError incError, AnalysisError fullError) {
51 if (incError.errorCode != fullError.errorCode ||
52 incError.source != fullError.source ||
53 incError.offset != fullError.offset ||
54 incError.length != fullError.length ||
55 incError.message != fullError.message) {
56 StringBuffer buffer = new StringBuffer();
57 buffer.writeln('Found error does not match expected error:');
58 if (incError.errorCode == fullError.errorCode) {
59 buffer.write(' errorCode = ');
60 buffer.write(fullError.errorCode.uniqueName);
61 } else {
62 buffer.write(' Expected errorCode = ');
63 buffer.write(fullError.errorCode.uniqueName);
64 buffer.write(' found ');
65 buffer.write(incError.errorCode.uniqueName);
66 }
67 buffer.writeln();
68 if (incError.source == fullError.source) {
69 buffer.write(' source = ');
70 buffer.write(fullError.source);
71 } else {
72 buffer.write(' Expected source = ');
73 buffer.write(fullError.source);
74 buffer.write(' found ');
75 buffer.write(incError.source);
76 }
77 buffer.writeln();
78 if (incError.offset == fullError.offset) {
79 buffer.write(' offset = ');
80 buffer.write(fullError.offset);
81 } else {
82 buffer.write(' Expected offset = ');
83 buffer.write(fullError.offset);
84 buffer.write(' found ');
85 buffer.write(incError.offset);
86 }
87 buffer.writeln();
88 if (incError.length == fullError.length) {
89 buffer.write(' length = ');
90 buffer.write(fullError.length);
91 } else {
92 buffer.write(' Expected length = ');
93 buffer.write(fullError.length);
94 buffer.write(' found ');
95 buffer.write(incError.length);
96 }
97 buffer.writeln();
98 if (incError.message == fullError.message) {
99 buffer.write(' message = ');
100 buffer.write(fullError.message);
101 } else {
102 buffer.write(' Expected message = ');
103 buffer.write(fullError.message);
104 buffer.write(' found ');
105 buffer.write(incError.message);
106 }
107 fail(buffer.toString());
108 }
109 }
110
111 void _assertEqualErrors(
112 List<AnalysisError> incErrors, List<AnalysisError> fullErrors) {
113 expect(incErrors, hasLength(fullErrors.length));
114 if (incErrors.isNotEmpty) {
115 incErrors.sort((a, b) => a.offset - b.offset);
116 }
117 if (fullErrors.isNotEmpty) {
118 fullErrors.sort((a, b) => a.offset - b.offset);
119 }
120 int length = incErrors.length;
121 for (int i = 0; i < length; i++) {
122 AnalysisError incError = incErrors[i];
123 AnalysisError fullError = fullErrors[i];
124 _assertEqualError(incError, fullError);
125 }
126 }
127
128 void _checkCacheEntries(AnalysisCache cache) {
129 Set seen = new Set();
130 MapIterator<AnalysisTarget, CacheEntry> it = cache.iterator();
131 while (it.moveNext()) {
132 AnalysisTarget key = it.key;
133 if (cache.get(key) == null) {
134 fail("cache corrupted: value of $key changed to null");
135 }
136 if (!seen.add(key)) {
137 fail("cache corrupted: $key appears more than once");
138 }
139 }
140 }
141
142 @reflectiveTest
143 class IncrementalResolverTest extends ResolverTestCase {
144 Source source;
145 String code;
146 LibraryElement library;
147 CompilationUnit unit;
148
149 void setUp() {
150 super.setUp();
151 logging.logger = logging.NULL_LOGGER;
152 }
153
154 void test_classMemberAccessor_body() {
155 _resolveUnit(r'''
156 class A {
157 int get test {
158 return 1 + 2;
159 }
160 }''');
161 _resolve(_editString('+', '*'), _isFunctionBody);
162 }
163
164 void test_computeConstants_offsetChanged() {
165 _resolveUnit(r'''
166 int f() => 0;
167 main() {
168 const x1 = f();
169 const x2 = f();
170 const x3 = f();
171 const x4 = f();
172 const x5 = f();
173 print(x1 + x2 + x3 + x4 + x5 + 1);
174 }
175 ''');
176 _resolve(_editString('x1', ' x1'), _isFunctionBody);
177 }
178
179 void test_constructor_body() {
180 _resolveUnit(r'''
181 class A {
182 int f;
183 A(int a, int b) {
184 f = a + b;
185 }
186 }''');
187 _resolve(_editString('+', '*'), _isFunctionBody);
188 }
189
190 void test_constructor_label_add() {
191 _resolveUnit(r'''
192 class A {
193 A() {
194 return 42;
195 }
196 }
197 ''');
198 _resolve(_editString('return', 'label: return'), _isBlock);
199 }
200
201 void test_constructor_localVariable_add() {
202 _resolveUnit(r'''
203 class A {
204 A() {
205 42;
206 }
207 }
208 ''');
209 _resolve(_editString('42;', 'var res = 42;'), _isBlock);
210 }
211
212 void test_function_localFunction_add() {
213 _resolveUnit(r'''
214 int main() {
215 return 0;
216 }
217 callIt(f) {}
218 ''');
219 _resolve(_editString('return 0;', 'callIt((p) {});'), _isBlock);
220 }
221
222 void test_functionBody_body() {
223 _resolveUnit(r'''
224 main(int a, int b) {
225 return a + b;
226 }''');
227 _resolve(_editString('+', '*'), _isFunctionBody);
228 }
229
230 void test_functionBody_statement() {
231 _resolveUnit(r'''
232 main(int a, int b) {
233 return a + b;
234 }''');
235 _resolve(_editString('+', '*'), _isStatement);
236 }
237
238 void test_method_body() {
239 _resolveUnit(r'''
240 class A {
241 m(int a, int b) {
242 return a + b;
243 }
244 }''');
245 _resolve(_editString('+', '*'), _isFunctionBody);
246 }
247
248 void test_method_label_add() {
249 _resolveUnit(r'''
250 class A {
251 int m(int a, int b) {
252 return a + b;
253 }
254 }
255 ''');
256 _resolve(_editString('return', 'label: return'), _isBlock);
257 }
258
259 void test_method_localFunction_add() {
260 _resolveUnit(r'''
261 class A {
262 int m() {
263 return 0;
264 }
265 }
266 callIt(f) {}
267 ''');
268 _resolve(_editString('return 0;', 'callIt((p) {});'), _isBlock);
269 }
270
271 void test_method_localVariable_add() {
272 _resolveUnit(r'''
273 class A {
274 int m(int a, int b) {
275 return a + b;
276 }
277 }
278 ''');
279 _resolve(
280 _editString(
281 ' return a + b;',
282 r'''
283 int res = a + b;
284 return res;
285 '''),
286 _isBlock);
287 }
288
289 void test_superInvocation() {
290 _resolveUnit(r'''
291 class A {
292 foo(p) {}
293 }
294 class B extends A {
295 bar() {
296 super.foo(1 + 2);
297 }
298 }''');
299 _resolve(_editString('+', '*'), _isFunctionBody);
300 }
301
302 void test_topLevelAccessor_body() {
303 _resolveUnit(r'''
304 int get test {
305 return 1 + 2;
306 }''');
307 _resolve(_editString('+', '*'), _isFunctionBody);
308 }
309
310 void test_topLevelFunction_label_add() {
311 _resolveUnit(r'''
312 int main(int a, int b) {
313 return a + b;
314 }
315 ''');
316 _resolve(_editString(' return', 'label: return a + b;'), _isBlock);
317 }
318
319 void test_topLevelFunction_label_remove() {
320 _resolveUnit(r'''
321 int main(int a, int b) {
322 label: return a + b;
323 }
324 ''');
325 _resolve(_editString('label: ', ''), _isBlock);
326 }
327
328 void test_topLevelFunction_localVariable_add() {
329 _resolveUnit(r'''
330 int main(int a, int b) {
331 return a + b;
332 }
333 ''');
334 _resolve(
335 _editString(
336 ' return a + b;',
337 r'''
338 int res = a + b;
339 return res;
340 '''),
341 _isBlock);
342 }
343
344 void test_topLevelFunction_localVariable_remove() {
345 _resolveUnit(r'''
346 int main(int a, int b) {
347 int res = a * b;
348 return a + b;
349 }
350 ''');
351 _resolve(_editString('int res = a * b;', ''), _isBlock);
352 }
353
354 void test_updateElementOffset() {
355 _resolveUnit(r'''
356 class A {
357 int am(String ap) {
358 int av = 1;
359 return av;
360 }
361 }
362 main(int a, int b) {
363 return a + b;
364 }
365 class B {
366 int bm(String bp) {
367 int bv = 1;
368 return bv;
369 }
370 }
371 ''');
372 _resolve(_editString('+', ' + '), _isStatement);
373 }
374
375 _Edit _editString(String search, String replacement, [int length]) {
376 int offset = code.indexOf(search);
377 expect(offset, isNot(-1));
378 if (length == null) {
379 length = search.length;
380 }
381 return new _Edit(offset, length, replacement);
382 }
383
384 /**
385 * Applies [edit] to [code], find the [AstNode] specified by [predicate]
386 * and incrementally resolves it.
387 *
388 * Then resolves the new code from scratch and validates that results of
389 * the incremental resolution and non-incremental resolutions are the same.
390 */
391 void _resolve(_Edit edit, Predicate<AstNode> predicate) {
392 int offset = edit.offset;
393 // parse "newCode"
394 String newCode = code.substring(0, offset) +
395 edit.replacement +
396 code.substring(offset + edit.length);
397 CompilationUnit newUnit = _parseUnit(newCode);
398 AnalysisCache cache = analysisContext2.analysisCache;
399 _checkCacheEntries(cache);
400
401 // replace the node
402 AstNode oldNode = _findNodeAt(unit, offset, predicate);
403 AstNode newNode = _findNodeAt(newUnit, offset, predicate);
404 {
405 bool success = NodeReplacer.replace(oldNode, newNode);
406 expect(success, isTrue);
407 }
408 // update tokens
409 {
410 int delta = edit.replacement.length - edit.length;
411 _shiftTokens(unit.beginToken, offset, delta);
412 Token oldBeginToken = oldNode.beginToken;
413 Token oldEndTokenNext = oldNode.endToken.next;
414 oldBeginToken.previous.setNext(newNode.beginToken);
415 newNode.endToken.setNext(oldEndTokenNext);
416 }
417 // do incremental resolution
418 int updateOffset = edit.offset;
419 int updateEndOld = updateOffset + edit.length;
420 int updateOldNew = updateOffset + edit.replacement.length;
421 IncrementalResolver resolver;
422 LibrarySpecificUnit lsu = new LibrarySpecificUnit(source, source);
423 resolver = new IncrementalResolver(cache, cache.get(source), cache.get(lsu),
424 unit.element, updateOffset, updateEndOld, updateOldNew);
425
426 BlockFunctionBody body = newNode.getAncestor((n) => n is BlockFunctionBody);
427 expect(body, isNotNull);
428
429 resolver.resolve(body);
430 _checkCacheEntries(cache);
431
432 List<AnalysisError> newErrors = analysisContext.computeErrors(source);
433 // resolve "newCode" from scratch
434 CompilationUnit fullNewUnit;
435 {
436 source = addSource(newCode);
437 _runTasks();
438 LibraryElement library = resolve2(source);
439 fullNewUnit = resolveCompilationUnit(source, library);
440 }
441 _checkCacheEntries(cache);
442
443 assertSameResolution(unit, fullNewUnit);
444 // errors
445 List<AnalysisError> newFullErrors =
446 analysisContext.getErrors(source).errors;
447 _assertEqualErrors(newErrors, newFullErrors);
448 // prepare for the next cycle
449 code = newCode;
450 }
451
452 void _resolveUnit(String code) {
453 this.code = code;
454 source = addSource(code);
455 library = resolve2(source);
456 unit = resolveCompilationUnit(source, library);
457 _runTasks();
458 _checkCacheEntries(analysisContext2.analysisCache);
459 }
460
461 void _runTasks() {
462 AnalysisResult result = analysisContext.performAnalysisTask();
463 while (result.changeNotices != null) {
464 result = analysisContext.performAnalysisTask();
465 }
466 }
467
468 static AstNode _findNodeAt(
469 CompilationUnit oldUnit, int offset, Predicate<AstNode> predicate) {
470 NodeLocator locator = new NodeLocator(offset);
471 AstNode node = locator.searchWithin(oldUnit);
472 return node.getAncestor(predicate);
473 }
474
475 static bool _isBlock(AstNode node) => node is Block;
476
477 static bool _isFunctionBody(AstNode node) => node is FunctionBody;
478
479 static bool _isStatement(AstNode node) => node is Statement;
480
481 static CompilationUnit _parseUnit(String code) {
482 var errorListener = new BooleanErrorListener();
483 var reader = new CharSequenceReader(code);
484 var scanner = new Scanner(null, reader, errorListener);
485 var token = scanner.tokenize();
486 var parser = new Parser(null, errorListener);
487 return parser.parseCompilationUnit(token);
488 }
489
490 static void _shiftTokens(Token token, int afterOffset, int delta) {
491 while (true) {
492 if (token.offset > afterOffset) {
493 token.applyDelta(delta);
494 }
495 if (token.type == TokenType.EOF) {
496 break;
497 }
498 token = token.next;
499 }
500 }
501 }
502
503 /**
504 * The test for [poorMansIncrementalResolution] function and its integration
505 * into [AnalysisContext].
506 */
507 @reflectiveTest
508 class PoorMansIncrementalResolutionTest extends ResolverTestCase {
509 final _TestLogger logger = new _TestLogger();
510
511 Source source;
512 String code;
513 LibraryElement oldLibrary;
514 CompilationUnit oldUnit;
515 CompilationUnitElement oldUnitElement;
516
517 @override
518 void setUp() {
519 super.setUp();
520 _resetWithIncremental(true);
521 }
522
523 void test_computeConstants() {
524 _resolveUnit(r'''
525 int f() => 0;
526 main() {
527 const x = f();
528 print(x + 1);
529 }
530 ''');
531 _updateAndValidate(
532 r'''
533 int f() => 0;
534 main() {
535 const x = f();
536 print(x + 2);
537 }
538 ''',
539 expectCachePostConstantsValid: false);
540 }
541
542 void test_dartDoc_beforeField() {
543 _resolveUnit(r'''
544 class A {
545 /**
546 * A field [field] of type [int] in class [A].
547 */
548 int field;
549 }
550 ''');
551 _updateAndValidate(r'''
552 class A {
553 /**
554 * A field [field] of the type [int] in the class [A].
555 * Updated, with a reference to the [String] type.
556 */
557 int field;
558 }
559 ''');
560 }
561
562 void test_dartDoc_beforeTopLevelVariable() {
563 _resolveUnit(r'''
564 /**
565 * Variables [V1] and [V2] of type [int].
566 */
567 int V1, V2;
568 ''');
569 _updateAndValidate(r'''
570 /**
571 * Variables [V1] and [V2] of type [int].
572 * Updated, with a reference to the [String] type.
573 */
574 int V1, V2;
575 ''');
576 }
577
578 void test_dartDoc_clumsy_addReference() {
579 _resolveUnit(r'''
580 /**
581 * aaa bbbb
582 */
583 main() {
584 }
585 ''');
586 _updateAndValidate(r'''
587 /**
588 * aaa [main] bbbb
589 */
590 main() {
591 }
592 ''');
593 }
594
595 void test_dartDoc_clumsy_removeReference() {
596 _resolveUnit(r'''
597 /**
598 * aaa [main] bbbb
599 */
600 main() {
601 }
602 ''');
603 _updateAndValidate(r'''
604 /**
605 * aaa bbbb
606 */
607 main() {
608 }
609 ''');
610 }
611
612 void test_dartDoc_clumsy_updateText_beforeKeywordToken() {
613 _resolveUnit(r'''
614 /**
615 * A comment with the [int] type reference.
616 */
617 class A {}
618 ''');
619 _updateAndValidate(r'''
620 /**
621 * A comment with the [int] type reference.
622 * Plus reference to [A] itself.
623 */
624 class A {}
625 ''');
626 }
627
628 void test_dartDoc_clumsy_updateText_insert() {
629 _resolveUnit(r'''
630 /**
631 * A function [main] with a parameter [p] of type [int].
632 */
633 main(int p) {
634 unresolvedFunctionProblem();
635 }
636 /**
637 * Other comment with [int] reference.
638 */
639 foo() {}
640 ''');
641 _updateAndValidate(r'''
642 /**
643 * A function [main] with a parameter [p] of type [int].
644 * Inserted text with [String] reference.
645 */
646 main(int p) {
647 unresolvedFunctionProblem();
648 }
649 /**
650 * Other comment with [int] reference.
651 */
652 foo() {}
653 ''');
654 }
655
656 void test_dartDoc_clumsy_updateText_remove() {
657 _resolveUnit(r'''
658 /**
659 * A function [main] with a parameter [p] of type [int].
660 * Some text with [String] reference to remove.
661 */
662 main(int p) {
663 }
664 /**
665 * Other comment with [int] reference.
666 */
667 foo() {}
668 ''');
669 _updateAndValidate(r'''
670 /**
671 * A function [main] with a parameter [p] of type [int].
672 */
673 main(int p) {
674 }
675 /**
676 * Other comment with [int] reference.
677 */
678 foo() {}
679 ''');
680 }
681
682 void test_dartDoc_elegant_addReference() {
683 _resolveUnit(r'''
684 /// aaa bbb
685 main() {
686 return 1;
687 }
688 ''');
689 _updateAndValidate(r'''
690 /// aaa [main] bbb
691 /// ccc [int] ddd
692 main() {
693 return 1;
694 }
695 ''');
696 }
697
698 void test_dartDoc_elegant_removeReference() {
699 _resolveUnit(r'''
700 /// aaa [main] bbb
701 /// ccc [int] ddd
702 main() {
703 return 1;
704 }
705 ''');
706 _updateAndValidate(r'''
707 /// aaa bbb
708 main() {
709 return 1;
710 }
711 ''');
712 }
713
714 void test_dartDoc_elegant_updateText_insertToken() {
715 _resolveUnit(r'''
716 /// A
717 /// [int]
718 class Test {
719 }
720 ''');
721 _updateAndValidate(r'''
722 /// A
723 ///
724 /// [int]
725 class Test {
726 }
727 ''');
728 }
729
730 void test_dartDoc_elegant_updateText_removeToken() {
731 _resolveUnit(r'''
732 /// A
733 ///
734 /// [int]
735 class Test {
736 }
737 ''');
738 _updateAndValidate(r'''
739 /// A
740 /// [int]
741 class Test {
742 }
743 ''');
744 }
745
746 void test_endOfLineComment_add_beforeKeywordToken() {
747 _resolveUnit(r'''
748 main() {
749 var v = 42;
750 }
751 ''');
752 _updateAndValidate(r'''
753 main() {
754 // some comment
755 var v = 42;
756 }
757 ''');
758 }
759
760 void test_endOfLineComment_add_beforeStringToken() {
761 _resolveUnit(r'''
762 main() {
763 print(0);
764 }
765 ''');
766 _updateAndValidate(r'''
767 main() {
768 // some comment
769 print(0);
770 }
771 ''');
772 }
773
774 void test_endOfLineComment_edit() {
775 _resolveUnit(r'''
776 main() {
777 // some comment
778 print(0);
779 }
780 ''');
781 _updateAndValidate(r'''
782 main() {
783 // edited comment text
784 print(0);
785 }
786 ''');
787 }
788
789 void test_endOfLineComment_outBody_add() {
790 _resolveUnit(r'''
791 main() {
792 Object x;
793 x.foo();
794 }
795 ''');
796 _updateAndValidate(
797 r'''
798 // 000
799 main() {
800 Object x;
801 x.foo();
802 }
803 ''',
804 expectedSuccess: false);
805 }
806
807 void test_endOfLineComment_outBody_remove() {
808 _resolveUnit(r'''
809 // 000
810 main() {
811 Object x;
812 x.foo();
813 }
814 ''');
815 _updateAndValidate(
816 r'''
817 main() {
818 Object x;
819 x.foo();
820 }
821 ''',
822 expectedSuccess: false);
823 }
824
825 void test_endOfLineComment_outBody_update() {
826 _resolveUnit(r'''
827 // 000
828 main() {
829 Object x;
830 x.foo();
831 }
832 ''');
833 _updateAndValidate(
834 r'''
835 // 10
836 main() {
837 Object x;
838 x.foo();
839 }
840 ''',
841 expectedSuccess: false);
842 }
843
844 void test_endOfLineComment_remove() {
845 _resolveUnit(r'''
846 main() {
847 // some comment
848 print(0);
849 }
850 ''');
851 _updateAndValidate(r'''
852 main() {
853 print(0);
854 }
855 ''');
856 }
857
858 void test_endOfLineComment_toDartDoc() {
859 _resolveUnit(r'''
860 class A {
861 // text
862 main() {
863 print(42);
864 }
865 }''');
866 _updateAndValidate(
867 r'''
868 class A {
869 /// text
870 main() {
871 print(42);
872 }
873 }''',
874 expectedSuccess: false);
875 }
876
877 void test_false_constConstructor_initializer() {
878 _resolveUnit(r'''
879 class C {
880 final int x;
881 const C(this.x);
882 const C.foo() : x = 0;
883 }
884 main() {
885 const {const C(0): 0, const C.foo(): 1};
886 }
887 ''');
888 _updateAndValidate(
889 r'''
890 class C {
891 final int x;
892 const C(this.x);
893 const C.foo() : x = 1;
894 }
895 main() {
896 const {const C(0): 0, const C.foo(): 1};
897 }
898 ''',
899 expectedSuccess: false);
900 }
901
902 void test_false_constructor_initializer_damage() {
903 _resolveUnit(r'''
904 class Problem {
905 final Map location;
906 final String message;
907
908 Problem(Map json)
909 : location = json["location"],
910 message = json["message"];
911 }''');
912 _updateAndValidate(
913 r'''
914 class Problem {
915 final Map location;
916 final String message;
917
918 Problem(Map json)
919 : location = json["location],
920 message = json["message"];
921 }''',
922 expectedSuccess: false);
923 }
924
925 void test_false_constructor_initializer_remove() {
926 _resolveUnit(r'''
927 class Problem {
928 final String severity;
929 final Map location;
930 final String message;
931
932 Problem(Map json)
933 : severity = json["severity"],
934 location = json["location"],
935 message = json["message"];
936 }''');
937 _updateAndValidate(
938 r'''
939 class Problem {
940 final String severity;
941 final Map location;
942 final String message;
943
944 Problem(Map json)
945 : severity = json["severity"],
946 message = json["message"];
947 }''',
948 expectedSuccess: false);
949 }
950
951 void test_false_endOfLineComment_localFunction_inTopLevelVariable() {
952 _resolveUnit(r'''
953 typedef int Binary(one, two, three);
954
955 int Global = f((a, b, c) {
956 return 0; // Some comment
957 });
958 ''');
959 _updateAndValidate(
960 r'''
961 typedef int Binary(one, two, three);
962
963 int Global = f((a, b, c) {
964 return 0; // Some comment
965 });
966 ''',
967 expectedSuccess: false);
968 }
969
970 void test_false_expressionBody() {
971 _resolveUnit(r'''
972 class A {
973 final f = (() => 1)();
974 }
975 ''');
976 _updateAndValidate(
977 r'''
978 class A {
979 final f = (() => 2)();
980 }
981 ''',
982 expectedSuccess: false);
983 }
984
985 void test_false_expressionBody2() {
986 _resolveUnit(r'''
987 class A {
988 int m() => 10 * 10;
989 }
990 ''');
991 _updateAndValidate(
992 r'''
993 class A {
994 int m() => 10 * 100;
995 }
996 ''',
997 expectedSuccess: false);
998 }
999
1000 void test_false_inBody_addAsync() {
1001 _resolveUnit(r'''
1002 class C {
1003 test() {}
1004 }
1005 ''');
1006 _updateAndValidate(
1007 r'''
1008 class C {
1009 test() async {}
1010 }
1011 ''',
1012 expectedSuccess: false);
1013 }
1014
1015 void test_false_inBody_async_addStar() {
1016 _resolveUnit(r'''
1017 import 'dart:async';
1018 class C {
1019 Stream test() async {}
1020 }
1021 ''');
1022 _updateAndValidate(
1023 r'''
1024 import 'dart:async';
1025 class C {
1026 Stream test() async* {}
1027 }
1028 ''',
1029 expectedSuccess: false);
1030 }
1031
1032 void test_false_inBody_async_removeStar() {
1033 _resolveUnit(r'''
1034 import 'dart:async';
1035 class C {
1036 Stream test() async* {}
1037 }
1038 ''');
1039 _updateAndValidate(
1040 r'''
1041 import 'dart:async';
1042 class C {
1043 Stream test() async {}
1044 }
1045 ''',
1046 expectedSuccess: false);
1047 }
1048
1049 void test_false_inBody_functionExpression() {
1050 _resolveUnit(r'''
1051 class C extends D {
1052 static final f = () {
1053 var x = 0;
1054 }();
1055 }
1056
1057 class D {}
1058 ''');
1059 _updateAndValidate(
1060 r'''
1061 class C extends D {
1062 static final f = () {
1063 var x = 01;
1064 }();
1065 }
1066
1067 class D {}
1068 ''',
1069 expectedSuccess: false);
1070 }
1071
1072 void test_false_inBody_removeAsync() {
1073 _resolveUnit(r'''
1074 class C {
1075 test() async {}
1076 }
1077 ''');
1078 _updateAndValidate(
1079 r'''
1080 class C {
1081 test() {}
1082 }
1083 ''',
1084 expectedSuccess: false);
1085 }
1086
1087 void test_false_inBody_sync_addStar() {
1088 _resolveUnit(r'''
1089 class C {
1090 test() {}
1091 }
1092 ''');
1093 _updateAndValidate(
1094 r'''
1095 class C {
1096 test() sync* {}
1097 }
1098 ''',
1099 expectedSuccess: false);
1100 }
1101
1102 void test_false_topLevelFunction_name() {
1103 _resolveUnit(r'''
1104 a() {}
1105 b() {}
1106 ''');
1107 _updateAndValidate(
1108 r'''
1109 a() {}
1110 bb() {}
1111 ''',
1112 expectedSuccess: false);
1113 }
1114
1115 void test_false_unbalancedCurlyBrackets_inNew() {
1116 _resolveUnit(r'''
1117 class A {
1118 aaa() {
1119 if (true) {
1120 1;
1121 }
1122 }
1123
1124 bbb() {
1125 print(0123456789);
1126 }
1127 }''');
1128 _updateAndValidate(
1129 r'''
1130 class A {
1131 aaa() {
1132 1;
1133 }
1134 }
1135
1136 bbb() {
1137 print(0123456789);
1138 }
1139 }''',
1140 expectedSuccess: false);
1141 }
1142
1143 void test_false_unbalancedCurlyBrackets_inOld() {
1144 _resolveUnit(r'''
1145 class A {
1146 aaa() {
1147 1;
1148 }
1149 }
1150
1151 bbb() {
1152 print(0123456789);
1153 }
1154 }''');
1155 _updateAndValidate(
1156 r'''
1157 class A {
1158 aaa() {
1159 if (true) {
1160 1;
1161 }
1162 }
1163
1164 bbb() {
1165 print(0123456789);
1166 }
1167 }''',
1168 expectedSuccess: false);
1169 }
1170
1171 void test_false_wholeConstructor() {
1172 _resolveUnit(r'''
1173 class A {
1174 A(int a) {
1175 print(a);
1176 }
1177 }
1178 ''');
1179 _updateAndValidate(
1180 r'''
1181 class A {
1182 A(int b) {
1183 print(b);
1184 }
1185 }
1186 ''',
1187 expectedSuccess: false);
1188 }
1189
1190 void test_false_wholeConstructor_addInitializer() {
1191 _resolveUnit(r'''
1192 class A {
1193 int field;
1194 A();
1195 }
1196 ''');
1197 _updateAndValidate(
1198 r'''
1199 class A {
1200 int field;
1201 A() : field = 5;
1202 }
1203 ''',
1204 expectedSuccess: false);
1205 }
1206
1207 void test_false_wholeFunction() {
1208 _resolveUnit(r'''
1209 foo() {}
1210 main(int a) {
1211 print(a);
1212 }
1213 ''');
1214 _updateAndValidate(
1215 r'''
1216 foo() {}
1217 main(int b) {
1218 print(b);
1219 }
1220 ''',
1221 expectedSuccess: false);
1222 }
1223
1224 void test_false_wholeMethod() {
1225 _resolveUnit(r'''
1226 class A {
1227 main(int a) {
1228 print(a);
1229 }
1230 }
1231 ''');
1232 _updateAndValidate(
1233 r'''
1234 class A {
1235 main(int b) {
1236 print(b);
1237 }
1238 }
1239 ''',
1240 expectedSuccess: false);
1241 }
1242
1243 void test_fieldClassField_propagatedType() {
1244 _resolveUnit(r'''
1245 class A {
1246 static const A b = const B();
1247 const A();
1248 }
1249
1250 class B extends A {
1251 const B();
1252 }
1253
1254 main() {
1255 print(12);
1256 A.b;
1257 }
1258 ''');
1259 _updateAndValidate(r'''
1260 class A {
1261 static const A b = const B();
1262 const A();
1263 }
1264
1265 class B extends A {
1266 const B();
1267 }
1268
1269 main() {
1270 print(123);
1271 A.b;
1272 }
1273 ''');
1274 }
1275
1276 void test_hasElementAfter_defaultParameter() {
1277 _resolveUnit(r'''
1278 main() {
1279 print(1);
1280 }
1281 otherFunction([p = 0]) {}
1282 ''');
1283 _updateAndValidate(r'''
1284 main() {
1285 print(2);
1286 }
1287 otherFunction([p = 0]) {}
1288 ''');
1289 }
1290
1291 void test_inBody_expression() {
1292 _resolveUnit(r'''
1293 class A {
1294 m() {
1295 print(1);
1296 }
1297 }
1298 ''');
1299 _updateAndValidate(r'''
1300 class A {
1301 m() {
1302 print(2 + 3);
1303 }
1304 }
1305 ''');
1306 }
1307
1308 void test_inBody_insertStatement() {
1309 _resolveUnit(r'''
1310 main() {
1311 print(1);
1312 }
1313 ''');
1314 _updateAndValidate(r'''
1315 main() {
1316 print(0);
1317 print(1);
1318 }
1319 ''');
1320 }
1321
1322 void test_inBody_tokenToNode() {
1323 _resolveUnit(r'''
1324 main() {
1325 var v = 42;
1326 print(v);
1327 }
1328 ''');
1329 _updateAndValidate(r'''
1330 main() {
1331 int v = 42;
1332 print(v);
1333 }
1334 ''');
1335 }
1336
1337 void test_multiple_emptyLine() {
1338 _resolveUnit(r'''
1339 class A {
1340 m() {
1341 return true;
1342 }
1343 }''');
1344 for (int i = 0; i < 6; i++) {
1345 if (i.isEven) {
1346 _updateAndValidate(
1347 r'''
1348 class A {
1349 m() {
1350 return true;
1351
1352 }
1353 }''',
1354 compareWithFull: false);
1355 } else {
1356 _updateAndValidate(
1357 r'''
1358 class A {
1359 m() {
1360 return true;
1361 }
1362 }''',
1363 compareWithFull: false);
1364 }
1365 }
1366 }
1367
1368 void test_multiple_expression() {
1369 _resolveUnit(r'''
1370 main() {
1371 print(1);
1372 }''');
1373 for (int i = 0; i < 6; i++) {
1374 if (i.isEven) {
1375 _updateAndValidate(
1376 r'''
1377 main() {
1378 print(12);
1379 }''',
1380 compareWithFull: false);
1381 } else {
1382 _updateAndValidate(
1383 r'''
1384 main() {
1385 print(1);
1386 }''',
1387 compareWithFull: false);
1388 }
1389 }
1390 }
1391
1392 void test_strongMode_typeComments_insertWhitespace() {
1393 _resolveUnit(r'''
1394 import 'dart:async';
1395
1396 void fadeIn(int milliseconds) {
1397 Future<String> f;
1398 f.then/*<String>*/((e) {print("hello");});
1399 }
1400 ''');
1401 _updateAndValidate(r'''
1402 import 'dart:async';
1403
1404 void fadeIn(int milliseconds) {
1405 Future<String> f;
1406 f.then/*<String>*/((e) {print("hello") ;});
1407 }
1408 ''');
1409 }
1410
1411 void test_true_emptyLine_betweenClassMembers_insert() {
1412 _resolveUnit(r'''
1413 class A {
1414 a() {}
1415 b() {}
1416 }
1417 ''');
1418 _updateAndValidate(r'''
1419 class A {
1420 a() {}
1421
1422 b() {}
1423 }
1424 ''');
1425 }
1426
1427 void test_true_emptyLine_betweenClassMembers_insert_beforeComment() {
1428 _resolveUnit(r'''
1429 class A {
1430 a() {}
1431 /// BBB
1432 b() {}
1433 }
1434 ''');
1435 _updateAndValidate(r'''
1436 class A {
1437 a() {}
1438
1439 /// BBB
1440 b() {}
1441 }
1442 ''');
1443 }
1444
1445 void test_true_emptyLine_betweenClassMembers_remove() {
1446 _resolveUnit(r'''
1447 class A {
1448 a() {}
1449
1450 b() {}
1451 }
1452 ''');
1453 _updateAndValidate(r'''
1454 class A {
1455 a() {}
1456 b() {}
1457 }
1458 ''');
1459 }
1460
1461 void test_true_emptyLine_betweenClassMembers_remove_beforeComment() {
1462 _resolveUnit(r'''
1463 class A {
1464 a() {}
1465
1466 /// BBB
1467 b() {}
1468 }
1469 ''');
1470 _updateAndValidate(r'''
1471 class A {
1472 a() {}
1473 /// BBB
1474 b() {}
1475 }
1476 ''');
1477 }
1478
1479 void test_true_emptyLine_betweenUnitMembers_insert() {
1480 _resolveUnit(r'''
1481 a() {}
1482 b() {}
1483 ''');
1484 _updateAndValidate(r'''
1485 a() {}
1486
1487 b() {}
1488 ''');
1489 }
1490
1491 void test_true_emptyLine_betweenUnitMembers_insert_beforeComment() {
1492 _resolveUnit(r'''
1493 a() {}
1494
1495 // BBB
1496 b() {}
1497 ''');
1498 _updateAndValidate(r'''
1499 a() {}
1500
1501
1502 // BBB
1503 b() {}
1504 ''');
1505 }
1506
1507 void test_true_emptyLine_betweenUnitMembers_remove() {
1508 _resolveUnit(r'''
1509 a() {
1510 print(1)
1511 }
1512
1513 b() {
1514 foo(42);
1515 }
1516 foo(String p) {}
1517 ''');
1518 _updateAndValidate(r'''
1519 a() {
1520 print(1)
1521 }
1522 b() {
1523 foo(42);
1524 }
1525 foo(String p) {}
1526 ''');
1527 }
1528
1529 void test_true_emptyLine_betweenUnitMembers_remove_beforeComment() {
1530 _resolveUnit(r'''
1531 a() {}
1532
1533 // BBB
1534 b() {}
1535 ''');
1536 _updateAndValidate(r'''
1537 a() {}
1538 // BBB
1539 b() {}
1540 ''');
1541 }
1542
1543 void test_true_todoHint() {
1544 _resolveUnit(r'''
1545 main() {
1546 print(1);
1547 }
1548 foo() {
1549 // TODO
1550 }
1551 ''');
1552 List<AnalysisError> oldErrors = analysisContext.computeErrors(source);
1553 _updateAndValidate(r'''
1554 main() {
1555 print(2);
1556 }
1557 foo() {
1558 // TODO
1559 }
1560 ''');
1561 List<AnalysisError> newErrors = analysisContext.computeErrors(source);
1562 _assertEqualErrors(newErrors, oldErrors);
1563 }
1564
1565 void test_unusedHint_add_wasUsedOnlyInPart() {
1566 Source partSource = addNamedSource(
1567 '/my_unit.dart',
1568 r'''
1569 part of lib;
1570
1571 f(A a) {
1572 a._foo();
1573 }
1574 ''');
1575 _resolveUnit(r'''
1576 library lib;
1577 part 'my_unit.dart';
1578 class A {
1579 _foo() {
1580 print(1);
1581 }
1582 }
1583 ''');
1584 _runTasks();
1585 // perform incremental resolution
1586 _resetWithIncremental(true);
1587 analysisContext2.setContents(
1588 partSource,
1589 r'''
1590 part of lib;
1591
1592 f(A a) {
1593 // a._foo();
1594 }
1595 ''');
1596 // no hints right now, because we delay hints computing
1597 {
1598 List<AnalysisError> errors = analysisContext.getErrors(source).errors;
1599 expect(errors, isEmpty);
1600 }
1601 // a new hint should be added
1602 List<AnalysisError> errors = analysisContext.computeErrors(source);
1603 expect(errors, hasLength(1));
1604 expect(errors[0].errorCode.type, ErrorType.HINT);
1605 // the same hint should be reported using a ChangeNotice
1606 bool noticeFound = false;
1607 AnalysisResult result = analysisContext2.performAnalysisTask();
1608 for (ChangeNotice notice in result.changeNotices) {
1609 if (notice.source == source) {
1610 expect(notice.errors, contains(errors[0]));
1611 noticeFound = true;
1612 }
1613 }
1614 expect(noticeFound, isTrue);
1615 }
1616
1617 void test_unusedHint_false_stillUsedInPart() {
1618 addNamedSource(
1619 '/my_unit.dart',
1620 r'''
1621 part of lib;
1622
1623 f(A a) {
1624 a._foo();
1625 }
1626 ''');
1627 _resolveUnit(r'''
1628 library lib;
1629 part 'my_unit.dart';
1630 class A {
1631 _foo() {
1632 print(1);
1633 }
1634 }
1635 ''');
1636 // perform incremental resolution
1637 _resetWithIncremental(true);
1638 analysisContext2.setContents(
1639 source,
1640 r'''
1641 library lib;
1642 part 'my_unit.dart';
1643 class A {
1644 _foo() {
1645 print(12);
1646 }
1647 }
1648 ''');
1649 // no hints
1650 List<AnalysisError> errors = analysisContext.getErrors(source).errors;
1651 expect(errors, isEmpty);
1652 }
1653
1654 void test_updateConstantInitializer() {
1655 _resolveUnit(r'''
1656 main() {
1657 const v = const [Unknown];
1658 }
1659 ''');
1660 _updateAndValidate(
1661 r'''
1662 main() {
1663 const v = const [Unknown];
1664 }
1665 ''',
1666 expectCachePostConstantsValid: false);
1667 }
1668
1669 void test_updateErrors_addNew_hint1() {
1670 _resolveUnit(r'''
1671 int main() {
1672 return 42;
1673 }
1674 ''');
1675 _updateAndValidate(r'''
1676 int main() {
1677 }
1678 ''');
1679 }
1680
1681 void test_updateErrors_addNew_hint2() {
1682 _resolveUnit(r'''
1683 main() {
1684 int v = 0;
1685 print(v);
1686 }
1687 ''');
1688 _updateAndValidate(r'''
1689 main() {
1690 int v = 0;
1691 }
1692 ''');
1693 }
1694
1695 void test_updateErrors_addNew_parse() {
1696 _resolveUnit(r'''
1697 main() {
1698 print(42);
1699 }
1700 ''');
1701 _updateAndValidate(r'''
1702 main() {
1703 print(42)
1704 }
1705 ''');
1706 }
1707
1708 void test_updateErrors_addNew_resolve() {
1709 _resolveUnit(r'''
1710 main() {
1711 foo();
1712 }
1713 foo() {}
1714 ''');
1715 _updateAndValidate(r'''
1716 main() {
1717 bar();
1718 }
1719 foo() {}
1720 ''');
1721 }
1722
1723 void test_updateErrors_addNew_resolve2() {
1724 _resolveUnit(r'''
1725 // this comment is important to reproduce the problem
1726 main() {
1727 int vvv = 42;
1728 print(vvv);
1729 }
1730 ''');
1731 _updateAndValidate(r'''
1732 // this comment is important to reproduce the problem
1733 main() {
1734 int vvv = 42;
1735 print(vvv2);
1736 }
1737 ''');
1738 }
1739
1740 void test_updateErrors_addNew_scan() {
1741 _resolveUnit(r'''
1742 main() {
1743 1;
1744 }
1745 ''');
1746 _updateAndValidate(r'''
1747 main() {
1748 1e;
1749 }
1750 ''');
1751 }
1752
1753 void test_updateErrors_addNew_verify() {
1754 _resolveUnit(r'''
1755 main() {
1756 foo(0);
1757 }
1758 foo(int p) {}
1759 ''');
1760 _updateAndValidate(r'''
1761 main() {
1762 foo('abc');
1763 }
1764 foo(int p) {}
1765 ''');
1766 }
1767
1768 void test_updateErrors_invalidVerifyErrors() {
1769 _resolveUnit(r'''
1770 main() {
1771 foo('aaa');
1772 }
1773 main2() {
1774 foo('bbb');
1775 }
1776 foo(int p) {}
1777 ''');
1778 // Complete analysis, e.g. compute VERIFY_ERRORS.
1779 _runTasks();
1780 // Invalidate VERIFY_ERRORS.
1781 AnalysisCache cache = analysisContext2.analysisCache;
1782 LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
1783 CacheEntry cacheEntry = cache.get(target);
1784 expect(cacheEntry.getValue(VERIFY_ERRORS), hasLength(2));
1785 cacheEntry.setState(VERIFY_ERRORS, CacheState.INVALID);
1786 // Perform incremental resolution.
1787 _resetWithIncremental(true);
1788 analysisContext2.setContents(
1789 source,
1790 r'''
1791 main() {
1792 foo(0);
1793 }
1794 main2() {
1795 foo('bbb');
1796 }
1797 foo(int p) {}
1798 ''');
1799 // VERIFY_ERRORS is still invalid.
1800 expect(cacheEntry.getState(VERIFY_ERRORS), CacheState.INVALID);
1801 // Continue analysis - run tasks, so recompute VERIFY_ERRORS.
1802 _runTasks();
1803 expect(cacheEntry.getState(VERIFY_ERRORS), CacheState.VALID);
1804 expect(cacheEntry.getValue(VERIFY_ERRORS), hasLength(1));
1805 }
1806
1807 void test_updateErrors_removeExisting_hint() {
1808 _resolveUnit(r'''
1809 int main() {
1810 }
1811 ''');
1812 _updateAndValidate(r'''
1813 int main() {
1814 return 42;
1815 }
1816 ''');
1817 }
1818
1819 void test_updateErrors_removeExisting_verify() {
1820 _resolveUnit(r'''
1821 f1() {
1822 print(1)
1823 }
1824 f2() {
1825 print(22)
1826 }
1827 f3() {
1828 print(333)
1829 }
1830 ''');
1831 _updateAndValidate(r'''
1832 f1() {
1833 print(1)
1834 }
1835 f2() {
1836 print(22);
1837 }
1838 f3() {
1839 print(333)
1840 }
1841 ''');
1842 }
1843
1844 void test_updateErrors_shiftExisting() {
1845 _resolveUnit(r'''
1846 f1() {
1847 print(1)
1848 }
1849 f2() {
1850 print(2);
1851 }
1852 f3() {
1853 print(333)
1854 }
1855 ''');
1856 _updateAndValidate(r'''
1857 f1() {
1858 print(1)
1859 }
1860 f2() {
1861 print(22);
1862 }
1863 f3() {
1864 print(333)
1865 }
1866 ''');
1867 }
1868
1869 void test_updateFunctionToForLoop() {
1870 _resolveUnit(r'''
1871 class PlayDrag {
1872 final List<num> times = new List<num>();
1873
1874 PlayDrag.start() {}
1875
1876 void update(num pos) {
1877 fo (int i = times.length - 2; i >= 0; i--) {}
1878 }
1879 }
1880 ''');
1881
1882 _updateAndValidate(
1883 r'''
1884 class PlayDrag {
1885 final List<num> times = new List<num>();
1886
1887 PlayDrag.start() {}
1888
1889 void update(num pos) {
1890 for (int i = times.length - 2; i >= 0; i--) {}
1891 }
1892 }
1893 ''',
1894 expectLibraryUnchanged: false);
1895 }
1896
1897 void test_visibleRange() {
1898 _resolveUnit(r'''
1899 class Test {
1900 method1(p1) {
1901 var v1;
1902 f1() {}
1903 return 1;
1904 }
1905 method2(p2) {
1906 var v2;
1907 f2() {}
1908 return 2;
1909 }
1910 method3(p3) {
1911 var v3;
1912 f3() {}
1913 return 3;
1914 }
1915 }
1916 ''');
1917 _updateAndValidate(r'''
1918 class Test {
1919 method1(p1) {
1920 var v1;
1921 f1() {}
1922 return 1;
1923 }
1924 method2(p2) {
1925 var v2;
1926 f2() {}
1927 return 2222;
1928 }
1929 method3(p3) {
1930 var v3;
1931 f3() {}
1932 return 3;
1933 }
1934 }
1935 ''');
1936 }
1937
1938 void test_whitespace_getElementAt() {
1939 _resolveUnit(r'''
1940 class A {}
1941 class B extends A {}
1942 ''');
1943 {
1944 ClassElement typeA = oldUnitElement.getType('A');
1945 expect(oldUnitElement.getElementAt(typeA.nameOffset), typeA);
1946 }
1947 {
1948 ClassElement typeB = oldUnitElement.getType('B');
1949 expect(oldUnitElement.getElementAt(typeB.nameOffset), typeB);
1950 }
1951 _updateAndValidate(r'''
1952 class A {}
1953
1954 class B extends A {}
1955 ''');
1956 // getElementAt() caches results, it should be notified when offset
1957 // are changed.
1958 {
1959 ClassElement typeA = oldUnitElement.getType('A');
1960 expect(oldUnitElement.getElementAt(typeA.nameOffset), typeA);
1961 }
1962 {
1963 ClassElement typeB = oldUnitElement.getType('B');
1964 expect(oldUnitElement.getElementAt(typeB.nameOffset), typeB);
1965 }
1966 }
1967
1968 void _assertCacheResults(
1969 {bool expectLibraryUnchanged: true,
1970 bool expectCachePostConstantsValid: true}) {
1971 _assertCacheSourceResult(TOKEN_STREAM);
1972 _assertCacheSourceResult(SCAN_ERRORS);
1973 _assertCacheSourceResult(PARSED_UNIT);
1974 _assertCacheSourceResult(PARSE_ERRORS);
1975 if (!expectLibraryUnchanged) {
1976 return;
1977 }
1978 _assertCacheSourceResult(LIBRARY_ELEMENT1);
1979 _assertCacheSourceResult(LIBRARY_ELEMENT2);
1980 _assertCacheSourceResult(LIBRARY_ELEMENT3);
1981 _assertCacheSourceResult(LIBRARY_ELEMENT4);
1982 _assertCacheSourceResult(LIBRARY_ELEMENT5);
1983 _assertCacheSourceResult(LIBRARY_ELEMENT6);
1984 _assertCacheSourceResult(LIBRARY_ELEMENT7);
1985 _assertCacheSourceResult(LIBRARY_ELEMENT8);
1986 _assertCacheSourceResult(LIBRARY_ELEMENT9);
1987 if (expectCachePostConstantsValid) {
1988 _assertCacheSourceResult(LIBRARY_ELEMENT);
1989 }
1990 _assertCacheUnitResult(RESOLVED_UNIT1);
1991 _assertCacheUnitResult(RESOLVED_UNIT2);
1992 _assertCacheUnitResult(RESOLVED_UNIT3);
1993 _assertCacheUnitResult(RESOLVED_UNIT4);
1994 _assertCacheUnitResult(RESOLVED_UNIT5);
1995 _assertCacheUnitResult(RESOLVED_UNIT6);
1996 _assertCacheUnitResult(RESOLVED_UNIT7);
1997 _assertCacheUnitResult(RESOLVED_UNIT8);
1998 _assertCacheUnitResult(RESOLVED_UNIT9);
1999 _assertCacheUnitResult(RESOLVED_UNIT10);
2000 _assertCacheUnitResult(RESOLVED_UNIT11);
2001 if (expectCachePostConstantsValid) {
2002 _assertCacheUnitResult(RESOLVED_UNIT12);
2003 _assertCacheUnitResult(RESOLVED_UNIT);
2004 }
2005 }
2006
2007 /**
2008 * Assert that the [result] of [source] is not INVALID.
2009 */
2010 void _assertCacheSourceResult(ResultDescriptor result) {
2011 AnalysisCache cache = analysisContext2.analysisCache;
2012 CacheState state = cache.getState(source, result);
2013 expect(state, isNot(CacheState.INVALID), reason: result.toString());
2014 }
2015
2016 /**
2017 * Assert that the [result] of the defining unit [source] is not INVALID.
2018 */
2019 void _assertCacheUnitResult(ResultDescriptor result) {
2020 AnalysisCache cache = analysisContext2.analysisCache;
2021 LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
2022 CacheState state = cache.getState(target, result);
2023 expect(state, isNot(CacheState.INVALID), reason: result.toString());
2024 }
2025
2026 void _assertEqualLineInfo(LineInfo incLineInfo, LineInfo fullLineInfo) {
2027 for (int offset = 0; offset < 1000; offset++) {
2028 LineInfo_Location incLocation = incLineInfo.getLocation(offset);
2029 LineInfo_Location fullLocation = fullLineInfo.getLocation(offset);
2030 if (incLocation.lineNumber != fullLocation.lineNumber ||
2031 incLocation.columnNumber != fullLocation.columnNumber) {
2032 fail('At offset $offset ' +
2033 '(${incLocation.lineNumber}, ${incLocation.columnNumber})' +
2034 ' != ' +
2035 '(${fullLocation.lineNumber}, ${fullLocation.columnNumber})');
2036 }
2037 }
2038 }
2039
2040 /**
2041 * Reset the analysis context to have the 'incremental' option set to the
2042 * given value.
2043 */
2044 void _resetWithIncremental(bool enable) {
2045 AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
2046 analysisOptions.strongMode = true;
2047 analysisOptions.incremental = enable;
2048 analysisOptions.incrementalApi = enable;
2049 logging.logger = logger;
2050 analysisContext2.analysisOptions = analysisOptions;
2051 }
2052
2053 void _resolveUnit(String code) {
2054 this.code = code;
2055 source = addSource(code);
2056 oldLibrary = resolve2(source);
2057 oldUnit = resolveCompilationUnit(source, oldLibrary);
2058 oldUnitElement = oldUnit.element;
2059 }
2060
2061 void _runTasks() {
2062 AnalysisResult result = analysisContext.performAnalysisTask();
2063 while (result.changeNotices != null) {
2064 result = analysisContext.performAnalysisTask();
2065 }
2066 }
2067
2068 void _updateAndValidate(String newCode,
2069 {bool expectedSuccess: true,
2070 bool expectLibraryUnchanged: true,
2071 bool expectCachePostConstantsValid: true,
2072 bool compareWithFull: true,
2073 bool runTasksBeforeIncremental: true}) {
2074 // Run any pending tasks tasks.
2075 if (runTasksBeforeIncremental) {
2076 _runTasks();
2077 }
2078 // Update the source - currently this may cause incremental resolution.
2079 // Then request the updated resolved unit.
2080 _resetWithIncremental(true);
2081 analysisContext2.setContents(source, newCode);
2082 CompilationUnit newUnit = resolveCompilationUnit(source, oldLibrary);
2083 logger.expectNoErrors();
2084 List<AnalysisError> newErrors = analysisContext.computeErrors(source);
2085 LineInfo newLineInfo = analysisContext.getLineInfo(source);
2086 // check for expected failure
2087 if (!expectedSuccess) {
2088 expect(newUnit.element, isNot(same(oldUnitElement)));
2089 return;
2090 }
2091 // The cache must still have enough results to make the incremental
2092 // resolution useful.
2093 _assertCacheResults(
2094 expectLibraryUnchanged: expectLibraryUnchanged,
2095 expectCachePostConstantsValid: expectCachePostConstantsValid);
2096 // The existing CompilationUnit[Element] should be updated.
2097 expect(newUnit, same(oldUnit));
2098 expect(newUnit.element, same(oldUnitElement));
2099 expect(analysisContext.getResolvedCompilationUnit(source, oldLibrary),
2100 same(oldUnit));
2101 // The only expected pending task should return the same resolved
2102 // "newUnit", so all clients will get it using the usual way.
2103 AnalysisResult analysisResult = analysisContext.performAnalysisTask();
2104 ChangeNotice notice = analysisResult.changeNotices[0];
2105 expect(notice.resolvedDartUnit, same(newUnit));
2106 // Resolve "newCode" from scratch.
2107 if (compareWithFull) {
2108 _resetWithIncremental(false);
2109 changeSource(source, '');
2110 changeSource(source, newCode);
2111 _runTasks();
2112 LibraryElement library = resolve2(source);
2113 CompilationUnit fullNewUnit = resolveCompilationUnit(source, library);
2114 // Validate tokens.
2115 _assertEqualTokens(newUnit, fullNewUnit);
2116 // Validate LineInfo
2117 _assertEqualLineInfo(newLineInfo, analysisContext.getLineInfo(source));
2118 // Validate that "incremental" and "full" units have the same resolution.
2119 try {
2120 assertSameResolution(newUnit, fullNewUnit, validateTypes: true);
2121 } on IncrementalResolutionMismatch catch (mismatch) {
2122 fail(mismatch.message);
2123 }
2124 List<AnalysisError> newFullErrors =
2125 analysisContext.getErrors(source).errors;
2126 _assertEqualErrors(newErrors, newFullErrors);
2127 }
2128 _checkCacheEntries(analysisContext2.analysisCache);
2129 }
2130
2131 static void _assertEqualToken(Token incToken, Token fullToken) {
2132 // print('[${incToken.offset}] |$incToken| vs. [${fullToken.offset}] |$fullTo ken|');
2133 expect(incToken.type, fullToken.type);
2134 expect(incToken.offset, fullToken.offset);
2135 expect(incToken.length, fullToken.length);
2136 expect(incToken.lexeme, fullToken.lexeme);
2137 }
2138
2139 static void _assertEqualTokens(
2140 CompilationUnit incUnit, CompilationUnit fullUnit) {
2141 Token incToken = incUnit.beginToken;
2142 Token fullToken = fullUnit.beginToken;
2143 while (incToken.type != TokenType.EOF && fullToken.type != TokenType.EOF) {
2144 _assertEqualToken(incToken, fullToken);
2145 // comments
2146 {
2147 Token incComment = incToken.precedingComments;
2148 Token fullComment = fullToken.precedingComments;
2149 while (true) {
2150 if (fullComment == null) {
2151 expect(incComment, isNull);
2152 break;
2153 }
2154 expect(incComment, isNotNull);
2155 _assertEqualToken(incComment, fullComment);
2156 incComment = incComment.next;
2157 fullComment = fullComment.next;
2158 }
2159 }
2160 // next tokens
2161 incToken = incToken.next;
2162 fullToken = fullToken.next;
2163 }
2164 }
2165 }
2166
2167 @reflectiveTest
2168 class ResolutionContextBuilderTest extends EngineTestCase {
2169 void test_scopeFor_ClassDeclaration() {
2170 Scope scope = _scopeFor(_createResolvedClassDeclaration());
2171 EngineTestCase.assertInstanceOf(
2172 (obj) => obj is LibraryScope, LibraryScope, scope);
2173 }
2174
2175 void test_scopeFor_ClassTypeAlias() {
2176 Scope scope = _scopeFor(_createResolvedClassTypeAlias());
2177 EngineTestCase.assertInstanceOf(
2178 (obj) => obj is LibraryScope, LibraryScope, scope);
2179 }
2180
2181 void test_scopeFor_CompilationUnit() {
2182 Scope scope = _scopeFor(_createResolvedCompilationUnit());
2183 EngineTestCase.assertInstanceOf(
2184 (obj) => obj is LibraryScope, LibraryScope, scope);
2185 }
2186
2187 void test_scopeFor_ConstructorDeclaration() {
2188 Scope scope = _scopeFor(_createResolvedConstructorDeclaration());
2189 EngineTestCase.assertInstanceOf(
2190 (obj) => obj is ClassScope, ClassScope, scope);
2191 }
2192
2193 void test_scopeFor_ConstructorDeclaration_parameters() {
2194 Scope scope = _scopeFor(_createResolvedConstructorDeclaration().parameters);
2195 EngineTestCase.assertInstanceOf(
2196 (obj) => obj is FunctionScope, FunctionScope, scope);
2197 }
2198
2199 void test_scopeFor_FunctionDeclaration() {
2200 Scope scope = _scopeFor(_createResolvedFunctionDeclaration());
2201 EngineTestCase.assertInstanceOf(
2202 (obj) => obj is LibraryScope, LibraryScope, scope);
2203 }
2204
2205 void test_scopeFor_FunctionDeclaration_parameters() {
2206 Scope scope = _scopeFor(
2207 _createResolvedFunctionDeclaration().functionExpression.parameters);
2208 EngineTestCase.assertInstanceOf(
2209 (obj) => obj is FunctionScope, FunctionScope, scope);
2210 }
2211
2212 void test_scopeFor_FunctionTypeAlias() {
2213 Scope scope = _scopeFor(_createResolvedFunctionTypeAlias());
2214 EngineTestCase.assertInstanceOf(
2215 (obj) => obj is LibraryScope, LibraryScope, scope);
2216 }
2217
2218 void test_scopeFor_FunctionTypeAlias_parameters() {
2219 Scope scope = _scopeFor(_createResolvedFunctionTypeAlias().parameters);
2220 EngineTestCase.assertInstanceOf(
2221 (obj) => obj is FunctionTypeScope, FunctionTypeScope, scope);
2222 }
2223
2224 void test_scopeFor_MethodDeclaration() {
2225 Scope scope = _scopeFor(_createResolvedMethodDeclaration());
2226 EngineTestCase.assertInstanceOf(
2227 (obj) => obj is ClassScope, ClassScope, scope);
2228 }
2229
2230 void test_scopeFor_MethodDeclaration_body() {
2231 Scope scope = _scopeFor(_createResolvedMethodDeclaration().body);
2232 EngineTestCase.assertInstanceOf(
2233 (obj) => obj is FunctionScope, FunctionScope, scope);
2234 }
2235
2236 void test_scopeFor_notInCompilationUnit() {
2237 try {
2238 _scopeFor(AstTestFactory.identifier3("x"));
2239 fail("Expected AnalysisException");
2240 } on AnalysisException {
2241 // Expected
2242 }
2243 }
2244
2245 void test_scopeFor_null() {
2246 try {
2247 _scopeFor(null);
2248 fail("Expected AnalysisException");
2249 } on AnalysisException {
2250 // Expected
2251 }
2252 }
2253
2254 void test_scopeFor_unresolved() {
2255 try {
2256 _scopeFor(AstTestFactory.compilationUnit());
2257 fail("Expected AnalysisException");
2258 } on AnalysisException {
2259 // Expected
2260 }
2261 }
2262
2263 ClassDeclaration _createResolvedClassDeclaration() {
2264 CompilationUnit unit = _createResolvedCompilationUnit();
2265 String className = "C";
2266 ClassDeclaration classNode = AstTestFactory.classDeclaration(
2267 null, className, AstTestFactory.typeParameterList(), null, null, null);
2268 unit.declarations.add(classNode);
2269 ClassElement classElement = ElementFactory.classElement2(className);
2270 classNode.name.staticElement = classElement;
2271 (unit.element as CompilationUnitElementImpl).types = <ClassElement>[
2272 classElement
2273 ];
2274 return classNode;
2275 }
2276
2277 ClassTypeAlias _createResolvedClassTypeAlias() {
2278 CompilationUnit unit = _createResolvedCompilationUnit();
2279 String className = "C";
2280 ClassTypeAlias classNode = AstTestFactory.classTypeAlias(
2281 className, AstTestFactory.typeParameterList(), null, null, null, null);
2282 unit.declarations.add(classNode);
2283 ClassElement classElement = ElementFactory.classElement2(className);
2284 classNode.name.staticElement = classElement;
2285 (unit.element as CompilationUnitElementImpl).types = <ClassElement>[
2286 classElement
2287 ];
2288 return classNode;
2289 }
2290
2291 CompilationUnit _createResolvedCompilationUnit() {
2292 CompilationUnit unit = AstTestFactory.compilationUnit();
2293 LibraryElementImpl library =
2294 ElementFactory.library(AnalysisContextFactory.contextWithCore(), "lib");
2295 unit.element = library.definingCompilationUnit;
2296 return unit;
2297 }
2298
2299 ConstructorDeclaration _createResolvedConstructorDeclaration() {
2300 ClassDeclaration classNode = _createResolvedClassDeclaration();
2301 String constructorName = "f";
2302 ConstructorDeclaration constructorNode =
2303 AstTestFactory.constructorDeclaration(
2304 AstTestFactory.identifier3(constructorName),
2305 null,
2306 AstTestFactory.formalParameterList(),
2307 null);
2308 classNode.members.add(constructorNode);
2309 ConstructorElement constructorElement =
2310 ElementFactory.constructorElement2(classNode.element, null);
2311 constructorNode.element = constructorElement;
2312 (classNode.element as ClassElementImpl).constructors = <ConstructorElement>[
2313 constructorElement
2314 ];
2315 return constructorNode;
2316 }
2317
2318 FunctionDeclaration _createResolvedFunctionDeclaration() {
2319 CompilationUnit unit = _createResolvedCompilationUnit();
2320 String functionName = "f";
2321 FunctionDeclaration functionNode = AstTestFactory.functionDeclaration(
2322 null, null, functionName, AstTestFactory.functionExpression());
2323 unit.declarations.add(functionNode);
2324 FunctionElement functionElement =
2325 ElementFactory.functionElement(functionName);
2326 functionNode.name.staticElement = functionElement;
2327 (unit.element as CompilationUnitElementImpl).functions = <FunctionElement>[
2328 functionElement
2329 ];
2330 return functionNode;
2331 }
2332
2333 FunctionTypeAlias _createResolvedFunctionTypeAlias() {
2334 CompilationUnit unit = _createResolvedCompilationUnit();
2335 FunctionTypeAlias aliasNode = AstTestFactory.typeAlias(
2336 AstTestFactory.typeName4("A"),
2337 "F",
2338 AstTestFactory.typeParameterList(),
2339 AstTestFactory.formalParameterList());
2340 unit.declarations.add(aliasNode);
2341 SimpleIdentifier aliasName = aliasNode.name;
2342 FunctionTypeAliasElement aliasElement =
2343 new FunctionTypeAliasElementImpl.forNode(aliasName);
2344 aliasName.staticElement = aliasElement;
2345 (unit.element as CompilationUnitElementImpl).typeAliases =
2346 <FunctionTypeAliasElement>[aliasElement];
2347 return aliasNode;
2348 }
2349
2350 MethodDeclaration _createResolvedMethodDeclaration() {
2351 ClassDeclaration classNode = _createResolvedClassDeclaration();
2352 String methodName = "f";
2353 MethodDeclaration methodNode = AstTestFactory.methodDeclaration(
2354 null,
2355 null,
2356 null,
2357 null,
2358 AstTestFactory.identifier3(methodName),
2359 AstTestFactory.formalParameterList());
2360 classNode.members.add(methodNode);
2361 MethodElement methodElement =
2362 ElementFactory.methodElement(methodName, null);
2363 methodNode.name.staticElement = methodElement;
2364 (classNode.element as ClassElementImpl).methods = <MethodElement>[
2365 methodElement
2366 ];
2367 return methodNode;
2368 }
2369
2370 Scope _scopeFor(AstNode node) {
2371 return ResolutionContextBuilder.contextFor(node).scope;
2372 }
2373 }
2374
2375 class _Edit {
2376 final int offset;
2377 final int length;
2378 final String replacement;
2379 _Edit(this.offset, this.length, this.replacement);
2380 }
2381
2382 class _TestLogger implements logging.Logger {
2383 Object lastException;
2384 Object lastStackTrace;
2385
2386 @override
2387 void enter(String name) {}
2388
2389 @override
2390 void exit() {}
2391
2392 void expectNoErrors() {
2393 if (lastException != null) {
2394 fail("logged an exception:\n$lastException\n$lastStackTrace\n");
2395 }
2396 }
2397
2398 @override
2399 void log(Object obj) {}
2400
2401 @override
2402 void logException(Object exception, [Object stackTrace]) {
2403 lastException = exception;
2404 lastStackTrace = stackTrace;
2405 }
2406
2407 @override
2408 logging.LoggingTimer startTimer() {
2409 return new logging.LoggingTimer(this);
2410 }
2411 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/incremental_resolver.dart ('k') | pkg/analyzer/test/generated/test_all.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698