extract: collect classes to search for available methods from intersections/captures, etc (IDEA-57404)

This commit is contained in:
Anna Kozlova
2015-12-28 10:27:00 +01:00
parent 6fe7ef3c12
commit a19f41e6c6
5 changed files with 64 additions and 8 deletions
@@ -154,12 +154,26 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
final Set<PsiClass> occurrenceClasses = new HashSet<PsiClass>();
for (final PsiExpression occurrence : myOccurrences) {
final PsiType occurrenceType = occurrence.getType();
collectOccurrenceClasses(occurrenceClasses, occurrenceType);
}
return new ExpectedTypeUtil.ExpectedClassesFromSetProvider(occurrenceClasses);
}
private static void collectOccurrenceClasses(Set<PsiClass> 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() {
@@ -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;
}
@@ -0,0 +1,19 @@
interface IA {
void a();
}
interface IB {
void b();
}
interface IC<T extends IA>{
T c();
}
class K {
void foo(IC<? extends IB> x){
IA m = x.c();
m.a();
}
}
@@ -0,0 +1,18 @@
interface IA {
void a();
}
interface IB {
void b();
}
interface IC<T extends IA>{
T c();
}
class K {
void foo(IC<? extends IB> x){
<selection>x.c()</selection>.a();
}
}
@@ -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");