introduce parameter: ensure varargs are not substituted twice (IDEA-161779)

This commit is contained in:
Anna.Kozlova
2016-09-28 09:16:48 +02:00
parent 347ee7481d
commit 946991683d
4 changed files with 58 additions and 28 deletions
@@ -22,14 +22,13 @@ import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.refactoring.IntroduceParameterRefactoring;
import com.intellij.refactoring.util.RefactoringUtil;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Map;
@@ -141,7 +140,26 @@ public class OldReferenceResolver {
final String varargsJoin = StringUtil.join(ContainerUtil.map2Array(myActualArgs, String.class,
expression -> expression != null ? expression.getText() : "null"), index + 1, myActualArgs.length, ",");
String newArrayInitializer = "new " + ((PsiEllipsisType)parameterType).toArrayType().getCanonicalText() + " {" + varargsJoin + "}";
initializer = replaceInitializerWithVarargSubstitution(factory, parameter, initializer, newArrayInitializer);
final String tempVar = getTempVar((PsiExpression)JavaCodeStyleManager.getInstance(myProject).shortenClassReferences(factory.createExpressionFromText(newArrayInitializer, myContext)));
final Map<PsiExpression, String> map = new HashMap<>();
if (initializer instanceof PsiReferenceExpression && Comparing.strEqual(parameter.getName(), initializer.getText())) {
newExpr.replace(factory.createExpressionFromText(tempVar, myContext));
}
else {
initializer = (PsiExpression)initializer.copy();
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
if (Comparing.strEqual(parameter.getName(), expression.getText())) {
map.put(expression, tempVar);
}
}
});
replaceOldRefWithNew(map.entrySet(), factory);
newExpr.replace(factory.createExpressionFromText(getTempVar(actualArg, initializer), null));
}
return;
}
if (RefactoringUtil.verifySafeCopyExpression(actualArg) == RefactoringUtil.EXPR_COPY_PROHIBITED) {
@@ -209,31 +227,6 @@ public class OldReferenceResolver {
}
}
@NotNull
private PsiExpression replaceInitializerWithVarargSubstitution(PsiElementFactory factory,
final PsiParameter parameter,
PsiExpression initializer, String newArrayInitializer) {
final String tempVar = getTempVar(factory.createExpressionFromText(newArrayInitializer, myContext));
final Map<PsiExpression, String> map = new HashMap<>();
if (initializer instanceof PsiReferenceExpression && Comparing.strEqual(parameter.getName(), initializer.getText())) {
initializer = factory.createExpressionFromText(tempVar, myContext);
}
else {
initializer = (PsiExpression)initializer.copy();
initializer.accept(new JavaRecursiveElementWalkingVisitor() {
@Override
public void visitReferenceExpression(PsiReferenceExpression expression) {
super.visitReferenceExpression(expression);
if (Comparing.strEqual(parameter.getName(), expression.getText())) {
map.put(expression, tempVar);
}
}
});
replaceOldRefWithNew(map.entrySet(), factory);
}
return initializer;
}
private PsiExpression getInstanceRef(PsiElementFactory factory) throws IncorrectOperationException {
int copyingSafetyLevel = RefactoringUtil.verifySafeCopyExpression(myInstanceRef);
@@ -0,0 +1,17 @@
class Test {
void f(String strings) {
final String[] strings1 = new String[]{"c", "d"};
final String foo = foo(strings1);
extract("a", "b", foo);
}
private static void extract(final String from, final String to, String anObject) {
}
public String foo(String[] extensions) {
return null
}
}
@@ -0,0 +1,16 @@
class Test {
void f(String strings) {
extract("a", "b", "c", "d");
}
private static void extract(final String from, final String to, final String... extensions) {
<selection>foo(extensions)</selection>;
}
public String foo(String[] extensions) {
return null
}
}
@@ -158,6 +158,10 @@ public class IntroduceParameterTest extends LightRefactoringTestCase {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, true, false, false, false);
}
public void testMethodCallRefToVararg() throws Exception {
doTest(IntroduceParameterRefactoring.REPLACE_FIELDS_WITH_GETTERS_INACCESSIBLE, true, 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");