remove redundant casts when extract changed parameter type accordingly (IDEA-79743)
[idea/community.git] / java / java-tests / testSrc / com / intellij / refactoring / ExtractMethodTest.java
1 package com.intellij.refactoring;
2
3 import com.intellij.JavaTestUtil;
4 import com.intellij.codeInsight.CodeInsightUtil;
5 import com.intellij.openapi.editor.Editor;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.psi.PsiElement;
8 import com.intellij.psi.PsiExpression;
9 import com.intellij.psi.PsiFile;
10 import com.intellij.psi.codeStyle.CodeStyleSettings;
11 import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
12 import com.intellij.refactoring.extractMethod.ExtractMethodProcessor;
13 import com.intellij.refactoring.extractMethod.PrepareFailedException;
14 import com.intellij.refactoring.introduceVariable.IntroduceVariableBase;
15 import com.intellij.refactoring.util.duplicates.Match;
16 import com.intellij.testFramework.LightCodeInsightTestCase;
17 import com.intellij.util.IncorrectOperationException;
18 import org.jetbrains.annotations.NonNls;
19
20 import java.util.List;
21
22 public class ExtractMethodTest extends LightCodeInsightTestCase {
23   @NonNls private static final String BASE_PATH = "/refactoring/extractMethod/";
24   private boolean myCatchOnNewLine = true;
25
26   @Override
27   protected String getTestDataPath() {
28     return JavaTestUtil.getJavaTestDataPath();
29   }
30
31   public void testExitPoints1() throws Exception {
32     doExitPointsTest(true);
33   }
34
35   public void testExitPoints2() throws Exception {
36     doTest();
37   }
38
39   public void testExitPoints3() throws Exception {
40     doExitPointsTest(true);
41   }
42
43   public void testExitPoints4() throws Exception {
44     doExitPointsTest(false);
45   }
46
47   public void testExitPointsInsideLoop() throws Exception {
48     doExitPointsTest(true);
49   }
50
51   public void testExitPoints5() throws Exception {
52     doTest();
53   }
54
55   public void testExitPoints6() throws Exception {
56     doExitPointsTest(false);
57   }
58
59   public void testExitPoints7() throws Exception {
60     doExitPointsTest(false);
61   }
62
63   public void testExitPoints8() throws Exception {
64     doExitPointsTest(false);
65   }
66
67   public void testExitPoints9() throws Exception {
68     doExitPointsTest(false);
69   }
70
71   public void testContinueInside() throws Exception {
72     doTest();
73   }
74
75   public void testBooleanExpression() throws Exception {
76     doTest();
77   }
78
79   public void testScr6241() throws Exception {
80     doTest();
81   }
82
83   public void testScr7091() throws Exception {
84     doTest();
85   }
86
87   public void testScr10464() throws Exception {
88     doTest();
89   }
90
91   public void testScr9852() throws Exception {
92     doTest();
93   }
94
95   public void testUseVarAfterTry() throws Exception {
96     doTest();
97   }
98
99   public void testOneBranchAssignment() throws Exception {
100     doTest();
101   }
102
103   public void testExtractFromCodeBlock() throws Exception {
104     doTest();
105   }
106
107   public void testUnusedInitializedVar() throws Exception {
108     doTest();
109   }
110
111   public void testTryFinally() throws Exception {
112     doTest();
113   }
114
115   public void testFinally() throws Exception {
116     doTest();
117   }
118
119   public void testExtractFromAnonymous() throws Exception {
120     doTest();
121   }
122
123   public void testSCR12245() throws Exception {
124     doTest();
125   }
126
127   public void testLeaveCommentsWhenExpressionExtracted() throws Exception {
128     doTest();
129   }
130
131   public void testSCR15815() throws Exception {
132     doTest();
133   }
134
135   public void testSCR27887() throws Exception {
136     doTest();
137   }
138
139   public void testSCR28427() throws Exception {
140     doTest();
141   }
142
143   public void testTryFinallyInsideFor() throws Exception {
144     doTest();
145   }
146
147   public void testExtractFromTryFinally() throws Exception {
148     doTest();
149   }
150
151   public void testExtractAssignmentExpression() throws Exception {
152     doTest();
153   }
154
155   public void testExtractAssignmentExpressionFromStatement() throws Exception {
156     doTest();
157   }
158
159   public void _testExtractFromTryFinally2() throws Exception {  // IDEADEV-11844
160     doTest();
161   }
162
163   public void testLesyaBug() throws Exception {
164     myCatchOnNewLine = false;
165     doTest();
166   }
167
168   public void testForEach() throws Exception {
169     doTest();
170   }
171
172   public void testAnonInner() throws Exception {
173     doTest();
174   }
175
176
177   public void testConflictingAnonymous() throws Exception {
178     doTest();
179   }
180
181
182   public void testFinalParamUsedInsideAnon() throws Exception {
183     CodeStyleSettingsManager.getSettings(getProject()).GENERATE_FINAL_PARAMETERS = false;
184     doTest();
185   }
186
187   public void testNonFinalWritableParam() throws Exception {
188     CodeStyleSettingsManager.getSettings(getProject()).GENERATE_FINAL_PARAMETERS = true;
189     doTest();
190   }
191
192   public void testCodeDuplicatesWithContinue() throws Exception {
193     doDuplicatesTest();
194   }
195
196   public void testCodeDuplicatesWithContinueNoReturn() throws Exception {
197     doDuplicatesTest();
198   }
199
200   public void testCodeDuplicatesWithStaticInitializer() throws Exception {
201     doDuplicatesTest();
202   }
203
204   public void testExpressionDuplicates() throws Exception {
205     doDuplicatesTest();
206   }
207
208   public void testCodeDuplicates() throws Exception {
209     doDuplicatesTest();
210   }
211
212   public void testCodeDuplicates2() throws Exception {
213     doDuplicatesTest();
214   }
215
216   public void testCodeDuplicates3() throws Exception {
217     doDuplicatesTest();
218   }
219
220   public void testCodeDuplicates4() throws Exception {
221     doDuplicatesTest();
222   }
223
224   public void testCodeDuplicates5() throws Exception {
225     doDuplicatesTest();
226   }
227
228   public void testCodeDuplicatesWithOutputValue() throws Exception {
229     doDuplicatesTest();
230   }
231
232   public void testCodeDuplicatesWithOutputValue1() throws Exception {
233     doDuplicatesTest();
234   }
235
236   public void testCodeDuplicatesWithMultExitPoints() throws Exception {
237     doDuplicatesTest();
238   }
239
240   public void testCodeDuplicatesWithReturn() throws Exception {
241     doDuplicatesTest();
242   }
243
244   public void testCodeDuplicatesWithReturn2() throws Exception {
245     doDuplicatesTest();
246   }
247
248   public void testCodeDuplicatesWithComments() throws Exception {
249     doDuplicatesTest();
250   }
251
252   public void testSCR32924() throws Exception {
253     doDuplicatesTest();
254   }
255
256   public void testFinalOutputVar() throws Exception {
257     doDuplicatesTest();
258   }
259
260   public void testIdeaDev2291() throws Exception {
261     doTest();
262   }
263
264   public void testOxfordBug() throws Exception {
265     doTest();
266   }
267
268   public void testIDEADEV33368() throws Exception {
269     doTest();
270   }
271
272   public void testInlineCreated2ReturnLocalVariablesOnly() throws Exception {
273     doTest();
274   }
275
276   public void testGuardMethodDuplicates() throws Exception {
277     doDuplicatesTest();
278   }
279
280   public void testGuardMethodDuplicates1() throws Exception {
281     doDuplicatesTest();
282   }
283
284   public void testInstanceMethodDuplicatesInStaticContext() throws Exception {
285     doDuplicatesTest();
286   }
287
288
289   public void testLValueNotDuplicate() throws Exception {
290     doDuplicatesTest();
291   }
292
293   protected void doDuplicatesTest() throws Exception {
294     doTest(true);
295   }
296
297   public void testExtractFromFinally() throws Exception {
298     doTest();
299   }
300
301   public void testNoShortCircuit() throws Exception {
302     doTest();
303   }
304
305   public void testStopFolding() throws Exception {
306     doTest();
307   }
308
309   public void testStopFoldingPostfixInside() throws Exception {
310     doTest();
311   }
312
313
314   public void testIDEADEV11748() throws Exception {
315     doTest();
316   }
317
318   public void testIDEADEV11848() throws Exception {
319     doTest();
320   }
321
322   public void testIDEADEV11036() throws Exception {
323     doTest();
324   }
325
326   public void testLocalClass() throws Exception {
327     doPrepareErrorTest("Cannot extract method because the selected code fragment uses local classes defined outside of the fragment");
328   }
329
330   public void testLocalClassUsage() throws Exception {
331     doPrepareErrorTest("Cannot extract method because the selected code fragment defines local classes used outside of the fragment");
332   }
333
334   public void testStaticImport() throws Exception {
335     doTest();
336   }
337
338   public void testThisCall() throws Exception {
339     doTest();
340   }
341
342   public void testChainedConstructor() throws Exception {
343     doChainedConstructorTest(false);
344   }
345
346   public void testChainedConstructorDuplicates() throws Exception {
347     doChainedConstructorTest(true);
348   }
349
350   public void testChainedConstructorInvalidDuplicates() throws Exception {
351     doChainedConstructorTest(true);
352   }
353
354   public void testReturnFromTry() throws Exception {
355     doTest();
356   }
357
358   public void testLocalClassDefinedInMethodWhichIsUsedLater() throws Exception {
359     doPrepareErrorTest("Cannot extract method because the selected code fragment defines variable of local class type used outside of the fragment");
360   }
361
362   public void testForceBraces() throws Exception {
363     final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
364     int old = settings.IF_BRACE_FORCE;
365     settings.IF_BRACE_FORCE = CodeStyleSettings.FORCE_BRACES_ALWAYS;
366     try {
367       doTest();
368     }
369     finally {
370       settings.IF_BRACE_FORCE = old;
371     }
372   }
373
374   public void testConstantConditionsAffectingControlFlow() throws Exception {
375     doTest();
376   }
377   public void testNotInitializedInsideFinally() throws Exception {
378     doTest();
379   }
380
381   public void testGenericsParameters() throws Exception {
382     doTest();
383   }
384
385   public void testUnusedGenerics() throws Exception {
386     doTest();
387   }
388
389   public void testParamsUsedInLocalClass() throws Exception {
390     doTest();
391   }
392
393   private void doChainedConstructorTest(final boolean replaceAllDuplicates) throws Exception {
394     configureByFile(BASE_PATH + getTestName(false) + ".java");
395     boolean success = performExtractMethod(true, replaceAllDuplicates, getEditor(), getFile(), getProject(), true);
396     assertTrue(success);
397     checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
398   }
399
400   public void testReassignedVarAfterCall() throws Exception {
401     final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
402     boolean oldGenerateFinalLocals = settings.GENERATE_FINAL_LOCALS;
403     try {
404       settings.GENERATE_FINAL_LOCALS = true;
405       doTest();
406     }
407     finally {
408       settings.GENERATE_FINAL_LOCALS = oldGenerateFinalLocals;
409     }
410   }
411
412   public void testNullableCheck() throws Exception {
413     doTest();
414   }
415   
416   public void testNullableCheck1() throws Exception {
417     doTest();
418   }
419
420   public void testNullableCheckVoid() throws Exception {
421     doTest();
422   }
423
424   public void testNullableCheckDontMissFinal() throws Exception {
425     doTest();
426   }
427
428   public void testSimpleArrayAccess() throws Exception {
429     doTest();
430   }
431
432   public void testArrayAccess() throws Exception {
433     doTest();
434   }
435
436   public void testArrayAccess1() throws Exception {
437     doTest();
438   }
439
440   public void testArrayAccessWithLocalIndex() throws Exception {
441     doTest();
442   }
443
444   public void testArrayAccessWithDuplicates() throws Exception {
445     doDuplicatesTest();
446   }
447
448   public void testVerboseArrayAccess() throws Exception {
449     doTest();
450   }
451
452   public void testReturnStatementFolding() throws Exception {
453     doTest();
454   }
455
456   public void testWriteArrayAccess() throws Exception {
457     doTest();
458   }
459
460   public void testShortCircuit() throws Exception {
461     doTest();
462   }
463
464   public void testRecursiveCallToExtracted() throws Exception {
465     doTest();
466   }
467
468   public void testCodeDuplicatesVarargsShouldNotChangeReturnType() throws Exception {
469     doDuplicatesTest();
470   }
471
472   public void testParametersFromAnonymous() throws Exception {
473     doTest();
474   }
475
476   public void testCast4ParamGeneration() throws Exception {
477     doTest();
478   }
479
480   public void testNearComment() throws Exception {
481     doTest();
482   }
483
484   public void testFoldInWhile() throws Exception {
485     doTest();
486   }
487
488   public void testComplexTypeParams() throws Exception {
489     doTest();
490   }
491
492   public void testExtractWithLeadingComment() throws Exception {
493     doTest();
494   }
495
496   public void testInvalidReference() throws Exception {
497     doTest();
498   }
499
500   public void testRedundantCast() throws Exception {
501     doTest();
502   }
503
504   private void doPrepareErrorTest(final String expectedMessage) throws Exception {
505     String expectedError = null;
506     try {
507       doExitPointsTest(false);
508     }
509     catch(PrepareFailedException ex) {
510       expectedError = ex.getMessage();
511     }
512     assertEquals(expectedMessage, expectedError);
513   }
514
515   private void doExitPointsTest(boolean shouldSucceed) throws Exception {
516     String fileName = getTestName(false) + ".java";
517     configureByFile(BASE_PATH + fileName);
518     boolean success = performAction(false, false);
519     assertEquals(shouldSucceed, success);
520   }
521
522   void doTest() throws Exception {
523     final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(getProject());
524     settings.ELSE_ON_NEW_LINE = true;
525     settings.CATCH_ON_NEW_LINE = myCatchOnNewLine;
526     doTest(true);
527   }
528
529   private void doTest(boolean duplicates) throws Exception {
530     configureByFile(BASE_PATH + getTestName(false) + ".java");
531     boolean success = performAction(true, duplicates);
532     assertTrue(success);
533     checkResultByFile(BASE_PATH + getTestName(false) + "_after.java");
534   }
535
536   private static boolean performAction(boolean doRefactor, boolean replaceAllDuplicates) throws Exception {
537     return performExtractMethod(doRefactor, replaceAllDuplicates, getEditor(), getFile(), getProject());
538   }
539
540   public static boolean performExtractMethod(boolean doRefactor, boolean replaceAllDuplicates, Editor editor, PsiFile file, Project project)
541     throws PrepareFailedException, IncorrectOperationException {
542     return performExtractMethod(doRefactor, replaceAllDuplicates, editor, file, project, false);
543   }
544
545   public static boolean performExtractMethod(boolean doRefactor, boolean replaceAllDuplicates, Editor editor, PsiFile file, Project project,
546                                              final boolean extractChainedConstructor)
547     throws PrepareFailedException, IncorrectOperationException {
548     int startOffset = editor.getSelectionModel().getSelectionStart();
549     int endOffset = editor.getSelectionModel().getSelectionEnd();
550
551     PsiElement[] elements;
552     PsiExpression expr = CodeInsightUtil.findExpressionInRange(file, startOffset, endOffset);
553     if (expr != null) {
554       elements = new PsiElement[]{expr};
555     }
556     else {
557       elements = CodeInsightUtil.findStatementsInRange(file, startOffset, endOffset);
558     }
559     if (elements.length == 0) {
560       final PsiExpression expression = IntroduceVariableBase.getSelectedExpression(project, file, startOffset, endOffset);
561       if (expression != null) {
562         elements = new PsiElement[]{expression};
563       }
564     }
565     assertTrue(elements.length > 0);
566
567     final ExtractMethodProcessor processor =
568       new ExtractMethodProcessor(project, editor, elements, null, "Extract Method", "newMethod", null);
569     processor.setShowErrorDialogs(false);
570     processor.setChainedConstructor(extractChainedConstructor);
571
572     if (!processor.prepare()) {
573       return false;
574     }
575
576     if (doRefactor) {
577       processor.testRun();
578     }
579
580     if (replaceAllDuplicates) {
581       final List<Match> duplicates = processor.getDuplicates();
582       for (final Match match : duplicates) {
583         if (!match.getMatchStart().isValid() || !match.getMatchEnd().isValid()) continue;
584         processor.processMatch(match);
585       }
586     }
587
588     return true;
589   }
590 }