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 test.services.correction.fix; | |
6 | |
7 import 'package:analysis_services/correction/change.dart'; | |
8 import 'package:analysis_services/correction/fix.dart'; | |
9 import 'package:analysis_services/index/index.dart'; | |
10 import 'package:analysis_services/index/local_memory_index.dart'; | |
11 import 'package:analysis_services/src/search/search_engine.dart'; | |
12 import 'package:analysis_testing/abstract_context.dart'; | |
13 import 'package:analysis_testing/abstract_single_unit.dart'; | |
14 import 'package:analysis_testing/reflective_tests.dart'; | |
15 import 'package:analyzer/file_system/file_system.dart'; | |
16 import 'package:analyzer/source/package_map_resolver.dart'; | |
17 import 'package:analyzer/src/generated/error.dart'; | |
18 import 'package:analyzer/src/generated/source.dart'; | |
19 import 'package:unittest/unittest.dart'; | |
20 | |
21 | |
22 main() { | |
23 groupSep = ' | '; | |
24 runReflectiveTests(FixProcessorTest); | |
25 } | |
26 | |
27 | |
28 @ReflectiveTestCase() | |
29 class FixProcessorTest extends AbstractSingleUnitTest { | |
30 Index index; | |
31 SearchEngineImpl searchEngine; | |
32 | |
33 Fix fix; | |
34 Change change; | |
35 String resultCode; | |
36 | |
37 void assertHasFix(FixKind kind, String expected) { | |
38 AnalysisError error = _findErrorToFix(); | |
39 fix = _assertHasFix(kind, error); | |
40 change = fix.change; | |
41 // apply to "file" | |
42 List<FileEdit> fileEdits = change.fileEdits; | |
43 expect(fileEdits, hasLength(1)); | |
44 resultCode = Edit.applySequence(testCode, change.fileEdits[0].edits); | |
45 // verify | |
46 expect(resultCode, expected); | |
47 } | |
48 | |
49 void assertHasPositionGroup(String id, List<Position> expectedPositions) { | |
50 List<LinkedEditGroup> linkedPositionGroups = change.linkedEditGroups; | |
51 for (LinkedEditGroup group in linkedPositionGroups) { | |
52 if (group.id == id) { | |
53 expect(group.positions, unorderedEquals(expectedPositions)); | |
54 return; | |
55 } | |
56 } | |
57 fail('No PositionGroup with id=$id found in $linkedPositionGroups'); | |
58 } | |
59 | |
60 void assertNoFix(FixKind kind) { | |
61 AnalysisError error = _findErrorToFix(); | |
62 List<Fix> fixes = computeFixes(searchEngine, testUnit, error); | |
63 for (Fix fix in fixes) { | |
64 if (fix.kind == kind) { | |
65 throw fail('Unexpected fix $kind in\n${fixes.join('\n')}'); | |
66 } | |
67 } | |
68 } | |
69 | |
70 void assert_undefinedFunction_create_returnType_bool(String lineWithTest) { | |
71 _indexTestUnit(''' | |
72 main() { | |
73 bool b = true; | |
74 $lineWithTest | |
75 } | |
76 '''); | |
77 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
78 main() { | |
79 bool b = true; | |
80 $lineWithTest | |
81 } | |
82 | |
83 bool test() { | |
84 } | |
85 '''); | |
86 } | |
87 | |
88 Position expectedPosition(String search) { | |
89 int offset = resultCode.indexOf(search); | |
90 int length = getLeadingIdentifierLength(search); | |
91 return new Position(testFile, offset); | |
92 } | |
93 | |
94 List<Position> expectedPositions(List<String> patterns) { | |
95 List<Position> positions = <Position>[]; | |
96 patterns.forEach((String search) { | |
97 positions.add(expectedPosition(search)); | |
98 }); | |
99 return positions; | |
100 } | |
101 | |
102 void setUp() { | |
103 super.setUp(); | |
104 index = createLocalMemoryIndex(); | |
105 searchEngine = new SearchEngineImpl(index); | |
106 verifyNoTestUnitErrors = false; | |
107 } | |
108 | |
109 void test_boolean() { | |
110 _indexTestUnit(''' | |
111 main() { | |
112 boolean v; | |
113 } | |
114 '''); | |
115 assertHasFix(FixKind.REPLACE_BOOLEAN_WITH_BOOL, ''' | |
116 main() { | |
117 bool v; | |
118 } | |
119 '''); | |
120 } | |
121 | |
122 void test_changeToStaticAccess_method() { | |
123 _indexTestUnit(''' | |
124 class A { | |
125 static foo() {} | |
126 } | |
127 main(A a) { | |
128 a.foo(); | |
129 } | |
130 '''); | |
131 assertHasFix(FixKind.CHANGE_TO_STATIC_ACCESS, ''' | |
132 class A { | |
133 static foo() {} | |
134 } | |
135 main(A a) { | |
136 A.foo(); | |
137 } | |
138 '''); | |
139 } | |
140 | |
141 void test_changeToStaticAccess_method_prefixLibrary() { | |
142 _indexTestUnit(''' | |
143 import 'dart:async' as pref; | |
144 main(pref.Future f) { | |
145 f.wait([]); | |
146 } | |
147 '''); | |
148 assertHasFix(FixKind.CHANGE_TO_STATIC_ACCESS, ''' | |
149 import 'dart:async' as pref; | |
150 main(pref.Future f) { | |
151 pref.Future.wait([]); | |
152 } | |
153 '''); | |
154 } | |
155 | |
156 void test_changeToStaticAccess_property() { | |
157 _indexTestUnit(''' | |
158 class A { | |
159 static get foo => 42; | |
160 } | |
161 main(A a) { | |
162 a.foo; | |
163 } | |
164 '''); | |
165 assertHasFix(FixKind.CHANGE_TO_STATIC_ACCESS, ''' | |
166 class A { | |
167 static get foo => 42; | |
168 } | |
169 main(A a) { | |
170 A.foo; | |
171 } | |
172 '''); | |
173 } | |
174 | |
175 void test_createClass() { | |
176 _indexTestUnit(''' | |
177 main() { | |
178 Test v = null; | |
179 } | |
180 '''); | |
181 assertHasFix(FixKind.CREATE_CLASS, ''' | |
182 main() { | |
183 Test v = null; | |
184 } | |
185 | |
186 class Test { | |
187 } | |
188 '''); | |
189 assertHasPositionGroup('NAME', expectedPositions(['Test v =', 'Test {'])); | |
190 } | |
191 | |
192 void test_createConstructorSuperExplicit() { | |
193 _indexTestUnit(''' | |
194 class A { | |
195 A(bool p1, int p2, double p3, String p4, {p5}); | |
196 } | |
197 class B extends A { | |
198 B() {} | |
199 } | |
200 '''); | |
201 assertHasFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' | |
202 class A { | |
203 A(bool p1, int p2, double p3, String p4, {p5}); | |
204 } | |
205 class B extends A { | |
206 B() : super(false, 0, 0.0, '') {} | |
207 } | |
208 '''); | |
209 } | |
210 | |
211 void test_createConstructorSuperExplicit_hasInitializers() { | |
212 _indexTestUnit(''' | |
213 class A { | |
214 A(int p); | |
215 } | |
216 class B extends A { | |
217 int field; | |
218 B() : field = 42 {} | |
219 } | |
220 '''); | |
221 assertHasFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' | |
222 class A { | |
223 A(int p); | |
224 } | |
225 class B extends A { | |
226 int field; | |
227 B() : field = 42, super(0) {} | |
228 } | |
229 '''); | |
230 } | |
231 | |
232 void test_createConstructorSuperExplicit_named() { | |
233 _indexTestUnit(''' | |
234 class A { | |
235 A.named(int p); | |
236 } | |
237 class B extends A { | |
238 B() {} | |
239 } | |
240 '''); | |
241 assertHasFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION, ''' | |
242 class A { | |
243 A.named(int p); | |
244 } | |
245 class B extends A { | |
246 B() : super.named(0) {} | |
247 } | |
248 '''); | |
249 } | |
250 | |
251 void test_createConstructorSuperExplicit_named_private() { | |
252 _indexTestUnit(''' | |
253 class A { | |
254 A._named(int p); | |
255 } | |
256 class B extends A { | |
257 B() {} | |
258 } | |
259 '''); | |
260 assertNoFix(FixKind.ADD_SUPER_CONSTRUCTOR_INVOCATION); | |
261 } | |
262 | |
263 void test_createConstructorSuperImplicit() { | |
264 _indexTestUnit(''' | |
265 class A { | |
266 A(p1, int p2, List<String> p3, [int p4]); | |
267 } | |
268 class B extends A { | |
269 int existingField; | |
270 | |
271 void existingMethod() {} | |
272 } | |
273 '''); | |
274 assertHasFix(FixKind.CREATE_CONSTRUCTOR_SUPER, ''' | |
275 class A { | |
276 A(p1, int p2, List<String> p3, [int p4]); | |
277 } | |
278 class B extends A { | |
279 int existingField; | |
280 | |
281 B(p1, int p2, List<String> p3) : super(p1, p2, p3); | |
282 | |
283 void existingMethod() {} | |
284 } | |
285 '''); | |
286 } | |
287 | |
288 void test_createConstructorSuperImplicit_fieldInitializer() { | |
289 _indexTestUnit(''' | |
290 class A { | |
291 int _field; | |
292 A(this._field); | |
293 } | |
294 class B extends A { | |
295 int existingField; | |
296 | |
297 void existingMethod() {} | |
298 } | |
299 '''); | |
300 assertHasFix(FixKind.CREATE_CONSTRUCTOR_SUPER, ''' | |
301 class A { | |
302 int _field; | |
303 A(this._field); | |
304 } | |
305 class B extends A { | |
306 int existingField; | |
307 | |
308 B(int field) : super(field); | |
309 | |
310 void existingMethod() {} | |
311 } | |
312 '''); | |
313 } | |
314 | |
315 void test_createConstructorSuperImplicit_named() { | |
316 _indexTestUnit(''' | |
317 class A { | |
318 A.named(p1, int p2); | |
319 } | |
320 class B extends A { | |
321 int existingField; | |
322 | |
323 void existingMethod() {} | |
324 } | |
325 '''); | |
326 assertHasFix(FixKind.CREATE_CONSTRUCTOR_SUPER, ''' | |
327 class A { | |
328 A.named(p1, int p2); | |
329 } | |
330 class B extends A { | |
331 int existingField; | |
332 | |
333 B.named(p1, int p2) : super.named(p1, p2); | |
334 | |
335 void existingMethod() {} | |
336 } | |
337 '''); | |
338 } | |
339 | |
340 void test_createConstructorSuperImplicit_private() { | |
341 _indexTestUnit(''' | |
342 class A { | |
343 A._named(p); | |
344 } | |
345 class B extends A { | |
346 } | |
347 '''); | |
348 assertNoFix(FixKind.CREATE_CONSTRUCTOR_SUPER); | |
349 } | |
350 | |
351 void test_createConstructor_insteadOfSyntheticDefault() { | |
352 _indexTestUnit(''' | |
353 class A { | |
354 int field; | |
355 | |
356 method() {} | |
357 } | |
358 main() { | |
359 new A(1, 2.0); | |
360 } | |
361 '''); | |
362 assertHasFix(FixKind.CREATE_CONSTRUCTOR, ''' | |
363 class A { | |
364 int field; | |
365 | |
366 A(int i, double d) { | |
367 } | |
368 | |
369 method() {} | |
370 } | |
371 main() { | |
372 new A(1, 2.0); | |
373 } | |
374 '''); | |
375 } | |
376 | |
377 void test_createConstructor_named() { | |
378 _indexTestUnit(''' | |
379 class A { | |
380 method() {} | |
381 } | |
382 main() { | |
383 new A.named(1, 2.0); | |
384 } | |
385 '''); | |
386 assertHasFix(FixKind.CREATE_CONSTRUCTOR, ''' | |
387 class A { | |
388 A.named(int i, double d) { | |
389 } | |
390 | |
391 method() {} | |
392 } | |
393 main() { | |
394 new A.named(1, 2.0); | |
395 } | |
396 '''); | |
397 } | |
398 | |
399 void test_createMissingOverrides_functionType() { | |
400 _indexTestUnit(''' | |
401 abstract class A { | |
402 forEach(int f(double p1, String p2)); | |
403 } | |
404 | |
405 class B extends A { | |
406 } | |
407 '''); | |
408 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, ''' | |
409 abstract class A { | |
410 forEach(int f(double p1, String p2)); | |
411 } | |
412 | |
413 class B extends A { | |
414 @override | |
415 forEach(int f(double p1, String p2)) { | |
416 // TODO: implement forEach | |
417 } | |
418 } | |
419 '''); | |
420 } | |
421 | |
422 void test_createMissingOverrides_generics() { | |
423 _indexTestUnit(''' | |
424 class Iterator<T> { | |
425 } | |
426 | |
427 abstract class IterableMixin<T> { | |
428 Iterator<T> get iterator; | |
429 } | |
430 | |
431 class Test extends IterableMixin<int> { | |
432 } | |
433 '''); | |
434 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, ''' | |
435 class Iterator<T> { | |
436 } | |
437 | |
438 abstract class IterableMixin<T> { | |
439 Iterator<T> get iterator; | |
440 } | |
441 | |
442 class Test extends IterableMixin<int> { | |
443 // TODO: implement iterator | |
444 @override | |
445 Iterator<int> get iterator => null; | |
446 } | |
447 '''); | |
448 } | |
449 | |
450 void test_createMissingOverrides_getter() { | |
451 _indexTestUnit(''' | |
452 abstract class A { | |
453 get g1; | |
454 int get g2; | |
455 } | |
456 | |
457 class B extends A { | |
458 } | |
459 '''); | |
460 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, ''' | |
461 abstract class A { | |
462 get g1; | |
463 int get g2; | |
464 } | |
465 | |
466 class B extends A { | |
467 // TODO: implement g1 | |
468 @override | |
469 get g1 => null; | |
470 | |
471 // TODO: implement g2 | |
472 @override | |
473 int get g2 => null; | |
474 } | |
475 '''); | |
476 } | |
477 | |
478 void test_createMissingOverrides_importPrefix() { | |
479 _indexTestUnit(''' | |
480 import 'dart:async' as aaa; | |
481 abstract class A { | |
482 Map<aaa.Future, List<aaa.Future>> g(aaa.Future p); | |
483 } | |
484 | |
485 class B extends A { | |
486 } | |
487 '''); | |
488 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, ''' | |
489 import 'dart:async' as aaa; | |
490 abstract class A { | |
491 Map<aaa.Future, List<aaa.Future>> g(aaa.Future p); | |
492 } | |
493 | |
494 class B extends A { | |
495 @override | |
496 Map<aaa.Future, List<aaa.Future>> g(aaa.Future p) { | |
497 // TODO: implement g | |
498 } | |
499 } | |
500 '''); | |
501 } | |
502 | |
503 void test_createMissingOverrides_method() { | |
504 _indexTestUnit(''' | |
505 abstract class A { | |
506 m1(); | |
507 int m2(); | |
508 String m3(int p1, double p2, Map<int, List<String>> p3); | |
509 String m4(p1, p2); | |
510 String m5(p1, [int p2 = 2, int p3, p4 = 4]); | |
511 String m6(p1, {int p2: 2, int p3, p4: 4}); | |
512 } | |
513 | |
514 class B extends A { | |
515 } | |
516 '''); | |
517 String expectedCode = ''' | |
518 abstract class A { | |
519 m1(); | |
520 int m2(); | |
521 String m3(int p1, double p2, Map<int, List<String>> p3); | |
522 String m4(p1, p2); | |
523 String m5(p1, [int p2 = 2, int p3, p4 = 4]); | |
524 String m6(p1, {int p2: 2, int p3, p4: 4}); | |
525 } | |
526 | |
527 class B extends A { | |
528 @override | |
529 m1() { | |
530 // TODO: implement m1 | |
531 } | |
532 | |
533 @override | |
534 int m2() { | |
535 // TODO: implement m2 | |
536 } | |
537 | |
538 @override | |
539 String m3(int p1, double p2, Map<int, List<String>> p3) { | |
540 // TODO: implement m3 | |
541 } | |
542 | |
543 @override | |
544 String m4(p1, p2) { | |
545 // TODO: implement m4 | |
546 } | |
547 | |
548 @override | |
549 String m5(p1, [int p2 = 2, int p3, p4 = 4]) { | |
550 // TODO: implement m5 | |
551 } | |
552 | |
553 @override | |
554 String m6(p1, {int p2: 2, int p3, p4: 4}) { | |
555 // TODO: implement m6 | |
556 } | |
557 } | |
558 '''; | |
559 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, expectedCode); | |
560 // end position should be on "m1", not on "m2", "m3", etc | |
561 { | |
562 Position endPosition = change.selection; | |
563 expect(endPosition, isNotNull); | |
564 expect(endPosition.file, testFile); | |
565 int endOffset = endPosition.offset; | |
566 String endString = expectedCode.substring(endOffset, endOffset + 25); | |
567 expect(endString, contains('m1')); | |
568 expect(endString, isNot(contains('m2'))); | |
569 expect(endString, isNot(contains('m3'))); | |
570 expect(endString, isNot(contains('m4'))); | |
571 expect(endString, isNot(contains('m5'))); | |
572 expect(endString, isNot(contains('m6'))); | |
573 } | |
574 } | |
575 | |
576 void test_createMissingOverrides_operator() { | |
577 _indexTestUnit(''' | |
578 abstract class A { | |
579 int operator [](int index); | |
580 void operator []=(int index, String value); | |
581 } | |
582 | |
583 class B extends A { | |
584 } | |
585 '''); | |
586 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, ''' | |
587 abstract class A { | |
588 int operator [](int index); | |
589 void operator []=(int index, String value); | |
590 } | |
591 | |
592 class B extends A { | |
593 @override | |
594 int operator [](int index) { | |
595 // TODO: implement [] | |
596 } | |
597 | |
598 @override | |
599 void operator []=(int index, String value) { | |
600 // TODO: implement []= | |
601 } | |
602 } | |
603 '''); | |
604 } | |
605 | |
606 void test_createMissingOverrides_setter() { | |
607 _indexTestUnit(''' | |
608 abstract class A { | |
609 set s1(x); | |
610 set s2(int x); | |
611 void set s3(String x); | |
612 } | |
613 | |
614 class B extends A { | |
615 } | |
616 '''); | |
617 assertHasFix(FixKind.CREATE_MISSING_OVERRIDES, ''' | |
618 abstract class A { | |
619 set s1(x); | |
620 set s2(int x); | |
621 void set s3(String x); | |
622 } | |
623 | |
624 class B extends A { | |
625 @override | |
626 set s1(x) { | |
627 // TODO: implement s1 | |
628 } | |
629 | |
630 @override | |
631 set s2(int x) { | |
632 // TODO: implement s2 | |
633 } | |
634 | |
635 @override | |
636 void set s3(String x) { | |
637 // TODO: implement s3 | |
638 } | |
639 } | |
640 '''); | |
641 } | |
642 | |
643 void test_createNoSuchMethod() { | |
644 _indexTestUnit(''' | |
645 abstract class A { | |
646 m1(); | |
647 int m2(); | |
648 } | |
649 | |
650 class B extends A { | |
651 existing() {} | |
652 } | |
653 '''); | |
654 assertHasFix(FixKind.CREATE_NO_SUCH_METHOD, ''' | |
655 abstract class A { | |
656 m1(); | |
657 int m2(); | |
658 } | |
659 | |
660 class B extends A { | |
661 existing() {} | |
662 | |
663 noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation); | |
664 } | |
665 '''); | |
666 } | |
667 | |
668 void test_creationFunction_forFunctionType_cascadeSecond() { | |
669 _indexTestUnit(''' | |
670 class A { | |
671 B ma() => null; | |
672 } | |
673 class B { | |
674 useFunction(int g(double a, String b)) {} | |
675 } | |
676 | |
677 main() { | |
678 A a = new A(); | |
679 a..ma().useFunction(test); | |
680 } | |
681 '''); | |
682 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
683 class A { | |
684 B ma() => null; | |
685 } | |
686 class B { | |
687 useFunction(int g(double a, String b)) {} | |
688 } | |
689 | |
690 main() { | |
691 A a = new A(); | |
692 a..ma().useFunction(test); | |
693 } | |
694 | |
695 int test(double a, String b) { | |
696 } | |
697 '''); | |
698 } | |
699 | |
700 void test_creationFunction_forFunctionType_dynamicArgument() { | |
701 _indexTestUnit(''' | |
702 main() { | |
703 useFunction(test); | |
704 } | |
705 useFunction(int g(a, b)) {} | |
706 '''); | |
707 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
708 main() { | |
709 useFunction(test); | |
710 } | |
711 useFunction(int g(a, b)) {} | |
712 | |
713 int test(a, b) { | |
714 } | |
715 '''); | |
716 } | |
717 | |
718 void test_creationFunction_forFunctionType_function() { | |
719 _indexTestUnit(''' | |
720 main() { | |
721 useFunction(test); | |
722 } | |
723 useFunction(int g(double a, String b)) {} | |
724 '''); | |
725 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
726 main() { | |
727 useFunction(test); | |
728 } | |
729 useFunction(int g(double a, String b)) {} | |
730 | |
731 int test(double a, String b) { | |
732 } | |
733 '''); | |
734 } | |
735 | |
736 void test_creationFunction_forFunctionType_method_enclosingClass_static() { | |
737 _indexTestUnit(''' | |
738 class A { | |
739 static foo() { | |
740 useFunction(test); | |
741 } | |
742 } | |
743 useFunction(int g(double a, String b)) {} | |
744 '''); | |
745 assertHasFix(FixKind.CREATE_METHOD, ''' | |
746 class A { | |
747 static foo() { | |
748 useFunction(test); | |
749 } | |
750 | |
751 static int test(double a, String b) { | |
752 } | |
753 } | |
754 useFunction(int g(double a, String b)) {} | |
755 '''); | |
756 } | |
757 | |
758 void test_creationFunction_forFunctionType_method_enclosingClass_static2() { | |
759 _indexTestUnit(''' | |
760 class A { | |
761 var f; | |
762 A() : f = useFunction(test); | |
763 } | |
764 useFunction(int g(double a, String b)) {} | |
765 '''); | |
766 assertHasFix(FixKind.CREATE_METHOD, ''' | |
767 class A { | |
768 var f; | |
769 A() : f = useFunction(test); | |
770 | |
771 static int test(double a, String b) { | |
772 } | |
773 } | |
774 useFunction(int g(double a, String b)) {} | |
775 '''); | |
776 } | |
777 | |
778 void test_creationFunction_forFunctionType_method_targetClass() { | |
779 _indexTestUnit(''' | |
780 main(A a) { | |
781 useFunction(a.test); | |
782 } | |
783 class A { | |
784 } | |
785 useFunction(int g(double a, String b)) {} | |
786 '''); | |
787 assertHasFix(FixKind.CREATE_METHOD, ''' | |
788 main(A a) { | |
789 useFunction(a.test); | |
790 } | |
791 class A { | |
792 int test(double a, String b) { | |
793 } | |
794 } | |
795 useFunction(int g(double a, String b)) {} | |
796 '''); | |
797 } | |
798 | |
799 void | |
800 test_creationFunction_forFunctionType_method_targetClass_hasOtherMember()
{ | |
801 _indexTestUnit(''' | |
802 main(A a) { | |
803 useFunction(a.test); | |
804 } | |
805 class A { | |
806 m() {} | |
807 } | |
808 useFunction(int g(double a, String b)) {} | |
809 '''); | |
810 assertHasFix(FixKind.CREATE_METHOD, ''' | |
811 main(A a) { | |
812 useFunction(a.test); | |
813 } | |
814 class A { | |
815 m() {} | |
816 | |
817 int test(double a, String b) { | |
818 } | |
819 } | |
820 useFunction(int g(double a, String b)) {} | |
821 '''); | |
822 } | |
823 | |
824 void test_creationFunction_forFunctionType_notFunctionType() { | |
825 _indexTestUnit(''' | |
826 main(A a) { | |
827 useFunction(a.test); | |
828 } | |
829 typedef A(); | |
830 useFunction(g) {} | |
831 '''); | |
832 assertNoFix(FixKind.CREATE_METHOD); | |
833 assertNoFix(FixKind.CREATE_FUNCTION); | |
834 } | |
835 | |
836 void test_creationFunction_forFunctionType_unknownTarget() { | |
837 _indexTestUnit(''' | |
838 main(A a) { | |
839 useFunction(a.test); | |
840 } | |
841 class A { | |
842 } | |
843 useFunction(g) {} | |
844 '''); | |
845 assertNoFix(FixKind.CREATE_METHOD); | |
846 } | |
847 | |
848 void test_expectedToken_semicolon() { | |
849 _indexTestUnit(''' | |
850 main() { | |
851 print(0) | |
852 } | |
853 '''); | |
854 assertHasFix(FixKind.INSERT_SEMICOLON, ''' | |
855 main() { | |
856 print(0); | |
857 } | |
858 '''); | |
859 } | |
860 | |
861 void test_importLibraryPackage_withType() { | |
862 provider.newFile('/packages/my_pkg/lib/my_lib.dart', ''' | |
863 library my_lib; | |
864 class Test {} | |
865 '''); | |
866 { | |
867 Folder myPkgFolder = provider.getResource('/packages/my_pkg/lib'); | |
868 UriResolver pkgResolver = new PackageMapUriResolver(provider, { | |
869 'my_pkg': [myPkgFolder] | |
870 }); | |
871 context.sourceFactory = new SourceFactory( | |
872 [AbstractContextTest.SDK_RESOLVER, resourceResolver, pkgResolver]); | |
873 } | |
874 // force 'my_pkg' resolution | |
875 addSource('/tmp/other.dart', "import 'package:my_pkg/my_lib.dart';"); | |
876 // try to find a fix | |
877 _indexTestUnit(''' | |
878 main() { | |
879 Test test = null; | |
880 } | |
881 '''); | |
882 performAllAnalysisTasks(); | |
883 assertHasFix(FixKind.IMPORT_LIBRARY_PROJECT, ''' | |
884 import 'package:my_pkg/my_lib.dart'; | |
885 | |
886 main() { | |
887 Test test = null; | |
888 } | |
889 '''); | |
890 } | |
891 | |
892 void test_importLibraryPrefix_withTopLevelVariable() { | |
893 _indexTestUnit(''' | |
894 import 'dart:math' as pref; | |
895 main() { | |
896 print(pref.E); | |
897 print(PI); | |
898 } | |
899 '''); | |
900 assertHasFix(FixKind.IMPORT_LIBRARY_PREFIX, ''' | |
901 import 'dart:math' as pref; | |
902 main() { | |
903 print(pref.E); | |
904 print(pref.PI); | |
905 } | |
906 '''); | |
907 } | |
908 | |
909 void test_importLibraryPrefix_withType() { | |
910 _indexTestUnit(''' | |
911 import 'dart:async' as pref; | |
912 main() { | |
913 pref.Stream s = null; | |
914 Future f = null; | |
915 } | |
916 '''); | |
917 assertHasFix(FixKind.IMPORT_LIBRARY_PREFIX, ''' | |
918 import 'dart:async' as pref; | |
919 main() { | |
920 pref.Stream s = null; | |
921 pref.Future f = null; | |
922 } | |
923 '''); | |
924 } | |
925 | |
926 void test_importLibraryProject_withFunction() { | |
927 addSource('/lib.dart', ''' | |
928 library lib; | |
929 myFunction() {} | |
930 '''); | |
931 _indexTestUnit(''' | |
932 main() { | |
933 myFunction(); | |
934 } | |
935 '''); | |
936 performAllAnalysisTasks(); | |
937 assertHasFix(FixKind.IMPORT_LIBRARY_PROJECT, ''' | |
938 import 'lib.dart'; | |
939 | |
940 main() { | |
941 myFunction(); | |
942 } | |
943 '''); | |
944 } | |
945 | |
946 void test_importLibraryProject_withTopLevelVariable() { | |
947 addSource('/lib.dart', ''' | |
948 library lib; | |
949 int MY_VAR = 42; | |
950 '''); | |
951 _indexTestUnit(''' | |
952 main() { | |
953 print(MY_VAR); | |
954 } | |
955 '''); | |
956 performAllAnalysisTasks(); | |
957 assertHasFix(FixKind.IMPORT_LIBRARY_PROJECT, ''' | |
958 import 'lib.dart'; | |
959 | |
960 main() { | |
961 print(MY_VAR); | |
962 } | |
963 '''); | |
964 } | |
965 | |
966 void test_importLibraryProject_withType_inParentFolder() { | |
967 testFile = '/project/bin/test.dart'; | |
968 addSource('/project/lib.dart', ''' | |
969 library lib; | |
970 class Test {} | |
971 '''); | |
972 _indexTestUnit(''' | |
973 main() { | |
974 Test t = null; | |
975 } | |
976 '''); | |
977 performAllAnalysisTasks(); | |
978 assertHasFix(FixKind.IMPORT_LIBRARY_PROJECT, ''' | |
979 import '../lib.dart'; | |
980 | |
981 main() { | |
982 Test t = null; | |
983 } | |
984 '''); | |
985 } | |
986 | |
987 void test_importLibraryProject_withType_inRelativeFolder() { | |
988 testFile = '/project/bin/test.dart'; | |
989 addSource('/project/lib/sub/folder/lib.dart', ''' | |
990 library lib; | |
991 class Test {} | |
992 '''); | |
993 _indexTestUnit(''' | |
994 main() { | |
995 Test t = null; | |
996 } | |
997 '''); | |
998 performAllAnalysisTasks(); | |
999 assertHasFix(FixKind.IMPORT_LIBRARY_PROJECT, ''' | |
1000 import '../lib/sub/folder/lib.dart'; | |
1001 | |
1002 main() { | |
1003 Test t = null; | |
1004 } | |
1005 '''); | |
1006 } | |
1007 | |
1008 void test_importLibraryProject_withType_inSameFolder() { | |
1009 testFile = '/project/bin/test.dart'; | |
1010 addSource('/project/bin/lib.dart', ''' | |
1011 library lib; | |
1012 class Test {} | |
1013 '''); | |
1014 _indexTestUnit(''' | |
1015 main() { | |
1016 Test t = null; | |
1017 } | |
1018 '''); | |
1019 performAllAnalysisTasks(); | |
1020 assertHasFix(FixKind.IMPORT_LIBRARY_PROJECT, ''' | |
1021 import 'lib.dart'; | |
1022 | |
1023 main() { | |
1024 Test t = null; | |
1025 } | |
1026 '''); | |
1027 } | |
1028 | |
1029 void test_importLibrarySdk_withTopLevelVariable() { | |
1030 _ensureSdkMathLibraryResolved(); | |
1031 _indexTestUnit(''' | |
1032 main() { | |
1033 print(PI); | |
1034 } | |
1035 '''); | |
1036 performAllAnalysisTasks(); | |
1037 assertHasFix(FixKind.IMPORT_LIBRARY_SDK, ''' | |
1038 import 'dart:math'; | |
1039 | |
1040 main() { | |
1041 print(PI); | |
1042 } | |
1043 '''); | |
1044 } | |
1045 | |
1046 void test_importLibrarySdk_withType_invocationTarget() { | |
1047 _ensureSdkAsyncLibraryResolved(); | |
1048 _indexTestUnit(''' | |
1049 main() { | |
1050 Future.wait(null); | |
1051 } | |
1052 '''); | |
1053 assertHasFix(FixKind.IMPORT_LIBRARY_SDK, ''' | |
1054 import 'dart:async'; | |
1055 | |
1056 main() { | |
1057 Future.wait(null); | |
1058 } | |
1059 '''); | |
1060 } | |
1061 | |
1062 void test_importLibrarySdk_withType_typeAnnotation() { | |
1063 _ensureSdkAsyncLibraryResolved(); | |
1064 _indexTestUnit(''' | |
1065 main() { | |
1066 Future f = null; | |
1067 } | |
1068 '''); | |
1069 assertHasFix(FixKind.IMPORT_LIBRARY_SDK, ''' | |
1070 import 'dart:async'; | |
1071 | |
1072 main() { | |
1073 Future f = null; | |
1074 } | |
1075 '''); | |
1076 } | |
1077 | |
1078 void test_importLibrarySdk_withType_typeAnnotation_PrefixedIdentifier() { | |
1079 _ensureSdkAsyncLibraryResolved(); | |
1080 _indexTestUnit(''' | |
1081 main() { | |
1082 Future.wait; | |
1083 } | |
1084 '''); | |
1085 assertHasFix(FixKind.IMPORT_LIBRARY_SDK, ''' | |
1086 import 'dart:async'; | |
1087 | |
1088 main() { | |
1089 Future.wait; | |
1090 } | |
1091 '''); | |
1092 } | |
1093 | |
1094 void test_importLibraryShow() { | |
1095 _indexTestUnit(''' | |
1096 import 'dart:async' show Stream; | |
1097 main() { | |
1098 Stream s = null; | |
1099 Future f = null; | |
1100 } | |
1101 '''); | |
1102 assertHasFix(FixKind.IMPORT_LIBRARY_SHOW, ''' | |
1103 import 'dart:async' show Future, Stream; | |
1104 main() { | |
1105 Stream s = null; | |
1106 Future f = null; | |
1107 } | |
1108 '''); | |
1109 } | |
1110 | |
1111 void test_isNotNull() { | |
1112 _indexTestUnit(''' | |
1113 main(p) { | |
1114 p is! Null; | |
1115 } | |
1116 '''); | |
1117 assertHasFix(FixKind.USE_NOT_EQ_NULL, ''' | |
1118 main(p) { | |
1119 p != null; | |
1120 } | |
1121 '''); | |
1122 } | |
1123 | |
1124 void test_isNull() { | |
1125 _indexTestUnit(''' | |
1126 main(p) { | |
1127 p is Null; | |
1128 } | |
1129 '''); | |
1130 assertHasFix(FixKind.USE_EQ_EQ_NULL, ''' | |
1131 main(p) { | |
1132 p == null; | |
1133 } | |
1134 '''); | |
1135 } | |
1136 | |
1137 void test_makeEnclosingClassAbstract_declaresAbstractMethod() { | |
1138 _indexTestUnit(''' | |
1139 class A { | |
1140 m(); | |
1141 } | |
1142 '''); | |
1143 assertHasFix(FixKind.MAKE_CLASS_ABSTRACT, ''' | |
1144 abstract class A { | |
1145 m(); | |
1146 } | |
1147 '''); | |
1148 } | |
1149 | |
1150 void test_makeEnclosingClassAbstract_inheritsAbstractMethod() { | |
1151 _indexTestUnit(''' | |
1152 abstract class A { | |
1153 m(); | |
1154 } | |
1155 class B extends A { | |
1156 } | |
1157 '''); | |
1158 assertHasFix(FixKind.MAKE_CLASS_ABSTRACT, ''' | |
1159 abstract class A { | |
1160 m(); | |
1161 } | |
1162 abstract class B extends A { | |
1163 } | |
1164 '''); | |
1165 } | |
1166 | |
1167 void test_removeParentheses_inGetterDeclaration() { | |
1168 _indexTestUnit(''' | |
1169 class A { | |
1170 int get foo() => 0; | |
1171 } | |
1172 '''); | |
1173 assertHasFix(FixKind.REMOVE_PARAMETERS_IN_GETTER_DECLARATION, ''' | |
1174 class A { | |
1175 int get foo => 0; | |
1176 } | |
1177 '''); | |
1178 } | |
1179 | |
1180 void test_removeParentheses_inGetterInvocation() { | |
1181 _indexTestUnit(''' | |
1182 class A { | |
1183 int get foo => 0; | |
1184 } | |
1185 main(A a) { | |
1186 a.foo(); | |
1187 } | |
1188 '''); | |
1189 assertHasFix(FixKind.REMOVE_PARENTHESIS_IN_GETTER_INVOCATION, ''' | |
1190 class A { | |
1191 int get foo => 0; | |
1192 } | |
1193 main(A a) { | |
1194 a.foo; | |
1195 } | |
1196 '''); | |
1197 } | |
1198 | |
1199 void test_removeUnnecessaryCast_assignment() { | |
1200 _indexTestUnit(''' | |
1201 main(Object p) { | |
1202 if (p is String) { | |
1203 String v = ((p as String)); | |
1204 } | |
1205 } | |
1206 '''); | |
1207 assertHasFix(FixKind.REMOVE_UNNECASSARY_CAST, ''' | |
1208 main(Object p) { | |
1209 if (p is String) { | |
1210 String v = p; | |
1211 } | |
1212 } | |
1213 '''); | |
1214 } | |
1215 | |
1216 void test_removeUnusedImport() { | |
1217 _indexTestUnit(''' | |
1218 import 'dart:math'; | |
1219 main() { | |
1220 } | |
1221 '''); | |
1222 assertHasFix(FixKind.REMOVE_UNUSED_IMPORT, ''' | |
1223 main() { | |
1224 } | |
1225 '''); | |
1226 } | |
1227 | |
1228 void test_removeUnusedImport_anotherImportOnLine() { | |
1229 _indexTestUnit(''' | |
1230 import 'dart:math'; import 'dart:async'; | |
1231 | |
1232 main() { | |
1233 Future f; | |
1234 } | |
1235 '''); | |
1236 assertHasFix(FixKind.REMOVE_UNUSED_IMPORT, ''' | |
1237 import 'dart:async'; | |
1238 | |
1239 main() { | |
1240 Future f; | |
1241 } | |
1242 '''); | |
1243 } | |
1244 | |
1245 void test_removeUnusedImport_severalLines() { | |
1246 _indexTestUnit(''' | |
1247 import | |
1248 'dart:math'; | |
1249 main() { | |
1250 } | |
1251 '''); | |
1252 assertHasFix(FixKind.REMOVE_UNUSED_IMPORT, ''' | |
1253 main() { | |
1254 } | |
1255 '''); | |
1256 } | |
1257 | |
1258 void test_replaceWithConstInstanceCreation() { | |
1259 _indexTestUnit(''' | |
1260 class A { | |
1261 const A(); | |
1262 } | |
1263 const a = new A(); | |
1264 '''); | |
1265 assertHasFix(FixKind.USE_CONST, ''' | |
1266 class A { | |
1267 const A(); | |
1268 } | |
1269 const a = const A(); | |
1270 '''); | |
1271 } | |
1272 | |
1273 void test_undefinedClass_useSimilar_fromImport() { | |
1274 _indexTestUnit(''' | |
1275 main() { | |
1276 Stirng s = 'abc'; | |
1277 } | |
1278 '''); | |
1279 assertHasFix(FixKind.CHANGE_TO, ''' | |
1280 main() { | |
1281 String s = 'abc'; | |
1282 } | |
1283 '''); | |
1284 } | |
1285 | |
1286 void test_undefinedClass_useSimilar_fromThisLibrary() { | |
1287 _indexTestUnit(''' | |
1288 class MyClass {} | |
1289 main() { | |
1290 MyCalss v = null; | |
1291 } | |
1292 '''); | |
1293 assertHasFix(FixKind.CHANGE_TO, ''' | |
1294 class MyClass {} | |
1295 main() { | |
1296 MyClass v = null; | |
1297 } | |
1298 '''); | |
1299 } | |
1300 | |
1301 void test_undefinedFunction_create_fromFunction() { | |
1302 _indexTestUnit(''' | |
1303 main() { | |
1304 int v = myUndefinedFunction(1, 2.0, '3'); | |
1305 } | |
1306 '''); | |
1307 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1308 main() { | |
1309 int v = myUndefinedFunction(1, 2.0, '3'); | |
1310 } | |
1311 | |
1312 int myUndefinedFunction(int i, double d, String s) { | |
1313 } | |
1314 '''); | |
1315 } | |
1316 | |
1317 void test_undefinedFunction_create_fromMethod() { | |
1318 _indexTestUnit(''' | |
1319 class A { | |
1320 main() { | |
1321 int v = myUndefinedFunction(1, 2.0, '3'); | |
1322 } | |
1323 } | |
1324 '''); | |
1325 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1326 class A { | |
1327 main() { | |
1328 int v = myUndefinedFunction(1, 2.0, '3'); | |
1329 } | |
1330 } | |
1331 | |
1332 int myUndefinedFunction(int i, double d, String s) { | |
1333 } | |
1334 '''); | |
1335 } | |
1336 | |
1337 void test_undefinedFunction_create_returnType_bool_expressions() { | |
1338 assert_undefinedFunction_create_returnType_bool("!test();"); | |
1339 assert_undefinedFunction_create_returnType_bool("b && test();"); | |
1340 assert_undefinedFunction_create_returnType_bool("test() && b;"); | |
1341 assert_undefinedFunction_create_returnType_bool("b || test();"); | |
1342 assert_undefinedFunction_create_returnType_bool("test() || b;"); | |
1343 } | |
1344 | |
1345 void test_undefinedFunction_create_returnType_bool_statements() { | |
1346 assert_undefinedFunction_create_returnType_bool("assert ( test() );"); | |
1347 assert_undefinedFunction_create_returnType_bool("if ( test() ) {}"); | |
1348 assert_undefinedFunction_create_returnType_bool("while ( test() ) {}"); | |
1349 assert_undefinedFunction_create_returnType_bool("do {} while ( test() );"); | |
1350 } | |
1351 | |
1352 void test_undefinedFunction_create_returnType_fromAssignment_eq() { | |
1353 _indexTestUnit(''' | |
1354 main() { | |
1355 int v; | |
1356 v = myUndefinedFunction(); | |
1357 } | |
1358 '''); | |
1359 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1360 main() { | |
1361 int v; | |
1362 v = myUndefinedFunction(); | |
1363 } | |
1364 | |
1365 int myUndefinedFunction() { | |
1366 } | |
1367 '''); | |
1368 } | |
1369 | |
1370 void test_undefinedFunction_create_returnType_fromAssignment_plusEq() { | |
1371 _indexTestUnit(''' | |
1372 main() { | |
1373 int v; | |
1374 v += myUndefinedFunction(); | |
1375 } | |
1376 '''); | |
1377 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1378 main() { | |
1379 int v; | |
1380 v += myUndefinedFunction(); | |
1381 } | |
1382 | |
1383 num myUndefinedFunction() { | |
1384 } | |
1385 '''); | |
1386 } | |
1387 | |
1388 void test_undefinedFunction_create_returnType_fromBinary_right() { | |
1389 _indexTestUnit(''' | |
1390 main() { | |
1391 0 + myUndefinedFunction(); | |
1392 } | |
1393 '''); | |
1394 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1395 main() { | |
1396 0 + myUndefinedFunction(); | |
1397 } | |
1398 | |
1399 num myUndefinedFunction() { | |
1400 } | |
1401 '''); | |
1402 } | |
1403 | |
1404 void test_undefinedFunction_create_returnType_fromInitializer() { | |
1405 _indexTestUnit(''' | |
1406 main() { | |
1407 int v = myUndefinedFunction(); | |
1408 } | |
1409 '''); | |
1410 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1411 main() { | |
1412 int v = myUndefinedFunction(); | |
1413 } | |
1414 | |
1415 int myUndefinedFunction() { | |
1416 } | |
1417 '''); | |
1418 } | |
1419 | |
1420 void test_undefinedFunction_create_returnType_fromInvocationArgument() { | |
1421 _indexTestUnit(''' | |
1422 foo(int p) {} | |
1423 main() { | |
1424 foo( myUndefinedFunction() ); | |
1425 } | |
1426 '''); | |
1427 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1428 foo(int p) {} | |
1429 main() { | |
1430 foo( myUndefinedFunction() ); | |
1431 } | |
1432 | |
1433 int myUndefinedFunction() { | |
1434 } | |
1435 '''); | |
1436 } | |
1437 | |
1438 void test_undefinedFunction_create_returnType_fromReturn() { | |
1439 _indexTestUnit(''' | |
1440 int main() { | |
1441 return myUndefinedFunction(); | |
1442 } | |
1443 '''); | |
1444 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1445 int main() { | |
1446 return myUndefinedFunction(); | |
1447 } | |
1448 | |
1449 int myUndefinedFunction() { | |
1450 } | |
1451 '''); | |
1452 } | |
1453 | |
1454 void test_undefinedFunction_create_returnType_void() { | |
1455 _indexTestUnit(''' | |
1456 main() { | |
1457 myUndefinedFunction(); | |
1458 } | |
1459 '''); | |
1460 assertHasFix(FixKind.CREATE_FUNCTION, ''' | |
1461 main() { | |
1462 myUndefinedFunction(); | |
1463 } | |
1464 | |
1465 void myUndefinedFunction() { | |
1466 } | |
1467 '''); | |
1468 } | |
1469 | |
1470 void test_undefinedFunction_useSimilar_fromImport() { | |
1471 _indexTestUnit(''' | |
1472 main() { | |
1473 pritn(0); | |
1474 } | |
1475 '''); | |
1476 assertHasFix(FixKind.CHANGE_TO, ''' | |
1477 main() { | |
1478 print(0); | |
1479 } | |
1480 '''); | |
1481 } | |
1482 | |
1483 void test_undefinedFunction_useSimilar_thisLibrary() { | |
1484 _indexTestUnit(''' | |
1485 myFunction() {} | |
1486 main() { | |
1487 myFuntcion(); | |
1488 } | |
1489 '''); | |
1490 assertHasFix(FixKind.CHANGE_TO, ''' | |
1491 myFunction() {} | |
1492 main() { | |
1493 myFunction(); | |
1494 } | |
1495 '''); | |
1496 } | |
1497 | |
1498 void test_undefinedMethod_createQualified_fromClass() { | |
1499 _indexTestUnit(''' | |
1500 class A { | |
1501 } | |
1502 main() { | |
1503 A.myUndefinedMethod(); | |
1504 } | |
1505 '''); | |
1506 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1507 class A { | |
1508 static void myUndefinedMethod() { | |
1509 } | |
1510 } | |
1511 main() { | |
1512 A.myUndefinedMethod(); | |
1513 } | |
1514 '''); | |
1515 } | |
1516 | |
1517 void test_undefinedMethod_createQualified_fromClass_hasOtherMember() { | |
1518 _indexTestUnit(''' | |
1519 class A { | |
1520 foo() {} | |
1521 } | |
1522 main() { | |
1523 A.myUndefinedMethod(); | |
1524 } | |
1525 '''); | |
1526 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1527 class A { | |
1528 foo() {} | |
1529 | |
1530 static void myUndefinedMethod() { | |
1531 } | |
1532 } | |
1533 main() { | |
1534 A.myUndefinedMethod(); | |
1535 } | |
1536 '''); | |
1537 } | |
1538 | |
1539 void test_undefinedMethod_createQualified_fromInstance() { | |
1540 _indexTestUnit(''' | |
1541 class A { | |
1542 } | |
1543 main(A a) { | |
1544 a.myUndefinedMethod(); | |
1545 } | |
1546 '''); | |
1547 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1548 class A { | |
1549 void myUndefinedMethod() { | |
1550 } | |
1551 } | |
1552 main(A a) { | |
1553 a.myUndefinedMethod(); | |
1554 } | |
1555 '''); | |
1556 } | |
1557 | |
1558 void test_undefinedMethod_createQualified_targetIsFunctionType() { | |
1559 _indexTestUnit(''' | |
1560 typedef A(); | |
1561 main() { | |
1562 A.myUndefinedMethod(); | |
1563 } | |
1564 '''); | |
1565 assertNoFix(FixKind.CREATE_METHOD); | |
1566 } | |
1567 | |
1568 void test_undefinedMethod_createQualified_targetIsUnresolved() { | |
1569 _indexTestUnit(''' | |
1570 main() { | |
1571 NoSuchClass.myUndefinedMethod(); | |
1572 } | |
1573 '''); | |
1574 assertNoFix(FixKind.CREATE_METHOD); | |
1575 } | |
1576 | |
1577 void test_undefinedMethod_createUnqualified_parameters() { | |
1578 _indexTestUnit(''' | |
1579 class A { | |
1580 main() { | |
1581 myUndefinedMethod(0, 1.0, '3'); | |
1582 } | |
1583 } | |
1584 '''); | |
1585 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1586 class A { | |
1587 main() { | |
1588 myUndefinedMethod(0, 1.0, '3'); | |
1589 } | |
1590 | |
1591 void myUndefinedMethod(int i, double d, String s) { | |
1592 } | |
1593 } | |
1594 '''); | |
1595 // linked positions | |
1596 _assertHasLinkedPositions( | |
1597 'NAME', | |
1598 ['myUndefinedMethod(0', 'myUndefinedMethod(int']); | |
1599 _assertHasLinkedPositions('RETURN_TYPE', ['void myUndefinedMethod(']); | |
1600 _assertHasLinkedPositions('TYPE0', ['int i']); | |
1601 _assertHasLinkedPositions('TYPE1', ['double d']); | |
1602 _assertHasLinkedPositions('TYPE2', ['String s']); | |
1603 _assertHasLinkedPositions('ARG0', ['i,']); | |
1604 _assertHasLinkedPositions('ARG1', ['d,']); | |
1605 _assertHasLinkedPositions('ARG2', ['s)']); | |
1606 // linked proposals | |
1607 _assertHasLinkedSuggestions( | |
1608 'TYPE0', | |
1609 expectedSuggestions( | |
1610 LinkedEditSuggestionKind.TYPE, | |
1611 ['int', 'num', 'Object', 'Comparable'])); | |
1612 _assertHasLinkedSuggestions( | |
1613 'TYPE1', | |
1614 expectedSuggestions( | |
1615 LinkedEditSuggestionKind.TYPE, | |
1616 ['double', 'num', 'Object', 'Comparable'])); | |
1617 _assertHasLinkedSuggestions( | |
1618 'TYPE2', | |
1619 expectedSuggestions( | |
1620 LinkedEditSuggestionKind.TYPE, | |
1621 ['String', 'Object', 'Comparable'])); | |
1622 } | |
1623 | |
1624 List<LinkedEditSuggestion> expectedSuggestions(LinkedEditSuggestionKind kind, | |
1625 List<String> values) { | |
1626 return values.map((value) { | |
1627 return new LinkedEditSuggestion(kind, value); | |
1628 }).toList(); | |
1629 } | |
1630 | |
1631 void test_undefinedMethod_createUnqualified_returnType() { | |
1632 _indexTestUnit(''' | |
1633 class A { | |
1634 main() { | |
1635 int v = myUndefinedMethod(); | |
1636 } | |
1637 } | |
1638 '''); | |
1639 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1640 class A { | |
1641 main() { | |
1642 int v = myUndefinedMethod(); | |
1643 } | |
1644 | |
1645 int myUndefinedMethod() { | |
1646 } | |
1647 } | |
1648 '''); | |
1649 // linked positions | |
1650 _assertHasLinkedPositions( | |
1651 'NAME', | |
1652 ['myUndefinedMethod();', 'myUndefinedMethod() {']); | |
1653 _assertHasLinkedPositions('RETURN_TYPE', ['int myUndefinedMethod(']); | |
1654 } | |
1655 | |
1656 void test_undefinedMethod_createUnqualified_staticFromField() { | |
1657 _indexTestUnit(''' | |
1658 class A { | |
1659 static var f = myUndefinedMethod(); | |
1660 } | |
1661 '''); | |
1662 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1663 class A { | |
1664 static var f = myUndefinedMethod(); | |
1665 | |
1666 static myUndefinedMethod() { | |
1667 } | |
1668 } | |
1669 '''); | |
1670 } | |
1671 | |
1672 void test_undefinedMethod_createUnqualified_staticFromMethod() { | |
1673 _indexTestUnit(''' | |
1674 class A { | |
1675 static main() { | |
1676 myUndefinedMethod(); | |
1677 } | |
1678 } | |
1679 '''); | |
1680 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1681 class A { | |
1682 static main() { | |
1683 myUndefinedMethod(); | |
1684 } | |
1685 | |
1686 static void myUndefinedMethod() { | |
1687 } | |
1688 } | |
1689 '''); | |
1690 } | |
1691 | |
1692 void test_undefinedMethod_hint_createQualified_fromInstance() { | |
1693 _indexTestUnit(''' | |
1694 class A { | |
1695 } | |
1696 main() { | |
1697 var a = new A(); | |
1698 a.myUndefinedMethod(); | |
1699 } | |
1700 '''); | |
1701 assertHasFix(FixKind.CREATE_METHOD, ''' | |
1702 class A { | |
1703 void myUndefinedMethod() { | |
1704 } | |
1705 } | |
1706 main() { | |
1707 var a = new A(); | |
1708 a.myUndefinedMethod(); | |
1709 } | |
1710 '''); | |
1711 } | |
1712 | |
1713 void test_undefinedMethod_useSimilar_ignoreOperators() { | |
1714 _indexTestUnit(''' | |
1715 main(Object object) { | |
1716 object.then(); | |
1717 } | |
1718 '''); | |
1719 assertNoFix(FixKind.CHANGE_TO); | |
1720 } | |
1721 | |
1722 void test_undefinedMethod_useSimilar_qualified() { | |
1723 _indexTestUnit(''' | |
1724 class A { | |
1725 myMethod() {} | |
1726 } | |
1727 main() { | |
1728 A a = new A(); | |
1729 a.myMehtod(); | |
1730 } | |
1731 '''); | |
1732 assertHasFix(FixKind.CHANGE_TO, ''' | |
1733 class A { | |
1734 myMethod() {} | |
1735 } | |
1736 main() { | |
1737 A a = new A(); | |
1738 a.myMethod(); | |
1739 } | |
1740 '''); | |
1741 } | |
1742 | |
1743 void test_undefinedMethod_useSimilar_unqualified_superClass() { | |
1744 _indexTestUnit(''' | |
1745 class A { | |
1746 myMethod() {} | |
1747 } | |
1748 class B extends A { | |
1749 main() { | |
1750 myMehtod(); | |
1751 } | |
1752 } | |
1753 '''); | |
1754 assertHasFix(FixKind.CHANGE_TO, ''' | |
1755 class A { | |
1756 myMethod() {} | |
1757 } | |
1758 class B extends A { | |
1759 main() { | |
1760 myMethod(); | |
1761 } | |
1762 } | |
1763 '''); | |
1764 } | |
1765 | |
1766 void test_undefinedMethod_useSimilar_unqualified_thisClass() { | |
1767 _indexTestUnit(''' | |
1768 class A { | |
1769 myMethod() {} | |
1770 main() { | |
1771 myMehtod(); | |
1772 } | |
1773 } | |
1774 '''); | |
1775 assertHasFix(FixKind.CHANGE_TO, ''' | |
1776 class A { | |
1777 myMethod() {} | |
1778 main() { | |
1779 myMethod(); | |
1780 } | |
1781 } | |
1782 '''); | |
1783 } | |
1784 | |
1785 void test_useEffectiveIntegerDivision() { | |
1786 _indexTestUnit(''' | |
1787 main() { | |
1788 var a = 5; | |
1789 var b = 2; | |
1790 print((a / b).toInt()); | |
1791 } | |
1792 '''); | |
1793 assertHasFix(FixKind.USE_EFFECTIVE_INTEGER_DIVISION, ''' | |
1794 main() { | |
1795 var a = 5; | |
1796 var b = 2; | |
1797 print(a ~/ b); | |
1798 } | |
1799 '''); | |
1800 } | |
1801 | |
1802 /** | |
1803 * Computes fixes and verifies that there is a fix of the given kind. | |
1804 */ | |
1805 Fix _assertHasFix(FixKind kind, AnalysisError error) { | |
1806 List<Fix> fixes = computeFixes(searchEngine, testUnit, error); | |
1807 for (Fix fix in fixes) { | |
1808 if (fix.kind == kind) { | |
1809 return fix; | |
1810 } | |
1811 } | |
1812 throw fail('Expected to find fix $kind in\n${fixes.join('\n')}'); | |
1813 } | |
1814 | |
1815 void _assertHasLinkedPositions(String groupId, List<String> expectedStrings) { | |
1816 List<Position> expectedPositions = _findResultPositions(expectedStrings); | |
1817 List<LinkedEditGroup> groups = change.linkedEditGroups; | |
1818 for (LinkedEditGroup group in groups) { | |
1819 if (group.id == groupId) { | |
1820 List<Position> actualPositions = group.positions; | |
1821 expect(actualPositions, unorderedEquals(expectedPositions)); | |
1822 return; | |
1823 } | |
1824 } | |
1825 fail('No group with ID=$groupId foind in\n${groups.join('\n')}'); | |
1826 } | |
1827 | |
1828 void _assertHasLinkedSuggestions(String groupId, | |
1829 List<LinkedEditSuggestion> expected) { | |
1830 List<LinkedEditGroup> groups = change.linkedEditGroups; | |
1831 for (LinkedEditGroup group in groups) { | |
1832 if (group.id == groupId) { | |
1833 expect(group.suggestions, expected); | |
1834 return; | |
1835 } | |
1836 } | |
1837 fail('No group with ID=$groupId foind in\n${groups.join('\n')}'); | |
1838 } | |
1839 | |
1840 /** | |
1841 * We search for elements only already resolved lbiraries, and we use | |
1842 * `dart:async` elements in tests. | |
1843 */ | |
1844 void _ensureSdkAsyncLibraryResolved() { | |
1845 resolveLibraryUnit(addSource('/other.dart', 'import "dart:async";')); | |
1846 } | |
1847 | |
1848 /** | |
1849 * We search for elements only already resolved lbiraries, and we use | |
1850 * `dart:async` elements in tests. | |
1851 */ | |
1852 void _ensureSdkMathLibraryResolved() { | |
1853 resolveLibraryUnit(addSource('/other.dart', 'import "dart:math";')); | |
1854 } | |
1855 | |
1856 AnalysisError _findErrorToFix() { | |
1857 List<AnalysisError> errors = context.computeErrors(testSource); | |
1858 expect( | |
1859 errors, | |
1860 hasLength(1), | |
1861 reason: 'Exactly 1 error expected, but ${errors.length} found:\n' + | |
1862 errors.join('\n')); | |
1863 return errors[0]; | |
1864 } | |
1865 | |
1866 List<Position> _findResultPositions(List<String> searchStrings) { | |
1867 List<Position> positions = <Position>[]; | |
1868 for (String search in searchStrings) { | |
1869 int offset = resultCode.indexOf(search); | |
1870 int length = getLeadingIdentifierLength(search); | |
1871 positions.add(new Position(testFile, offset)); | |
1872 } | |
1873 return positions; | |
1874 } | |
1875 | |
1876 void _indexTestUnit(String code) { | |
1877 resolveTestUnit(code); | |
1878 index.indexUnit(context, testUnit); | |
1879 } | |
1880 } | |
OLD | NEW |