From fa25a0d53f532a6018d90b9644faa7b855fbf7cb Mon Sep 17 00:00:00 2001 From: anna Date: Mon, 12 Jul 2010 20:26:34 +0400 Subject: [PATCH] extract method type suggestions: suggest more accurate type if casts found (IDEA-56427) --- .../extractMethod/InputVariables.java | 54 +++++++++++++++++++ .../suggestedTypes/CastInside.java | 7 +++ .../suggestedTypes/CastNoCast.java | 14 +++++ .../suggestedTypes/MultipleCasts.java | 15 ++++++ .../refactoring/SuggestedParamTypesTest.java | 12 +++++ 5 files changed, 102 insertions(+) create mode 100644 java/java-tests/testData/refactoring/suggestedTypes/CastInside.java create mode 100644 java/java-tests/testData/refactoring/suggestedTypes/CastNoCast.java create mode 100644 java/java-tests/testData/refactoring/suggestedTypes/MultipleCasts.java diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/InputVariables.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/InputVariables.java index 655eba6ec29e..f4f0af847677 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/InputVariables.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/InputVariables.java @@ -29,11 +29,16 @@ import com.intellij.psi.controlFlow.ControlFlow; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.TypeConversionUtil; import com.intellij.refactoring.util.ParameterTablePanel; import com.intellij.refactoring.util.duplicates.DuplicatesFinder; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.*; +import org.jetbrains.annotations.Nullable; import java.util.*; +import java.util.HashMap; +import java.util.HashSet; public class InputVariables { private final List myInputVariables; @@ -86,6 +91,33 @@ public class InputVariables { if (type instanceof PsiEllipsisType) { type = ((PsiEllipsisType)type).toArrayType(); } + final Map casts = new HashMap(); + for (PsiReference reference : ReferencesSearch.search(var, myScope)) { + final PsiElement element = reference.getElement(); + final PsiElement parent = element.getParent(); + final PsiCodeBlock block = PsiTreeUtil.getParentOfType(parent, PsiCodeBlock.class); + if (parent instanceof PsiTypeCastExpression) { + final PsiType currentType = casts.get(block); + final PsiType castType = ((PsiTypeCastExpression)parent).getType(); + casts.put(block, getBroaderType(currentType, castType)); + } else if (!(parent instanceof PsiInstanceOfExpression)){ + if (!casts.containsKey(block)) { + casts.put(block, null); + } + } + } + if (!casts.containsValue(null)) { + PsiType currentType = null; + for (PsiType psiType : casts.values()) { + currentType = getBroaderType(currentType, psiType); + if (currentType == null) { + break; + } + } + if (currentType != null) { + type = currentType; + } + } ParameterTablePanel.VariableData data = new ParameterTablePanel.VariableData(var, type); data.name = name; @@ -111,6 +143,28 @@ public class InputVariables { return inputData; } + @Nullable + private static PsiType getBroaderType(PsiType currentType, PsiType castType) { + if (currentType != null) { + if (castType != null) { + if (TypeConversionUtil.isAssignable(castType, currentType)) { + return castType; + } else if (!TypeConversionUtil.isAssignable(currentType, castType)) { + for (PsiType superType : castType.getSuperTypes()) { + if (TypeConversionUtil.isAssignable(superType, currentType)) { + return superType; + } + } + return null; + } + } + } + else { + return castType; + } + return currentType; + } + public List getInputVariables() { return myInputVariables; } diff --git a/java/java-tests/testData/refactoring/suggestedTypes/CastInside.java b/java/java-tests/testData/refactoring/suggestedTypes/CastInside.java new file mode 100644 index 000000000000..967fe3c7af78 --- /dev/null +++ b/java/java-tests/testData/refactoring/suggestedTypes/CastInside.java @@ -0,0 +1,7 @@ +class Test { + void foo(Object o) { + ((A)o).doSmth(); + } +} + +class A {void doSmth(){}} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/suggestedTypes/CastNoCast.java b/java/java-tests/testData/refactoring/suggestedTypes/CastNoCast.java new file mode 100644 index 000000000000..7e0fc0e58173 --- /dev/null +++ b/java/java-tests/testData/refactoring/suggestedTypes/CastNoCast.java @@ -0,0 +1,14 @@ +class Test { + void foo(Object o) { + + if (true) { + ((A1)o).doSmth(); + } else { + o.toString(); + } + + } +} + +class A {void doSmth(){}} +class A1 extends A {} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/suggestedTypes/MultipleCasts.java b/java/java-tests/testData/refactoring/suggestedTypes/MultipleCasts.java new file mode 100644 index 000000000000..91aeb8a8d41b --- /dev/null +++ b/java/java-tests/testData/refactoring/suggestedTypes/MultipleCasts.java @@ -0,0 +1,15 @@ +class Test { + void foo(Object o) { + + if (true) { + ((A1)o).doSmth(); + } else { + ((A2)o).doSmth(); + } + + } +} + +class A {void doSmth(){}} +class A1 extends A {} +class A2 extends A {} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/SuggestedParamTypesTest.java b/java/java-tests/testSrc/com/intellij/refactoring/SuggestedParamTypesTest.java index 881ca1b180e3..c8101c7f362d 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/SuggestedParamTypesTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/SuggestedParamTypesTest.java @@ -75,6 +75,18 @@ public class SuggestedParamTypesTest extends LightCodeInsightTestCase { doTest("String", "Object", "Serializable", "Comparable", "CharSequence"); } + public void testCastInside() throws Exception { + doTest("A", "Object"); + } + + public void testMultipleCasts() throws Exception { + doTest("A", "Object"); + } + + public void testCastNoCast() throws Exception { + doTest("Object"); + } + private void doTest(String... types) throws Exception { configureByFile(BASE_PATH + getTestName(false) + ".java");