extract method type suggestions: suggest more accurate type if casts found (IDEA-56427)

This commit is contained in:
anna
2010-07-14 10:57:05 +04:00
parent 94d548b63c
commit fa25a0d53f
5 changed files with 102 additions and 0 deletions
@@ -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<ParameterTablePanel.VariableData> myInputVariables;
@@ -86,6 +91,33 @@ public class InputVariables {
if (type instanceof PsiEllipsisType) {
type = ((PsiEllipsisType)type).toArrayType();
}
final Map<PsiCodeBlock, PsiType> casts = new HashMap<PsiCodeBlock, PsiType>();
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<ParameterTablePanel.VariableData> getInputVariables() {
return myInputVariables;
}
@@ -0,0 +1,7 @@
class Test {
void foo(Object o) {
<selection>((A)o).doSmth();</selection>
}
}
class A {void doSmth(){}}
@@ -0,0 +1,14 @@
class Test {
void foo(Object o) {
<selection>
if (true) {
((A1)o).doSmth();
} else {
o.toString();
}
</selection>
}
}
class A {void doSmth(){}}
class A1 extends A {}
@@ -0,0 +1,15 @@
class Test {
void foo(Object o) {
<selection>
if (true) {
((A1)o).doSmth();
} else {
((A2)o).doSmth();
}
</selection>
}
}
class A {void doSmth(){}}
class A1 extends A {}
class A2 extends A {}
@@ -75,6 +75,18 @@ public class SuggestedParamTypesTest extends LightCodeInsightTestCase {
doTest("String", "Object", "Serializable", "Comparable<String>", "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");