From 23cf1ec2157ed33e9cfd533ca79ab0f8e378d399 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Thu, 5 May 2016 15:15:25 +0300 Subject: [PATCH] type migration: multiple declaration IDEA-154937 initial --- .../ChangeTypeSignatureHandler.java | 41 +++++++++++++------ .../typeMigration/TypeMigrationLabeler.java | 6 ++- .../typeMigration/TypeMigrationProcessor.java | 11 ++--- .../TypeMigrationReplacementUtil.java | 2 +- .../refactoring/typeMigration/Util.java | 15 +++++-- .../typeMigration/ui/TypeMigrationDialog.java | 10 +++-- 6 files changed, 56 insertions(+), 29 deletions(-) diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java index 9ab5ba0289e9..e537629db391 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ChangeTypeSignatureHandler.java @@ -27,9 +27,10 @@ import com.intellij.refactoring.RefactoringActionHandler; import com.intellij.refactoring.RefactoringBundle; import com.intellij.refactoring.typeMigration.ui.TypeMigrationDialog; import com.intellij.refactoring.util.CommonRefactoringUtil; -import com.intellij.util.Function; import org.jetbrains.annotations.NotNull; +import java.util.Arrays; + public class ChangeTypeSignatureHandler implements RefactoringActionHandler { private static final Logger LOG = Logger.getInstance("#" + ChangeTypeSignatureHandler.class.getName()); @@ -42,8 +43,15 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler { PsiTypeElement typeElement = PsiTreeUtil.getParentOfType(element, PsiTypeElement.class); while (typeElement != null) { final PsiElement parent = typeElement.getParent(); - if (parent instanceof PsiVariable || (parent instanceof PsiMember && !(parent instanceof PsiClass)) || isClassArgument(parent)) { - invoke(project, parent, null, null, editor); + PsiElement[] toMigrate = null; + if (parent instanceof PsiVariable) { + toMigrate = extractReferencedVariables(typeElement); + } + else if ((parent instanceof PsiMember && !(parent instanceof PsiClass)) || isClassArgument(parent)) { + toMigrate = new PsiElement[]{parent}; + } + if (toMigrate != null && toMigrate.length > 0) { + invoke(project, toMigrate, null, null, editor); return; } typeElement = PsiTreeUtil.getParentOfType(parent, PsiTypeElement.class, false); @@ -61,12 +69,11 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler { } public static boolean invokeOnElement(final Project project, final PsiElement element) { - if (element instanceof PsiVariable || (element instanceof PsiMember && !(element instanceof PsiClass)) || element instanceof PsiFile) { - invoke(project, element, null, null, null); - return true; - } - if (isClassArgument(element)) { - invoke(project, element, null, null, null); + if (element instanceof PsiVariable || + (element instanceof PsiMember && !(element instanceof PsiClass)) || + element instanceof PsiFile || + isClassArgument(element)) { + invoke(project, new PsiElement[] {element}, null, null, null); return true; } return false; @@ -88,9 +95,9 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler { return false; } - public static void invoke(final Project project, final PsiElement root, final PsiType type, final TypeMigrationRules rules, final Editor editor) { - if (Util.canBeMigrated(root)) { - TypeMigrationDialog dialog = new TypeMigrationDialog.SingleElement(project, root, type, rules); + public static void invoke(final Project project, final PsiElement[] roots, final PsiType type, final TypeMigrationRules rules, final Editor editor) { + if (Util.canBeMigrated(roots)) { + TypeMigrationDialog dialog = new TypeMigrationDialog.SingleElement(project, roots, type, rules); dialog.show(); return; } @@ -99,4 +106,14 @@ public class ChangeTypeSignatureHandler implements RefactoringActionHandler { RefactoringBundle.message("unable.to.start.type.migration"), null); } + + @NotNull + private static PsiElement[] extractReferencedVariables(PsiTypeElement typeElement) { + final PsiDeclarationStatement declaration = PsiTreeUtil.getParentOfType(typeElement, PsiDeclarationStatement.class); + if (declaration == null) return PsiElement.EMPTY_ARRAY; + return Arrays.stream(declaration.getDeclaredElements()) + .filter(PsiVariable.class::isInstance) + .filter(e -> ((PsiVariable)e).getTypeElement() == typeElement) + .toArray(PsiElement[]::new); + } } \ No newline at end of file diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java index f93cfcb0e6bc..fa1d972a4990 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationLabeler.java @@ -304,7 +304,9 @@ public class TypeMigrationLabeler { myRemainConversions = conversions; } - public void change(final TypeMigrationUsageInfo usageInfo, @NotNull Consumer consumer) { + public void change(@NotNull final TypeMigrationUsageInfo usageInfo, + @NotNull Consumer consumer, + @NotNull TypeMigrationLabeler labeler) { final PsiElement element = usageInfo.getElement(); if (element == null) return; final Project project = element.getProject(); @@ -341,7 +343,7 @@ public class TypeMigrationLabeler { } } else { - TypeMigrationReplacementUtil.migratePsiMemberType(element, project, getTypeEvaluator().getType(usageInfo)); + TypeMigrationReplacementUtil.migrateMemberOrVariableType(element, project, getTypeEvaluator().getType(usageInfo)); if (usageInfo instanceof OverridenUsageInfo) { final String migrationName = ((OverridenUsageInfo)usageInfo).getMigrateMethodName(); if (migrationName != null) { diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java index ab6fd927c2e6..b5024b56862f 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationProcessor.java @@ -248,7 +248,7 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor { final TypeMigrationLabeler.MigrationProducer producer = labeler.createMigratorFor(usages); final SmartPointerManager smartPointerManager = SmartPointerManager.getInstance(project); - List nonCodeUsages = new ArrayList(); + List nonCodeUsages = new ArrayList<>(); for (UsageInfo usage : usages) { if (((TypeMigrationUsageInfo)usage).isExcluded()) continue; final PsiElement element = usage.getElement(); @@ -256,12 +256,9 @@ public class TypeMigrationProcessor extends BaseRefactoringProcessor { element instanceof PsiMember || element instanceof PsiExpression || element instanceof PsiReferenceParameterList) { - producer.change((TypeMigrationUsageInfo)usage, new Consumer() { - @Override - public void consume(@NotNull PsiNewExpression expression) { - newExpressionsToCheckDiamonds.add(smartPointerManager.createSmartPsiElementPointer(expression)); - } - }); + producer.change((TypeMigrationUsageInfo)usage, + expression -> newExpressionsToCheckDiamonds.add(smartPointerManager.createSmartPsiElementPointer(expression)), + labeler); } else { nonCodeUsages.add(usage); diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java index 38f9e82a694c..6dde6d91f021 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/TypeMigrationReplacementUtil.java @@ -114,7 +114,7 @@ public class TypeMigrationReplacementUtil { return expression; } - static void migratePsiMemberType(final PsiElement element, final Project project, PsiType migratedType) { + static void migrateMemberOrVariableType(final PsiElement element, final Project project, PsiType migratedType) { try { if (!migratedType.isValid()) { migratedType = JavaPsiFacade.getElementFactory(project).createTypeByFQClassName(migratedType.getCanonicalText()); diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java index b779fb6e5645..9bfdcc18fd47 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/Util.java @@ -19,6 +19,7 @@ import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.SmartList; import com.intellij.util.containers.Queue; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; @@ -91,7 +92,16 @@ public class Util { return element; } - public static boolean canBeMigrated(final PsiElement e) { + public static boolean canBeMigrated(@NotNull final PsiElement[] es) { + for (PsiElement e : es) { + if (!canBeMigrated(e)) { + return false; + } + } + return true; + } + + private static boolean canBeMigrated(@Nullable final PsiElement e) { if (e == null) { return false; } @@ -116,8 +126,7 @@ public class Util { return aClass != null; } else if (elementType instanceof PsiDisjunctionType) { - final PsiType lub = ((PsiDisjunctionType)elementType).getLeastUpperBound(); - return lub != null; + return true; } } diff --git a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java index 6403df79e7e4..9f4eb9bf4d99 100644 --- a/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java +++ b/java/java-impl/src/com/intellij/refactoring/typeMigration/ui/TypeMigrationDialog.java @@ -59,7 +59,7 @@ import java.util.List; * Date: 25-Mar-2008 */ public abstract class TypeMigrationDialog extends RefactoringDialog { - private static final Logger LOG = Logger.getInstance("#com.intellij.refactoring.typeMigration.ui.TypeMigrationDialog"); + private static final Logger LOG = Logger.getInstance(TypeMigrationDialog.class); public static final String REFACTORING_NAME = "Type Migration"; @@ -68,7 +68,7 @@ public abstract class TypeMigrationDialog extends RefactoringDialog { private final ScopeChooserCombo myScopeChooserCombo; public TypeMigrationDialog(@NotNull Project project, - PsiElement roots[], + PsiElement[] roots, TypeMigrationRules rules) { super(project, false); myRoots = roots; @@ -150,14 +150,16 @@ public abstract class TypeMigrationDialog extends RefactoringDialog { private final EditorComboBox myToTypeEditor; public SingleElement(@NotNull Project project, - PsiElement root, + PsiElement[] roots, PsiType migrationType, TypeMigrationRules rules) { - super(project, new PsiElement[]{root}, rules); + super(project, roots, rules); + LOG.assertTrue(roots.length > 0); final PsiType rootType = getRootType(); final String text = migrationType != null ? migrationType.getCanonicalText(true) : rootType != null ? rootType.getCanonicalText(true) : ""; int flags = 0; + PsiElement root = roots[0]; if (root instanceof PsiParameter) { final PsiElement scope = ((PsiParameter)root).getDeclarationScope(); if (scope instanceof PsiMethod) {