blob: 0423d0939242413b1d087b7481336721cef503fb [file] [log] [blame]
/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.refactoring;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.pom.java.LanguageLevel;
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 com.intellij.util.ObjectUtils;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.List;
/**
* @author dsl
* @since 07.05.2002
*/
@TestDataPath("$CONTENT_ROOT/testData")
public class IntroduceParameterTest extends LightRefactoringTestCase {
@NotNull
@Override
protected String getTestDataPath() {
return JavaTestUtil.getJavaTestDataPath();
}
@Override
protected LanguageLevel getLanguageLevel() {
return LanguageLevel.JDK_1_7;
}
public void testNoUsages() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testSimpleUsage() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testMethodWithoutParams() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testParameterSubstitution() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testThisSubstitution() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testThisSubstitutionInQualifier() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false,
"field <b><code>Test.i</code></b> is not accessible from method <b><code>XTest.n()</code></b>. " +
"Value for introduced parameter in that method call will be incorrect.");
}
public void testFieldAccess() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testMethodAccess() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testStaticFieldAccess() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testFieldWithGetterReplacement() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, false, false, false, false);
}
public void testFieldWithInaccessibleGetterReplacement() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testWeirdQualifier() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testSuperInExpression() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false,
"Parameter initializer contains <b><code>super</code></b>, but not all calls to method are in its class");
}
public void testNull() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testWeirdQualifierAndParameter() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testImplicitSuperCall() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testImplicitDefaultConstructor() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testLocalVarDeclaration() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testInternalSideEffect() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testQualifiedNew() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testAnonymousClass() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testSuperWithSideEffect() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false,
"Parameter initializer contains <b><code>super</code></b>, but not all calls to method are in its class");
}
public void testConflictingField() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, true, false, false);
}
public void testParameterInFor() {
configureByFile("/refactoring/introduceParameter/beforeParameterInFor.java");
performForLocal(true, true, true, false, false);
checkResultByFile("/refactoring/introduceParameter/afterParameterInFor.java");
}
public void testParameterJavaDoc1() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false);
}
public void testParameterJavaDoc2() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false);
}
public void testParameterJavaDoc3() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false);
}
public void testParameterJavaDocBeforeVararg() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false);
}
public void testIncompleteVararg() {
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() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, true, true, false);
}
public void testExpectedType() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, true, false);
}
public void testRemoveParameter() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false);
}
public void testRemoveParameterAfterVariable() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false);
}
public void testRemoveParameterInHierarchy() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false);
}
public void testRemoveParameterWithJavadoc() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false);
}
public void testVarargs() { // IDEADEV-16828
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testVarargs1() { // IDEADEV-33555
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, false);
}
public void testUseInInnerClass() {
doTestThroughHandler();
}
public void testLocalVarSelection() {
doTestThroughHandler();
}
public void testGenerateDelegate() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, true);
}
public void testGenerateDelegateRemoveParameter() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, true, false, false, true);
}
public void testGenerateDelegateNoArgs() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, true);
}
public void testEnums() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testMethodUsageInThisMethodInheritor() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
public void testGetterQualifier() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, false, false, false, false);
}
public void testArrayInitializer() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, true, false, false, false);
}
public void testIncompleteEnumDefinition() {
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() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testGenerateDelegateInSuperClass() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, true, true, true);
}
public void testGenerateDelegateInSuperInterface() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, true, true, true);
}
public void testReplaceAllAndDeleteUnused() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testDiamond2Raw() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testDiamondOccurrences() {
final LanguageLevel oldLevel = getLanguageLevel();
try {
setLanguageLevel(LanguageLevel.JDK_1_7);
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
finally {
setLanguageLevel(oldLevel);
}
}
public void testPreserveDiamondOccurrences() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testSubstituteTypeParams() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testDelegateWithVarargs() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, true);
}
public void testSelfReference() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testSelfReferenceVarargs() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testSelfReferenceVarargs1() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testSimplifiedResultedType() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
public void testPackageReferenceShouldBeIgnored() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_ALL, true, false, true, false);
}
private void doTestThroughHandler() {
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() {
configureByFile("/refactoring/introduceParameter/before" + getTestName(false) + ".java");
perform(true, 0, "anObject", false, true, true, false, 1);
checkResultByFile("/refactoring/introduceParameter/after" + getTestName(false) + ".java");
}
public void testTypeAnnotation() {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_NONE, false, false, false, false);
}
private void doTest(int replaceFieldsWithGetters,
boolean removeUnusedParameters,
boolean searchForSuper,
boolean declareFinal,
boolean generateDelegate) {
doTest(replaceFieldsWithGetters, removeUnusedParameters, searchForSuper, declareFinal, generateDelegate, null);
}
private void doTest(int replaceFieldsWithGetters,
boolean removeUnusedParameters,
boolean searchForSuper,
boolean declareFinal,
boolean generateDelegate,
String conflict) {
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);
}
}
private static boolean perform(boolean replaceAllOccurrences,
int replaceFieldsWithGetters,
@NonNls String parameterName,
boolean searchForSuper,
boolean declareFinal,
boolean removeUnusedParameters,
boolean generateDelegate) {
return perform(
replaceAllOccurrences, replaceFieldsWithGetters, parameterName, searchForSuper, declareFinal,
removeUnusedParameters, generateDelegate, 0
);
}
private static boolean perform(boolean replaceAllOccurrences,
int replaceFieldsWithGetters,
@NonNls String parameterName,
boolean searchForSuper,
boolean declareFinal,
boolean removeUnusedParameters,
boolean generateDelegate,
int enclosingLevel) {
final ElementToWorkOn[] elementToWorkOn = new ElementToWorkOn[1];
ElementToWorkOn.processElementToWorkOn(myEditor, myFile, "INtr param", HelpID.INTRODUCE_PARAMETER, getProject(),
new ElementToWorkOn.ElementsProcessor<ElementToWorkOn>() {
@Override
public boolean accept(ElementToWorkOn el) {
return true;
}
@Override
public void pass(final ElementToWorkOn e) {
if (e != null) {
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<PsiMethod> methods = com.intellij.refactoring.introduceParameter.IntroduceParameterHandler.getEnclosingMethods(method);
assertTrue(methods.size() > enclosingLevel);
method = methods.get(enclosingLevel);
final PsiMethod methodToSearchFor;
if (searchForSuper) {
methodToSearchFor = method.findDeepestSuperMethods()[0];
}
else {
methodToSearchFor = method;
}
PsiExpression[] occurrences;
PsiExpression initializer;
if (expr == null) {
initializer = localVar.getInitializer();
assertNotNull(initializer);
occurrences = CodeInsightUtil.findReferenceExpressions(method, localVar);
}
else {
initializer = expr;
occurrences = new ExpressionOccurrenceManager(expr, method, null).findExpressionOccurrences();
}
TIntArrayList parametersToRemove = removeUnusedParameters ? Util.findParametersToRemove(method, initializer, occurrences)
: new TIntArrayList();
new IntroduceParameterProcessor(
getProject(), method, methodToSearchFor, initializer, expr, localVar, true, parameterName, replaceAllOccurrences,
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 = ObjectUtils.assertNotNull(myFile.findElementAt(offset)).getParent();
assertTrue(element instanceof PsiLocalVariable);
PsiMethod method = Util.getContainingMethod(element);
final PsiMethod methodToSearchFor;
if (searchForSuper) {
PsiMethod[] deepestSuperMethods = method.findDeepestSuperMethods();
methodToSearchFor = deepestSuperMethods.length > 0 ? deepestSuperMethods[0] : method;
}
else {
methodToSearchFor = method;
}
assertNotNull(method);
assertNotNull(methodToSearchFor);
final PsiLocalVariable localVariable = (PsiLocalVariable)element;
final PsiExpression parameterInitializer = localVariable.getInitializer();
assertNotNull(parameterInitializer);
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();
}
}