diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java index 80c49afb9125..99cd3259e3e4 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationStatementProcessor.java @@ -520,7 +520,7 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { myLabeler.migrateExpressionType(value, adjustMigrationTypeIfGenericArrayCreation(declarationType, value), myStatement, - TypeConversionUtil.isAssignable(declarationType, valueType), true); + left.isVarArgs() ? isVarargAssignable(left, right) : TypeConversionUtil.isAssignable(declarationType, valueType), true); } break; @@ -663,6 +663,10 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { public Pair getTypePair() { return Pair.create(myOriginType, myType); } + + public boolean isVarArgs() { + return myType instanceof PsiEllipsisType && myOriginType instanceof PsiEllipsisType; + } } private static class TypeInfection { @@ -731,4 +735,18 @@ class TypeMigrationStatementProcessor extends JavaRecursiveElementVisitor { } return result; } + + private static boolean isVarargAssignable(TypeView left, TypeView right) { + Pair leftPair = left.getTypePair(); + Pair rightPair = right.getTypePair(); + + PsiType leftOrigin = leftPair.getFirst(); + PsiType rightOrigin = rightPair.getFirst(); + + boolean isDirectlyAssignable = TypeConversionUtil.isAssignable(leftOrigin, rightOrigin); + + return TypeConversionUtil.isAssignable(isDirectlyAssignable ? + leftPair.getSecond() : + ((PsiEllipsisType)leftPair.getSecond()).getComponentType(), rightPair.getSecond()); + } } diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/rules/RootTypeConversionRule.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/rules/RootTypeConversionRule.java index b628abf857ae..df5234d34a9c 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/rules/RootTypeConversionRule.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/rules/RootTypeConversionRule.java @@ -27,6 +27,8 @@ import com.intellij.util.IncorrectOperationException; import com.siyeh.ig.style.UnnecessarilyQualifiedStaticUsageInspection; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; + /** * @author anna * Date: 08-Aug-2008 @@ -143,12 +145,26 @@ public class RootTypeConversionRule extends TypeConversionRule { private static boolean areParametersAssignable(PsiType migrationType, int paramId, PsiExpression[] actualParams) { if (migrationType instanceof PsiEllipsisType) { - for (int i = paramId; i < actualParams.length; i++) { - if (!TypeConversionUtil.areTypesAssignmentCompatible(migrationType, actualParams[i])) { - return false; - } + if (actualParams.length == paramId) { + // no arguments for ellipsis + return true; } - return true; + else if (actualParams.length == paramId + 1) { + // only one argument for ellipsis + return TypeConversionUtil.areTypesAssignmentCompatible(migrationType, actualParams[paramId]) || + TypeConversionUtil.areTypesAssignmentCompatible(((PsiEllipsisType)migrationType).getComponentType(), actualParams[paramId]); + } + else if (actualParams.length > paramId + 1) { + // few arguments + PsiType componentType = ((PsiEllipsisType)migrationType).getComponentType(); + for (int i = paramId; i < actualParams.length; i++) { + if (!TypeConversionUtil.areTypesAssignmentCompatible(componentType, actualParams[i])) { + return false; + } + } + return true; + } + throw new AssertionError(" migrationType: " + migrationType + ", paramId: " + paramId + ", actualParameters: " + Arrays.toString(actualParams)); } else { return TypeConversionUtil.areTypesAssignmentCompatible(migrationType, actualParams[paramId]); } diff --git a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java index 9c8145e51faf..fb8e00324608 100644 --- a/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java +++ b/java/typeMigration/test/com/intellij/refactoring/TypeMigrationTest.java @@ -866,6 +866,10 @@ public class TypeMigrationTest extends TypeMigrationTestBase { doTestFieldType("migrationField", myJavaFacade.getElementFactory().createTypeFromText("Test", null)); } + public void testGenericEllipsis2() { + doTestFieldType("migrationField", myJavaFacade.getElementFactory().createTypeFromText("Test", null)); + } + private void doTestReturnType(final String methodName, final String migrationType) { start(new RulesProvider() { @Override diff --git a/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/after/Test.items b/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/after/Test.items new file mode 100644 index 000000000000..3b7438cc5f10 --- /dev/null +++ b/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/after/Test.items @@ -0,0 +1,12 @@ +Types: +PsiField:migrationField : Test +PsiMethodCallExpression:migrationField.method(x1, x2) : void +PsiReferenceExpression:migrationField : Test + +Conversions: +migrationField.method(x1, x2) -> $ +x1 -> $ +x2 -> $ + +New expression type changes: +Fails: diff --git a/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/after/test.java b/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/after/test.java new file mode 100644 index 000000000000..69b8a12eaa9b --- /dev/null +++ b/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/after/test.java @@ -0,0 +1,11 @@ +class Test { + private static Test migrationField; + + private static void m(Short x1, Short x2) { + migrationField.method(x1, x2); + } + + void method(X... xes) { + + } +} diff --git a/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/before/test.java b/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/before/test.java new file mode 100644 index 000000000000..3efd6b2d1ee3 --- /dev/null +++ b/java/typeMigration/testData/refactoring/typeMigration/genericEllipsis2/before/test.java @@ -0,0 +1,11 @@ +class Test { + private static Test migrationField; + + private static void m(Short x1, Short x2) { + migrationField.method(x1, x2); + } + + void method(X... xes) { + + } +}