OLD | NEW |
| (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 } | |
OLD | NEW |