/* * Created by IntelliJ IDEA. * User: dsl * Date: 07.05.2002 * Time: 13:59:01 * To change template for new class use * Code Style | Class Templates options (Tools | IDE Options). */ package com.intellij.refactoring; import com.intellij.JavaTestUtil; import com.intellij.codeInsight.CodeInsightUtil; import com.intellij.openapi.actionSystem.DataContext; import com.intellij.openapi.util.Pass; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiLocalVariable; import com.intellij.psi.PsiMethod; import com.intellij.refactoring.introduceField.ElementToWorkOn; import com.intellij.refactoring.introduceParameter.IntroduceParameterHandler; import com.intellij.refactoring.introduceParameter.IntroduceParameterProcessor; import com.intellij.refactoring.introduceParameter.Util; import com.intellij.refactoring.util.occurrences.ExpressionOccurrenceManager; import com.intellij.testFramework.TestDataPath; import gnu.trove.TIntArrayList; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.Nullable; import java.util.List; @TestDataPath("$CONTENT_ROOT/testData") public class IntroduceParameterTest extends LightRefactoringTestCase { @Override protected String getTestDataPath() { return JavaTestUtil.getJavaTestDataPath(); } private void doTest(int replaceFieldsWithGetters, boolean removeUnusedParameters, boolean searchForSuper, boolean declareFinal, final boolean generateDelegate) throws Exception { doTest(replaceFieldsWithGetters, removeUnusedParameters, searchForSuper, declareFinal, generateDelegate, null); } private void doTest(int replaceFieldsWithGetters, boolean removeUnusedParameters, boolean searchForSuper, boolean declareFinal, final boolean generateDelegate, String conflict) throws Exception { boolean enabled = true; try { configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); enabled = myEditor.getSettings().isVariableInplaceRenameEnabled(); myEditor.getSettings().setVariableInplaceRenameEnabled(false); perform(true, replaceFieldsWithGetters, "anObject", searchForSuper, declareFinal, removeUnusedParameters, generateDelegate); checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); if (conflict != null) { fail("Conflict expected"); } } catch (BaseRefactoringProcessor.ConflictsInTestsException e) { if (conflict == null) { throw e; } assertEquals(conflict, e.getMessage()); } finally { myEditor.getSettings().setVariableInplaceRenameEnabled(enabled); } } public void testNoUsages() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testSimpleUsage() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testMethodWithoutParams() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testParameterSubstitution() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testThisSubstitution() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testThisSubstitutionInQualifier() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false, "field Test.i is not accessible from method XTest.n(). Value for introduced parameter in that method call will be incorrect."); } public void testFieldAccess() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testMethodAccess() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testStaticFieldAccess() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testFieldWithGetterReplacement() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, false, false, false, false); } public void testFieldWithInaccessibleGetterReplacement() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testWeirdQualifier() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testSuperInExpression() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false, "Parameter initializer contains super, but not all calls to method are in its class."); } public void testNull() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testWeirdQualifierAndParameter() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testImplicitSuperCall() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testImplicitDefaultConstructor() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testLocalVarDeclaration() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testInternalSideEffect() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testQualifiedNew() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testAnonymousClass() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testSuperWithSideEffect() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false, "Parameter initializer contains super, but not all calls to method are in its class."); } public void testConflictingField() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, true, false, false); } public void testParameterInFor() throws Exception { configureByFile("/refactoring/introduceParameter/beforeParameterInFor.java"); performForLocal(true, true, true, false, false); checkResultByFile("/refactoring/introduceParameter/afterParameterInFor.java"); } public void testParameterJavaDoc1() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false); } public void testParameterJavaDoc2() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false); } public void testParameterJavaDoc3() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false); } public void testParameterJavaDocBeforeVararg() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false); } public void testIncompleteVararg() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, true, false, true, false, "Incomplete call(method()): 2 parameters expected but only 0 found\n" + "Incomplete call(method()): expected to delete the 0 parameter but only 0 parameters found"); } public void testIncorrectScope() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, true, true, false); } public void testExpectedType() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false); } public void testRemoveParameter() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false); } public void testRemoveParameterAfterVariable() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false); } public void testRemoveParameterInHierarchy() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false); } public void testRemoveParameterWithJavadoc() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false); } public void testVarargs() throws Exception { // IDEADEV-16828 doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testVarargs1() throws Exception { // IDEADEV-33555 doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false); } public void testUseInInnerClass() throws Exception { doTestThroughHandler(); } public void testLocalVarSelection() throws Exception { doTestThroughHandler(); } public void testGenerateDelegate() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, true); } public void testGenerateDelegateRemoveParameter() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, true); } public void testGenerateDelegateNoArgs() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, true); } public void testEnums() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testMethodUsageInThisMethodInheritor() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false); } public void testGetterQualifier() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false); } public void testIncompleteEnumDefinition() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false, "Incomplete call(Root()): 2 parameters expected but only 0 found\n" + "Incomplete call(Root()): expected to delete the 1 parameter but only 0 parameters found"); } public void testStaticFieldWithGetterReplacement() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false); } public void testGenerateDelegateInSuperClass() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, true, true, true); } public void testGenerateDelegateInSuperInterface() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, true, true, true); } public void testReplaceAllAndDeleteUnused() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false); } public void testDiamond2Raw() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false); } public void testDiamondOccurrences() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false); } public void testSubstituteTypeParams() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false); } public void testDelegateWithVarargs() throws Exception { doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, true); } private void doTestThroughHandler() throws Exception { configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); boolean enabled = true; try { configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); enabled = myEditor.getSettings().isVariableInplaceRenameEnabled(); myEditor.getSettings().setVariableInplaceRenameEnabled(false); new IntroduceParameterHandler().invoke(getProject(), myEditor, myFile, new DataContext() { @Override @Nullable public Object getData(@NonNls final String dataId) { return null; } }); checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); } finally { myEditor.getSettings().setVariableInplaceRenameEnabled(enabled); } } public void testEnclosingWithParamDeletion() throws Exception { configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java"); perform(true, 0, "anObject", false, true, true, false, 1); checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java"); } private static boolean perform(boolean replaceAllOccurences, int replaceFieldsWithGetters, @NonNls String parameterName, boolean searchForSuper, boolean declareFinal, final boolean removeUnusedParameters, final boolean generateDelegate) { return perform(replaceAllOccurences, replaceFieldsWithGetters, parameterName, searchForSuper, declareFinal, removeUnusedParameters, generateDelegate, 0); } private static boolean perform(boolean replaceAllOccurences, int replaceFieldsWithGetters, @NonNls String parameterName, boolean searchForSuper, boolean declareFinal, final boolean removeUnusedParameters, final boolean generateDelegate, int enclosingLevel) { final ElementToWorkOn[] elementToWorkOn = new ElementToWorkOn[1]; ElementToWorkOn .processElementToWorkOn(myEditor, myFile, "INtr param", HelpID.INTRODUCE_PARAMETER, getProject(), new Pass() { @Override public void pass(final ElementToWorkOn e) { if (e == null) return; elementToWorkOn[0] = e; } }); final PsiExpression expr = elementToWorkOn[0].getExpression(); final PsiLocalVariable localVar = elementToWorkOn[0].getLocalVariable(); PsiElement context = expr == null ? localVar : expr; PsiMethod method = Util.getContainingMethod(context); if (method == null) return false; final List methods = com.intellij.refactoring.introduceParameter.IntroduceParameterHandler.getEnclosingMethods(method); assertTrue(methods.size() > enclosingLevel); method = methods.get(enclosingLevel); final PsiMethod methodToSearchFor; if (searchForSuper) { methodToSearchFor = method.findDeepestSuperMethod(); } else { methodToSearchFor = method; } PsiExpression[] occurences; PsiExpression initializer; if (expr == null) { initializer = localVar.getInitializer(); occurences = CodeInsightUtil.findReferenceExpressions(method, localVar); } else { initializer = expr; occurences = new ExpressionOccurrenceManager(expr, method, null).findExpressionOccurrences(); } TIntArrayList parametersToRemove = removeUnusedParameters ? Util.findParametersToRemove(method, initializer, occurences) : new TIntArrayList(); new IntroduceParameterProcessor( getProject(), method, methodToSearchFor, initializer, expr, localVar, true, parameterName, replaceAllOccurences, replaceFieldsWithGetters, declareFinal, generateDelegate, null, parametersToRemove).run(); myEditor.getSelectionModel().removeSelection(); return true; } private static void performForLocal(boolean searchForSuper, boolean removeLocalVariable, boolean replaceAllOccurrences, boolean declareFinal, final boolean removeUnusedParameters) { final int offset = myEditor.getCaretModel().getOffset(); final PsiElement element = myFile.findElementAt(offset).getParent(); assertTrue(element instanceof PsiLocalVariable); PsiMethod method = Util.getContainingMethod(element); final PsiMethod methodToSearchFor; if (searchForSuper) { final PsiMethod deepestSuperMethod = method.findDeepestSuperMethod(); methodToSearchFor = deepestSuperMethod != null ? deepestSuperMethod : method; } else { methodToSearchFor = method; } assertNotNull(method); assertNotNull(methodToSearchFor); final PsiLocalVariable localVariable = (PsiLocalVariable)element; final PsiExpression parameterInitializer = localVariable.getInitializer(); TIntArrayList parametersToRemove = removeUnusedParameters ? Util.findParametersToRemove(method, parameterInitializer, null) : new TIntArrayList(); new IntroduceParameterProcessor( getProject(), method, methodToSearchFor, parameterInitializer, null, localVariable, removeLocalVariable, localVariable.getName(), replaceAllOccurrences, IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, declareFinal, false, null, parametersToRemove).run(); } }