From a19f41e6c6523b592630c1965d304878c1a5a8ca Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 16 Dec 2015 17:57:41 +0100 Subject: [PATCH] extract: collect classes to search for available methods from intersections/captures, etc (IDEA-57404) --- .../ui/TypeSelectorManagerImpl.java | 16 +++++++++++++++- .../refactoring/util/RefactoringUtil.java | 13 +++++++------ ...onConjunctBasedOnFollowingCalls.after.java | 19 +++++++++++++++++++ ...rsectionConjunctBasedOnFollowingCalls.java | 18 ++++++++++++++++++ .../refactoring/IntroduceVariableTest.java | 6 +++++- 5 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.after.java create mode 100644 java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.java diff --git a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java index b97e98789ede..b308a4cdf929 100644 --- a/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java +++ b/java/java-impl/src/com/intellij/refactoring/ui/TypeSelectorManagerImpl.java @@ -154,12 +154,26 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager { final Set occurrenceClasses = new HashSet(); for (final PsiExpression occurrence : myOccurrences) { final PsiType occurrenceType = occurrence.getType(); + collectOccurrenceClasses(occurrenceClasses, occurrenceType); + } + return new ExpectedTypeUtil.ExpectedClassesFromSetProvider(occurrenceClasses); + } + + private static void collectOccurrenceClasses(Set occurrenceClasses, PsiType occurrenceType) { + if (occurrenceType instanceof PsiIntersectionType) { + for (PsiType type : ((PsiIntersectionType)occurrenceType).getConjuncts()) { + collectOccurrenceClasses(occurrenceClasses, type); + } + } + else if (occurrenceType instanceof PsiCapturedWildcardType) { + collectOccurrenceClasses(occurrenceClasses, ((PsiCapturedWildcardType)occurrenceType).getUpperBound()); + } + else { final PsiClass aClass = PsiUtil.resolveClassInType(occurrenceType); if (aClass != null) { occurrenceClasses.add(aClass); } } - return new ExpectedTypeUtil.ExpectedClassesFromSetProvider(occurrenceClasses); } private PsiType[] getTypesForMain() { diff --git a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java index 4912bdd76769..26aae675623d 100644 --- a/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java +++ b/java/java-impl/src/com/intellij/refactoring/util/RefactoringUtil.java @@ -46,10 +46,7 @@ import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.SearchScope; import com.intellij.psi.search.searches.ReferencesSearch; import com.intellij.psi.tree.IElementType; -import com.intellij.psi.util.InheritanceUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.psi.util.PsiUtil; -import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.psi.util.*; import com.intellij.refactoring.PackageWrapper; import com.intellij.refactoring.introduceField.ElementToWorkOn; import com.intellij.refactoring.introduceVariable.IntroduceVariableBase; @@ -389,14 +386,18 @@ public class RefactoringUtil { PsiElementFactory factory = JavaPsiFacade.getInstance(expr.getProject()).getElementFactory(); PsiType type = getTypeByExpression(expr, factory); final boolean isFunctionalType = type instanceof PsiLambdaExpressionType || type instanceof PsiMethodReferenceType || type instanceof PsiLambdaParameterType; - if (type != null && !isFunctionalType) { + final boolean isDenotable = PsiTypesUtil.isDenotableType(expr.getType()); + if (type != null && !isFunctionalType && isDenotable) { return type; } ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getInstance(expr.getProject()).getExpectedTypes(expr, false); - if (expectedTypes.length == 1 || isFunctionalType && expectedTypes.length > 0) { + if (expectedTypes.length == 1 || (isFunctionalType || !isDenotable)&& expectedTypes.length > 0 ) { type = expectedTypes[0].getType(); if (!type.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) return type; } + if (!isDenotable) { + return type; + } return null; } diff --git a/java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.after.java b/java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.after.java new file mode 100644 index 000000000000..1163b038b1ca --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.after.java @@ -0,0 +1,19 @@ + +interface IA { + void a(); +} + +interface IB { + void b(); +} + +interface IC{ + T c(); +} + +class K { + void foo(IC x){ + IA m = x.c(); + m.a(); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.java b/java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.java new file mode 100644 index 000000000000..e89dba1958a4 --- /dev/null +++ b/java/java-tests/testData/refactoring/introduceVariable/ChooseIntersectionConjunctBasedOnFollowingCalls.java @@ -0,0 +1,18 @@ + +interface IA { + void a(); +} + +interface IB { + void b(); +} + +interface IC{ + T c(); +} + +class K { + void foo(IC x){ + x.c().a(); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java index d74120994221..ae1fb74ff029 100644 --- a/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java +++ b/java/java-tests/testSrc/com/intellij/refactoring/IntroduceVariableTest.java @@ -539,7 +539,11 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase { } }); } - + + public void testChooseIntersectionConjunctBasedOnFollowingCalls() throws Exception { + doTest(new MockIntroduceVariableHandler("m", false, false, false, "IA")); + } + private void doTest(IntroduceVariableBase testMe) { String baseName = "/refactoring/introduceVariable/" + getTestName(false); configureByFile(baseName + ".java");