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.refactoring.rename_class_member; | |
6 | |
7 import 'package:analysis_services/correction/status.dart'; | |
8 import 'package:analysis_testing/reflective_tests.dart'; | |
9 import 'package:unittest/unittest.dart'; | |
10 | |
11 import 'abstract_rename.dart'; | |
12 | |
13 | |
14 main() { | |
15 groupSep = ' | '; | |
16 runReflectiveTests(RenameClassMemberTest); | |
17 } | |
18 | |
19 | |
20 @ReflectiveTestCase() | |
21 class RenameClassMemberTest extends RenameRefactoringTest { | |
22 test_checkFinalConditions_OK_noShadow() { | |
23 indexTestUnit(''' | |
24 class A { | |
25 int newName; | |
26 } | |
27 class B { | |
28 test() {} | |
29 } | |
30 class C extends A { | |
31 main() { | |
32 print(newName); | |
33 } | |
34 } | |
35 '''); | |
36 createRenameRefactoringAtString('test() {}'); | |
37 // check status | |
38 refactoring.newName = 'newName'; | |
39 return refactoring.checkFinalConditions().then((status) { | |
40 assertRefactoringStatusOK(status); | |
41 }); | |
42 } | |
43 | |
44 test_checkFinalConditions_hasMember_MethodElement() { | |
45 indexTestUnit(''' | |
46 class A { | |
47 test() {} | |
48 newName() {} // existing | |
49 } | |
50 '''); | |
51 createRenameRefactoringAtString('test() {}'); | |
52 // check status | |
53 refactoring.newName = 'newName'; | |
54 return refactoring.checkFinalConditions().then((status) { | |
55 assertRefactoringStatus( | |
56 status, | |
57 RefactoringStatusSeverity.ERROR, | |
58 expectedMessage: "Class 'A' already declares method with name 'newName
'.", | |
59 expectedContextSearch: 'newName() {} // existing'); | |
60 }); | |
61 } | |
62 | |
63 test_checkFinalConditions_shadowed_byLocal_OK_qualifiedReference() { | |
64 indexTestUnit(''' | |
65 class A { | |
66 test() {} | |
67 main() { | |
68 var newName; | |
69 this.test(); // marker | |
70 } | |
71 } | |
72 '''); | |
73 createRenameRefactoringAtString('test() {}'); | |
74 // check status | |
75 refactoring.newName = 'newName'; | |
76 return refactoring.checkFinalConditions().then((status) { | |
77 assertRefactoringStatusOK(status); | |
78 }); | |
79 } | |
80 | |
81 test_checkFinalConditions_shadowed_byLocal_OK_renamedNotUsed() { | |
82 indexTestUnit(''' | |
83 class A { | |
84 test() {} | |
85 main() { | |
86 var newName; | |
87 } | |
88 } | |
89 '''); | |
90 createRenameRefactoringAtString('test() {}'); | |
91 // check status | |
92 refactoring.newName = 'newName'; | |
93 return refactoring.checkFinalConditions().then((status) { | |
94 assertRefactoringStatusOK(status); | |
95 }); | |
96 } | |
97 | |
98 test_checkFinalConditions_shadowed_byLocal_inSameClass() { | |
99 indexTestUnit(''' | |
100 class A { | |
101 test() {} | |
102 main() { | |
103 var newName; | |
104 test(); // marker | |
105 } | |
106 } | |
107 '''); | |
108 createRenameRefactoringAtString('test() {}'); | |
109 // check status | |
110 refactoring.newName = 'newName'; | |
111 return refactoring.checkFinalConditions().then((status) { | |
112 assertRefactoringStatus( | |
113 status, | |
114 RefactoringStatusSeverity.ERROR, | |
115 expectedMessage: | |
116 "Usage of renamed method will be shadowed by local variable 'newNa
me'.", | |
117 expectedContextSearch: 'test(); // marker'); | |
118 }); | |
119 } | |
120 | |
121 test_checkFinalConditions_shadowed_byLocal_inSubClass() { | |
122 indexTestUnit(''' | |
123 class A { | |
124 test() {} | |
125 } | |
126 class B extends A { | |
127 main() { | |
128 var newName; | |
129 test(); // marker | |
130 } | |
131 } | |
132 '''); | |
133 createRenameRefactoringAtString('test() {}'); | |
134 // check status | |
135 refactoring.newName = 'newName'; | |
136 return refactoring.checkFinalConditions().then((status) { | |
137 assertRefactoringStatus( | |
138 status, | |
139 RefactoringStatusSeverity.ERROR, | |
140 expectedMessage: | |
141 "Usage of renamed method will be shadowed by local variable 'newNa
me'.", | |
142 expectedContextSearch: 'test(); // marker'); | |
143 }); | |
144 } | |
145 | |
146 test_checkFinalConditions_shadowed_byParameter_inSameClass() { | |
147 indexTestUnit(''' | |
148 class A { | |
149 test() {} | |
150 main(newName) { | |
151 test(); // marker | |
152 } | |
153 } | |
154 '''); | |
155 createRenameRefactoringAtString('test() {}'); | |
156 // check status | |
157 refactoring.newName = 'newName'; | |
158 return refactoring.checkFinalConditions().then((status) { | |
159 assertRefactoringStatus( | |
160 status, | |
161 RefactoringStatusSeverity.ERROR, | |
162 expectedMessage: | |
163 "Usage of renamed method will be shadowed by parameter 'newName'."
, | |
164 expectedContextSearch: 'test(); // marker'); | |
165 }); | |
166 } | |
167 | |
168 test_checkFinalConditions_shadowed_inSubClass() { | |
169 indexTestUnit(''' | |
170 class A { | |
171 newName() {} // marker | |
172 } | |
173 class B extends A { | |
174 test() {} | |
175 main() { | |
176 newName(); | |
177 } | |
178 } | |
179 '''); | |
180 createRenameRefactoringAtString('test() {}'); | |
181 // check status | |
182 refactoring.newName = 'newName'; | |
183 return refactoring.checkFinalConditions().then((status) { | |
184 assertRefactoringStatus( | |
185 status, | |
186 RefactoringStatusSeverity.ERROR, | |
187 expectedMessage: "Renamed method will shadow method 'A.newName'.", | |
188 expectedContextSearch: 'newName() {} // marker'); | |
189 }); | |
190 } | |
191 | |
192 test_checkFinalConditions_shadowsSuper_MethodElement() { | |
193 indexTestUnit(''' | |
194 class A { | |
195 test() {} | |
196 } | |
197 class B extends A { | |
198 newName() {} // marker | |
199 main() { | |
200 test(); | |
201 } | |
202 } | |
203 '''); | |
204 createRenameRefactoringAtString('test() {}'); | |
205 // check status | |
206 refactoring.newName = 'newName'; | |
207 return refactoring.checkFinalConditions().then((status) { | |
208 assertRefactoringStatus( | |
209 status, | |
210 RefactoringStatusSeverity.ERROR, | |
211 expectedMessage: "Renamed method will be shadowed by method 'B.newName
'.", | |
212 expectedContextSearch: 'newName() {} // marker'); | |
213 }); | |
214 } | |
215 | |
216 test_checkFinalConditions_shadowsSuper_inSubClass_FieldElement() { | |
217 indexTestUnit(''' | |
218 class A { | |
219 int newName; // marker | |
220 } | |
221 class B extends A { | |
222 test() {} | |
223 } | |
224 class C extends B { | |
225 main() { | |
226 print(newName); | |
227 } | |
228 } | |
229 '''); | |
230 createRenameRefactoringAtString('test() {}'); | |
231 // check status | |
232 refactoring.newName = 'newName'; | |
233 return refactoring.checkFinalConditions().then((status) { | |
234 assertRefactoringStatus( | |
235 status, | |
236 RefactoringStatusSeverity.ERROR, | |
237 expectedMessage: "Renamed method will shadow field 'A.newName'.", | |
238 expectedContextSearch: 'newName; // marker'); | |
239 }); | |
240 } | |
241 | |
242 test_checkInitialConditions_operator() { | |
243 indexTestUnit(''' | |
244 class A { | |
245 operator -(other) => this; | |
246 } | |
247 '''); | |
248 createRenameRefactoringAtString('-(other)'); | |
249 // check status | |
250 refactoring.newName = 'newName'; | |
251 return refactoring.checkInitialConditions().then((status) { | |
252 assertRefactoringStatus(status, RefactoringStatusSeverity.FATAL); | |
253 }); | |
254 } | |
255 | |
256 test_checkNewName_FieldElement() { | |
257 indexTestUnit(''' | |
258 class A { | |
259 int test; | |
260 } | |
261 '''); | |
262 createRenameRefactoringAtString('test;'); | |
263 // null | |
264 refactoring.newName = null; | |
265 assertRefactoringStatus( | |
266 refactoring.checkNewName(), | |
267 RefactoringStatusSeverity.ERROR, | |
268 expectedMessage: "Field name must not be null."); | |
269 // OK | |
270 refactoring.newName = 'newName'; | |
271 assertRefactoringStatusOK(refactoring.checkNewName()); | |
272 } | |
273 | |
274 test_checkNewName_FieldElement_const() { | |
275 indexTestUnit(''' | |
276 class A { | |
277 static const int TEST = 0; | |
278 } | |
279 '''); | |
280 createRenameRefactoringAtString('TEST ='); | |
281 // null | |
282 refactoring.newName = null; | |
283 assertRefactoringStatus( | |
284 refactoring.checkNewName(), | |
285 RefactoringStatusSeverity.ERROR, | |
286 expectedMessage: "Constant name must not be null."); | |
287 // not upper case | |
288 refactoring.newName = 'newName'; | |
289 assertRefactoringStatus( | |
290 refactoring.checkNewName(), | |
291 RefactoringStatusSeverity.WARNING); | |
292 // OK | |
293 refactoring.newName = 'NEW_NAME'; | |
294 assertRefactoringStatusOK(refactoring.checkNewName()); | |
295 } | |
296 | |
297 test_checkNewName_MethodElement() { | |
298 indexTestUnit(''' | |
299 class A { | |
300 test() {} | |
301 } | |
302 '''); | |
303 createRenameRefactoringAtString('test() {}'); | |
304 // null | |
305 refactoring.newName = null; | |
306 assertRefactoringStatus( | |
307 refactoring.checkNewName(), | |
308 RefactoringStatusSeverity.ERROR, | |
309 expectedMessage: "Method name must not be null."); | |
310 // empty | |
311 refactoring.newName = ''; | |
312 assertRefactoringStatus( | |
313 refactoring.checkNewName(), | |
314 RefactoringStatusSeverity.ERROR, | |
315 expectedMessage: "Method name must not be empty."); | |
316 // same | |
317 refactoring.newName = 'test'; | |
318 assertRefactoringStatus( | |
319 refactoring.checkNewName(), | |
320 RefactoringStatusSeverity.FATAL, | |
321 expectedMessage: "The new name must be different than the current name."
); | |
322 // OK | |
323 refactoring.newName = 'newName'; | |
324 assertRefactoringStatusOK(refactoring.checkNewName()); | |
325 } | |
326 | |
327 test_createChange_FieldElement() { | |
328 indexTestUnit(''' | |
329 class A { | |
330 int test; // marker | |
331 main() { | |
332 print(test); | |
333 test = 1; | |
334 test += 2; | |
335 } | |
336 } | |
337 class B extends A { | |
338 } | |
339 class C extends B { | |
340 get test => 1; | |
341 set test(x) {} | |
342 } | |
343 main() { | |
344 A a = new A(); | |
345 B b = new B(); | |
346 C c = new C(); | |
347 print(a.test); | |
348 a.test = 1; | |
349 a.test += 2; | |
350 print(b.test); | |
351 b.test = 1; | |
352 print(c.test); | |
353 c.test = 1; | |
354 } | |
355 '''); | |
356 // configure refactoring | |
357 createRenameRefactoringAtString('test; // marker'); | |
358 expect(refactoring.refactoringName, 'Rename Field'); | |
359 expect(refactoring.oldName, 'test'); | |
360 refactoring.newName = 'newName'; | |
361 // validate change | |
362 return assertSuccessfulRename(''' | |
363 class A { | |
364 int newName; // marker | |
365 main() { | |
366 print(newName); | |
367 newName = 1; | |
368 newName += 2; | |
369 } | |
370 } | |
371 class B extends A { | |
372 } | |
373 class C extends B { | |
374 get newName => 1; | |
375 set newName(x) {} | |
376 } | |
377 main() { | |
378 A a = new A(); | |
379 B b = new B(); | |
380 C c = new C(); | |
381 print(a.newName); | |
382 a.newName = 1; | |
383 a.newName += 2; | |
384 print(b.newName); | |
385 b.newName = 1; | |
386 print(c.newName); | |
387 c.newName = 1; | |
388 } | |
389 '''); | |
390 } | |
391 | |
392 test_createChange_FieldElement_constructorFieldInitializer() { | |
393 indexTestUnit(''' | |
394 class A { | |
395 final test; | |
396 A() : test = 5; | |
397 } | |
398 '''); | |
399 // configure refactoring | |
400 createRenameRefactoringAtString('test;'); | |
401 expect(refactoring.refactoringName, 'Rename Field'); | |
402 expect(refactoring.oldName, 'test'); | |
403 refactoring.newName = 'newName'; | |
404 // validate change | |
405 return assertSuccessfulRename(''' | |
406 class A { | |
407 final newName; | |
408 A() : newName = 5; | |
409 } | |
410 '''); | |
411 } | |
412 | |
413 test_createChange_FieldElement_fieldFormalParameter() { | |
414 indexTestUnit(''' | |
415 class A { | |
416 final test; | |
417 A(this.test); | |
418 } | |
419 '''); | |
420 // configure refactoring | |
421 createRenameRefactoringAtString('test;'); | |
422 expect(refactoring.refactoringName, 'Rename Field'); | |
423 expect(refactoring.oldName, 'test'); | |
424 refactoring.newName = 'newName'; | |
425 // validate change | |
426 return assertSuccessfulRename(''' | |
427 class A { | |
428 final newName; | |
429 A(this.newName); | |
430 } | |
431 '''); | |
432 } | |
433 | |
434 test_createChange_FieldElement_invocation() { | |
435 indexTestUnit(''' | |
436 typedef F(a); | |
437 class A { | |
438 F test; | |
439 main() { | |
440 test(1); | |
441 } | |
442 } | |
443 main() { | |
444 A a = new A(); | |
445 a.test(2); | |
446 } | |
447 '''); | |
448 // configure refactoring | |
449 createRenameRefactoringAtString('test(2);'); | |
450 expect(refactoring.refactoringName, 'Rename Field'); | |
451 expect(refactoring.oldName, 'test'); | |
452 refactoring.newName = 'newName'; | |
453 // validate change | |
454 return assertSuccessfulRename(''' | |
455 typedef F(a); | |
456 class A { | |
457 F newName; | |
458 main() { | |
459 newName(1); | |
460 } | |
461 } | |
462 main() { | |
463 A a = new A(); | |
464 a.newName(2); | |
465 } | |
466 '''); | |
467 } | |
468 | |
469 test_createChange_MethodElement() { | |
470 indexTestUnit(''' | |
471 class A { | |
472 test() {} | |
473 } | |
474 class B extends A { | |
475 test() {} // marker | |
476 } | |
477 class C extends B { | |
478 test() {} | |
479 } | |
480 class D implements A { | |
481 test() {} | |
482 } | |
483 class E { | |
484 test() {} | |
485 } | |
486 main() { | |
487 A a = new A(); | |
488 B b = new B(); | |
489 C c = new C(); | |
490 D d = new D(); | |
491 E e = new E(); | |
492 a.test(); | |
493 b.test(); | |
494 c.test(); | |
495 d.test(); | |
496 e.test(); | |
497 } | |
498 '''); | |
499 // configure refactoring | |
500 createRenameRefactoringAtString('test() {} // marker'); | |
501 expect(refactoring.refactoringName, 'Rename Method'); | |
502 expect(refactoring.oldName, 'test'); | |
503 refactoring.newName = 'newName'; | |
504 // validate change | |
505 return assertSuccessfulRename(''' | |
506 class A { | |
507 newName() {} | |
508 } | |
509 class B extends A { | |
510 newName() {} // marker | |
511 } | |
512 class C extends B { | |
513 newName() {} | |
514 } | |
515 class D implements A { | |
516 newName() {} | |
517 } | |
518 class E { | |
519 test() {} | |
520 } | |
521 main() { | |
522 A a = new A(); | |
523 B b = new B(); | |
524 C c = new C(); | |
525 D d = new D(); | |
526 E e = new E(); | |
527 a.newName(); | |
528 b.newName(); | |
529 c.newName(); | |
530 d.newName(); | |
531 e.test(); | |
532 } | |
533 '''); | |
534 } | |
535 | |
536 test_createChange_MethodElement_potential() { | |
537 indexTestUnit(''' | |
538 class A { | |
539 test() {} | |
540 } | |
541 main(var a) { | |
542 a.test(); // 1 | |
543 new A().test(); | |
544 a.test(); // 2 | |
545 } | |
546 '''); | |
547 // configure refactoring | |
548 createRenameRefactoringAtString('test() {}'); | |
549 expect(refactoring.refactoringName, 'Rename Method'); | |
550 expect(refactoring.oldName, 'test'); | |
551 refactoring.newName = 'newName'; | |
552 // validate change | |
553 return assertSuccessfulRename(''' | |
554 class A { | |
555 newName() {} | |
556 } | |
557 main(var a) { | |
558 a.newName(); // 1 | |
559 new A().newName(); | |
560 a.newName(); // 2 | |
561 } | |
562 ''').then((_) { | |
563 assertPotentialEdits(['test(); // 1', 'test(); // 2']); | |
564 }); | |
565 } | |
566 | |
567 test_createChange_MethodElement_potential_private_otherLibrary() { | |
568 indexUnit('/lib.dart', ''' | |
569 library lib; | |
570 main(p) { | |
571 p._test(); | |
572 } | |
573 '''); | |
574 indexTestUnit(''' | |
575 class A { | |
576 _test() {} | |
577 } | |
578 main(var a) { | |
579 a._test(); | |
580 new A()._test(); | |
581 } | |
582 '''); | |
583 // configure refactoring | |
584 createRenameRefactoringAtString('_test() {}'); | |
585 expect(refactoring.refactoringName, 'Rename Method'); | |
586 expect(refactoring.oldName, '_test'); | |
587 refactoring.newName = 'newName'; | |
588 // validate change | |
589 return assertSuccessfulRename(''' | |
590 class A { | |
591 newName() {} | |
592 } | |
593 main(var a) { | |
594 a.newName(); | |
595 new A().newName(); | |
596 } | |
597 ''').then((_) { | |
598 assertNoFileChange('/lib.dart'); | |
599 }); | |
600 } | |
601 | |
602 test_createChange_PropertyAccessorElement_getter() { | |
603 indexTestUnit(''' | |
604 class A { | |
605 get test {} // marker | |
606 set test(x) {} | |
607 main() { | |
608 print(test); | |
609 test = 1; | |
610 } | |
611 } | |
612 class B extends A { | |
613 get test {} | |
614 set test(x) {} | |
615 } | |
616 main() { | |
617 A a = new A(); | |
618 print(a.test); | |
619 a.test = 2; | |
620 | |
621 B b = new B(); | |
622 print(b.test); | |
623 b.test = 2; | |
624 } | |
625 '''); | |
626 // configure refactoring | |
627 createRenameRefactoringAtString('test {} // marker'); | |
628 expect(refactoring.refactoringName, 'Rename Field'); | |
629 expect(refactoring.oldName, 'test'); | |
630 refactoring.newName = 'newName'; | |
631 // validate change | |
632 return assertSuccessfulRename(''' | |
633 class A { | |
634 get newName {} // marker | |
635 set newName(x) {} | |
636 main() { | |
637 print(newName); | |
638 newName = 1; | |
639 } | |
640 } | |
641 class B extends A { | |
642 get newName {} | |
643 set newName(x) {} | |
644 } | |
645 main() { | |
646 A a = new A(); | |
647 print(a.newName); | |
648 a.newName = 2; | |
649 | |
650 B b = new B(); | |
651 print(b.newName); | |
652 b.newName = 2; | |
653 } | |
654 '''); | |
655 } | |
656 | |
657 test_createChange_PropertyAccessorElement_setter() { | |
658 indexTestUnit(''' | |
659 class A { | |
660 get test {} | |
661 set test(x) {} // marker | |
662 main() { | |
663 print(test); | |
664 test = 1; | |
665 } | |
666 } | |
667 class B extends A { | |
668 get test {} | |
669 set test(x) {} | |
670 } | |
671 main() { | |
672 A a = new A(); | |
673 print(a.test); | |
674 a.test = 2; | |
675 | |
676 B b = new B(); | |
677 print(b.test); | |
678 b.test = 2; | |
679 } | |
680 '''); | |
681 // configure refactoring | |
682 createRenameRefactoringAtString('test(x) {} // marker'); | |
683 expect(refactoring.refactoringName, 'Rename Field'); | |
684 expect(refactoring.oldName, 'test'); | |
685 refactoring.newName = 'newName'; | |
686 // validate change | |
687 return assertSuccessfulRename(''' | |
688 class A { | |
689 get newName {} | |
690 set newName(x) {} // marker | |
691 main() { | |
692 print(newName); | |
693 newName = 1; | |
694 } | |
695 } | |
696 class B extends A { | |
697 get newName {} | |
698 set newName(x) {} | |
699 } | |
700 main() { | |
701 A a = new A(); | |
702 print(a.newName); | |
703 a.newName = 2; | |
704 | |
705 B b = new B(); | |
706 print(b.newName); | |
707 b.newName = 2; | |
708 } | |
709 '''); | |
710 } | |
711 | |
712 test_createChange_TypeParameterElement() { | |
713 indexTestUnit(''' | |
714 class A<Test> { | |
715 Test field; | |
716 List<Test> items; | |
717 Test method(Test p) => null; | |
718 } | |
719 '''); | |
720 // configure refactoring | |
721 createRenameRefactoringAtString('Test> {'); | |
722 expect(refactoring.refactoringName, 'Rename Type Parameter'); | |
723 expect(refactoring.oldName, 'Test'); | |
724 refactoring.newName = 'NewName'; | |
725 // validate change | |
726 return assertSuccessfulRename(''' | |
727 class A<NewName> { | |
728 NewName field; | |
729 List<NewName> items; | |
730 NewName method(NewName p) => null; | |
731 } | |
732 '''); | |
733 } | |
734 } | |
OLD | NEW |