mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
More fair handle of PsiDisjunctionType; introduce variable for multi-catch types
This commit is contained in:
+45
-13
@@ -13,10 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @author max
|
||||
*/
|
||||
package com.intellij.psi.impl.smartPointers;
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
@@ -26,20 +22,28 @@ import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import com.intellij.psi.impl.source.PsiImmediateClassType;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.NullableFunction;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.containers.HashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.smartPointers.SmartTypePointerManagerImpl");
|
||||
|
||||
private final SmartPointerManager myPsiPointerManager;
|
||||
private final Project myProject;
|
||||
|
||||
public SmartTypePointerManagerImpl(SmartPointerManager psiPointerManager, final Project project) {
|
||||
public SmartTypePointerManagerImpl(final SmartPointerManager psiPointerManager, final Project project) {
|
||||
myPsiPointerManager = psiPointerManager;
|
||||
myProject = project;
|
||||
}
|
||||
@@ -102,26 +106,24 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
|
||||
return PsiWildcardType.createUnbounded(myManager);
|
||||
}
|
||||
else {
|
||||
final PsiType type = myBoundPointer.getType();
|
||||
assert type != null : myBoundPointer;
|
||||
if (myIsExtending) {
|
||||
return PsiWildcardType.createExtends(myManager, myBoundPointer.getType());
|
||||
return PsiWildcardType.createExtends(myManager, type);
|
||||
}
|
||||
else {
|
||||
return PsiWildcardType.createSuper(myManager, myBoundPointer.getType());
|
||||
return PsiWildcardType.createSuper(myManager, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ClassTypePointer implements SmartTypePointer {
|
||||
private PsiType myType;
|
||||
private final SmartPsiElementPointer myClass;
|
||||
private final Map<SmartPsiElementPointer, SmartTypePointer> myMap;
|
||||
|
||||
|
||||
public ClassTypePointer(PsiType type,
|
||||
SmartPsiElementPointer aClass,
|
||||
Map<SmartPsiElementPointer, SmartTypePointer> map) {
|
||||
public ClassTypePointer(PsiType type, SmartPsiElementPointer aClass, Map<SmartPsiElementPointer, SmartTypePointer> map) {
|
||||
myType = type;
|
||||
myClass = aClass;
|
||||
myMap = map;
|
||||
@@ -182,15 +184,40 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
|
||||
}
|
||||
}
|
||||
|
||||
private class DisjunctionTypePointer implements SmartTypePointer {
|
||||
private PsiType myType;
|
||||
private final List<SmartTypePointer> myPointers;
|
||||
|
||||
private DisjunctionTypePointer(final PsiDisjunctionType type) {
|
||||
myType = type;
|
||||
myPointers = ContainerUtil.map(type.getDisjunctions(), new Function<PsiType, SmartTypePointer>() {
|
||||
@Override public SmartTypePointer fun(PsiType psiType) { return createSmartTypePointer(psiType); }
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType getType() {
|
||||
if (myType.isValid()) return myType;
|
||||
|
||||
final List<PsiType> types = ContainerUtil.map(myPointers, new NullableFunction<SmartTypePointer, PsiType>() {
|
||||
@Override public PsiType fun(SmartTypePointer typePointer) { return typePointer.getType(); }
|
||||
});
|
||||
return new PsiDisjunctionType(types, PsiManager.getInstance(myProject));
|
||||
}
|
||||
}
|
||||
|
||||
private class SmartTypeCreatingVisitor extends PsiTypeVisitor<SmartTypePointer> {
|
||||
@Override
|
||||
public SmartTypePointer visitPrimitiveType(PsiPrimitiveType primitiveType) {
|
||||
return new SimpleTypePointer(primitiveType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartTypePointer visitArrayType(PsiArrayType arrayType) {
|
||||
return new ArrayTypePointer(arrayType, arrayType.getComponentType().accept(this));
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartTypePointer visitWildcardType(PsiWildcardType wildcardType) {
|
||||
final PsiType bound = wildcardType.getBound();
|
||||
final SmartTypePointer boundPointer;
|
||||
@@ -203,6 +230,7 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
|
||||
return new WildcardTypePointer(wildcardType, boundPointer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartTypePointer visitClassType(PsiClassType classType) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = classType.resolveGenerics();
|
||||
final PsiClass aClass = resolveResult.getElement();
|
||||
@@ -226,6 +254,10 @@ public class SmartTypePointerManagerImpl extends SmartTypePointerManager {
|
||||
}
|
||||
return new ClassTypePointer(classType, myPsiPointerManager.createSmartPsiElementPointer(aClass), map);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SmartTypePointer visitDisjunctionType(PsiDisjunctionType disjunctionType) {
|
||||
return new DisjunctionTypePointer(disjunctionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,7 @@ import com.intellij.util.Function;
|
||||
import com.intellij.util.IncorrectOperationException;
|
||||
import com.intellij.util.PatchedSoftReference;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -102,7 +103,12 @@ public class PsiTypeElementImpl extends CompositePsiElement implements PsiTypeEl
|
||||
cachedType = componentType.createArrayType();
|
||||
}
|
||||
else {
|
||||
cachedType = new PsiDisjunctionType(this);
|
||||
final List<PsiTypeElement> typeElements = PsiTreeUtil.getChildrenOfTypeAsList(this, PsiTypeElement.class);
|
||||
if (typeElements.size() < 2) LOG.error("Incorrect nested type: " + this);
|
||||
final List<PsiType> types = ContainerUtil.map(typeElements, new Function<PsiTypeElement, PsiType>() {
|
||||
@Override public PsiType fun(final PsiTypeElement psiTypeElement) { return psiTypeElement.getType(); }
|
||||
});
|
||||
cachedType = new PsiDisjunctionType(types, getManager());
|
||||
}
|
||||
}
|
||||
else if (elementType == JavaElementType.JAVA_CODE_REFERENCE) {
|
||||
|
||||
@@ -180,15 +180,18 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
|
||||
return createType(original.getProject(), originalText, null, generated);
|
||||
}
|
||||
if (type instanceof PsiIntersectionType) {
|
||||
PsiIntersectionType intersectionType = (PsiIntersectionType)type;
|
||||
LightTypeElement te = new LightTypeElement(original.getManager(), intersectionType.getConjuncts()[0]);
|
||||
LightTypeElement te = new LightTypeElement(original.getManager(), ((PsiIntersectionType)type).getRepresentative());
|
||||
return ChangeUtil.generateTreeElement(te, table, manager);
|
||||
}
|
||||
if (type instanceof PsiDisjunctionType) {
|
||||
LightTypeElement te = new LightTypeElement(original.getManager(), ((PsiDisjunctionType)type).getLeastUpperBound());
|
||||
return ChangeUtil.generateTreeElement(te, table, manager);
|
||||
}
|
||||
PsiClassType classType = (PsiClassType)type;
|
||||
|
||||
String text = classType.getPresentableText();
|
||||
final TreeElement element = createType(original.getProject(), text, original, false);
|
||||
PsiTypeElementImpl result = (PsiTypeElementImpl)SourceTreeToPsiMap.treeElementToPsi(element);
|
||||
PsiTypeElementImpl result = SourceTreeToPsiMap.treeToPsiNotNull(element);
|
||||
|
||||
CodeEditUtil.setNodeGenerated(result, generated);
|
||||
if (generated) {
|
||||
@@ -397,7 +400,7 @@ public class JavaChangeUtilSupport implements TreeGenerator, TreeCopyHandler {
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_NAME_KIND:
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_OR_PACKAGE_NAME_KIND:
|
||||
case PsiJavaCodeReferenceElementImpl.CLASS_IN_QUALIFIED_NEW_KIND:
|
||||
final PsiElement target = ((PsiJavaCodeReferenceElement)SourceTreeToPsiMap.treeElementToPsi(original)).resolve();
|
||||
final PsiElement target = SourceTreeToPsiMap.<PsiJavaCodeReferenceElement>treeToPsiNotNull(original).resolve();
|
||||
if (target instanceof PsiClass) {
|
||||
ref.putCopyableUserData(REFERENCED_CLASS_KEY, (PsiClass)target);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,6 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
private final PsiElementFactory myFactory;
|
||||
private final SmartTypePointerManager mySmartTypePointerManager;
|
||||
private ExpectedTypesProvider.ExpectedClassProvider myOccurrenceClassProvider;
|
||||
private ExpectedTypesProvider myExpectedTypesProvider;
|
||||
|
||||
public TypeSelectorManagerImpl(Project project, PsiType type, PsiExpression mainOccurrence, PsiExpression[] occurrences) {
|
||||
this(project, type, null, mainOccurrence, occurrences);
|
||||
@@ -65,12 +64,12 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
setDefaultType(type);
|
||||
myMainOccurrence = null;
|
||||
myOccurrences = occurrences;
|
||||
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
|
||||
|
||||
myOccurrenceClassProvider = createOccurrenceClassProvider();
|
||||
myTypesForAll = getTypesForAll(areTypesDirected);
|
||||
myTypesForMain = PsiType.EMPTY_ARRAY;
|
||||
myIsOneSuggestion = myTypesForAll.length == 1;
|
||||
|
||||
myIsOneSuggestion = myTypesForAll.length == 1;
|
||||
if (myIsOneSuggestion) {
|
||||
myTypeSelector = new TypeSelector(myTypesForAll[0]);
|
||||
}
|
||||
@@ -90,7 +89,6 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
setDefaultType(type);
|
||||
myMainOccurrence = mainOccurrence;
|
||||
myOccurrences = occurrences;
|
||||
myExpectedTypesProvider = ExpectedTypesProvider.getInstance(project);
|
||||
|
||||
myOccurrenceClassProvider = createOccurrenceClassProvider();
|
||||
myTypesForMain = getTypesForMain();
|
||||
@@ -149,8 +147,8 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
|
||||
private ExpectedTypesProvider.ExpectedClassProvider createOccurrenceClassProvider() {
|
||||
final Set<PsiClass> occurrenceClasses = new HashSet<PsiClass>();
|
||||
for (final PsiExpression occurence : myOccurrences) {
|
||||
final PsiType occurrenceType = occurence.getType();
|
||||
for (final PsiExpression occurrence : myOccurrences) {
|
||||
final PsiType occurrenceType = occurrence.getType();
|
||||
final PsiClass aClass = PsiUtil.resolveClassInType(occurrenceType);
|
||||
if (aClass != null) {
|
||||
occurrenceClasses.add(aClass);
|
||||
@@ -160,8 +158,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
}
|
||||
|
||||
private PsiType[] getTypesForMain() {
|
||||
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(myMainOccurrence, false, myOccurrenceClassProvider,
|
||||
false);
|
||||
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(myMainOccurrence, false, myOccurrenceClassProvider, false);
|
||||
final ArrayList<PsiType> allowedTypes = new ArrayList<PsiType>();
|
||||
RefactoringHierarchyUtil.processSuperTypes(getDefaultType(), new RefactoringHierarchyUtil.SuperTypeVisitor() {
|
||||
public void visitType(PsiType aType) {
|
||||
@@ -173,9 +170,8 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
}
|
||||
|
||||
private void checkIfAllowed(PsiType type) {
|
||||
if (expectedTypes != null && expectedTypes.length > 0) {
|
||||
final ExpectedTypeInfo
|
||||
typeInfo = ExpectedTypesProvider.createInfo(type, ExpectedTypeInfo.TYPE_STRICTLY, type, TailType.NONE);
|
||||
if (expectedTypes.length > 0) {
|
||||
final ExpectedTypeInfo typeInfo = ExpectedTypesProvider.createInfo(type, ExpectedTypeInfo.TYPE_STRICTLY, type, TailType.NONE);
|
||||
for (ExpectedTypeInfo expectedType : expectedTypes) {
|
||||
if (expectedType.intersect(typeInfo).length != 0) {
|
||||
allowedTypes.add(type);
|
||||
@@ -196,9 +192,7 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
private PsiType[] getTypesForAll(final boolean areTypesDirected) {
|
||||
final ArrayList<ExpectedTypeInfo[]> expectedTypesFromAll = new ArrayList<ExpectedTypeInfo[]>();
|
||||
for (PsiExpression occurrence : myOccurrences) {
|
||||
|
||||
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(occurrence, false, myOccurrenceClassProvider,
|
||||
isUsedAfter());
|
||||
final ExpectedTypeInfo[] expectedTypes = ExpectedTypesProvider.getExpectedTypes(occurrence, false, myOccurrenceClassProvider, isUsedAfter());
|
||||
if (expectedTypes.length > 0) {
|
||||
expectedTypesFromAll.add(expectedTypes);
|
||||
}
|
||||
@@ -266,13 +260,15 @@ public class TypeSelectorManagerImpl implements TypeSelectorManager {
|
||||
result.add(0, boxedType);
|
||||
}
|
||||
}
|
||||
result.add(0, defaultType);
|
||||
if (!TypeConversionUtil.isComposite(defaultType)) {
|
||||
result.add(0, defaultType);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void setAllOccurences(boolean allOccurences) {
|
||||
public void setAllOccurences(boolean occurrences) {
|
||||
if (myIsOneSuggestion) return;
|
||||
setTypesAndPreselect(allOccurences ? myTypesForAll : myTypesForMain);
|
||||
setTypesAndPreselect(occurrences ? myTypesForAll : myTypesForMain);
|
||||
}
|
||||
|
||||
private void setTypesAndPreselect(PsiType[] types) {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
static class E1 extends Exception { }
|
||||
static class E2 extends Exception { }
|
||||
|
||||
void m() {
|
||||
try { }
|
||||
catch (E1 | E2 ex) {
|
||||
final Exception e = ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class C {
|
||||
static class E1 extends Exception { }
|
||||
static class E2 extends Exception { }
|
||||
|
||||
void m() {
|
||||
try { }
|
||||
catch (E1 | E2 ex) {
|
||||
<caret>ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
interface B<T> { }
|
||||
static class E1 extends Exception implements B<Integer> { }
|
||||
static class E2 extends Exception implements B<Long> { }
|
||||
|
||||
void m() {
|
||||
try { }
|
||||
catch (E1 | E2 ex) {
|
||||
final B<? extends Number> b = ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
interface B<T> { }
|
||||
static class E1 extends Exception implements B<Integer> { }
|
||||
static class E2 extends Exception implements B<Long> { }
|
||||
|
||||
void m() {
|
||||
try { }
|
||||
catch (E1 | E2 ex) {
|
||||
<caret>ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ package com.intellij.refactoring;
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiExpression;
|
||||
import com.intellij.psi.PsiType;
|
||||
@@ -250,6 +248,14 @@ public class IntroduceVariableTest extends LightCodeInsightTestCase {
|
||||
});
|
||||
}
|
||||
|
||||
public void testMultiCatchSimple() throws Exception {
|
||||
doTest(new MockIntroduceVariableHandler("e", true, true, false, "C.E1 | C.E2"));
|
||||
}
|
||||
|
||||
public void testMultiCatchTyped() throws Exception {
|
||||
doTest(new MockIntroduceVariableHandler("b", true, true, false, "C.E1 | C.E2"));
|
||||
}
|
||||
|
||||
private void doTest(IntroduceVariableBase testMe) throws Exception {
|
||||
@NonNls String baseName = "/refactoring/introduceVariable/" + getTestName(false);
|
||||
configureByFile(baseName + ".java");
|
||||
|
||||
@@ -18,39 +18,38 @@ package com.intellij.psi;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.*;
|
||||
import com.intellij.psi.util.CachedValue;
|
||||
import com.intellij.psi.util.CachedValueProvider;
|
||||
import com.intellij.psi.util.CachedValuesManager;
|
||||
import com.intellij.psi.util.PsiModificationTracker;
|
||||
import com.intellij.util.Function;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Composite type resulting from Project Coin's multi-catch statements, * i.e. <code>FileNotFoundException | EOFException</code>.
|
||||
* In most cases should be threatened via its least upper bound * (<code>IOException</code> in the example above).
|
||||
*/
|
||||
public class PsiDisjunctionType extends PsiType {
|
||||
private final PsiTypeElement myTypeElement;
|
||||
private final PsiManager myManager;
|
||||
private final List<PsiType> myTypes;
|
||||
private final CachedValue<PsiType> myLubCache;
|
||||
|
||||
public PsiDisjunctionType(final PsiTypeElement typeElement) {
|
||||
public PsiDisjunctionType(final List<PsiType> types, final PsiManager psiManager) {
|
||||
super(PsiAnnotation.EMPTY_ARRAY);
|
||||
|
||||
myTypeElement = typeElement;
|
||||
myManager = psiManager;
|
||||
myTypes = Collections.unmodifiableList(types);
|
||||
|
||||
final List<PsiTypeElement> typeElements = PsiTreeUtil.getChildrenOfTypeAsList(myTypeElement, PsiTypeElement.class);
|
||||
myTypes = Collections.unmodifiableList(ContainerUtil.map(typeElements, new Function<PsiTypeElement, PsiType>() {
|
||||
@Override
|
||||
public PsiType fun(final PsiTypeElement psiTypeElement) {
|
||||
return psiTypeElement.getType();
|
||||
}
|
||||
}));
|
||||
|
||||
final CachedValuesManager cacheManager = CachedValuesManager.getManager(myTypeElement.getProject());
|
||||
final CachedValuesManager cacheManager = CachedValuesManager.getManager(psiManager.getProject());
|
||||
myLubCache = cacheManager.createCachedValue(new CachedValueProvider<PsiType>() {
|
||||
public Result<PsiType> compute() {
|
||||
PsiType lub = myTypes.get(0);
|
||||
for (int i = 1; i < myTypes.size(); i++) {
|
||||
lub = GenericsUtil.getLeastUpperBound(lub, myTypes.get(i), myTypeElement.getManager());
|
||||
lub = GenericsUtil.getLeastUpperBound(lub, myTypes.get(i), psiManager);
|
||||
}
|
||||
return Result.create(lub, PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
|
||||
}
|
||||
@@ -65,6 +64,10 @@ public class PsiDisjunctionType extends PsiType {
|
||||
return myTypes;
|
||||
}
|
||||
|
||||
public PsiManager getManager() {
|
||||
return myManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPresentableText() {
|
||||
return StringUtil.join(myTypes, new Function<PsiType, String>() {
|
||||
@@ -101,11 +104,7 @@ public class PsiDisjunctionType extends PsiType {
|
||||
|
||||
@Override
|
||||
public <A> A accept(final PsiTypeVisitor<A> visitor) {
|
||||
final PsiType lub = getLeastUpperBound();
|
||||
if (lub instanceof PsiClassType) {
|
||||
return visitor.visitClassType((PsiClassType)lub);
|
||||
}
|
||||
return visitor.visitType(lub);
|
||||
return visitor.visitDisjunctionType(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -48,4 +48,8 @@ public class PsiTypeVisitor<A> {
|
||||
public A visitEllipsisType(PsiEllipsisType ellipsisType) {
|
||||
return visitArrayType(ellipsisType);
|
||||
}
|
||||
|
||||
public A visitDisjunctionType(PsiDisjunctionType disjunctionType) {
|
||||
return visitType(disjunctionType);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,10 +33,7 @@ import gnu.trove.TObjectIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
public class TypeConversionUtil {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.util.TypeConversionUtil");
|
||||
@@ -75,6 +72,7 @@ public class TypeConversionUtil {
|
||||
TYPE_TO_RANK_MAP.put(PsiType.BOOLEAN, BOOL_RANK);
|
||||
}
|
||||
|
||||
private TypeConversionUtil() { }
|
||||
|
||||
/**
|
||||
* @return true if fromType can be casted to toType
|
||||
@@ -1077,6 +1075,10 @@ public class TypeConversionUtil {
|
||||
return type != null && isPrimitiveWrapper(type.getCanonicalText());
|
||||
}
|
||||
|
||||
public static boolean isComposite(final PsiType type) {
|
||||
return type instanceof PsiDisjunctionType || type instanceof PsiIntersectionType;
|
||||
}
|
||||
|
||||
public static PsiType typeParameterErasure(@NotNull PsiTypeParameter typeParameter) {
|
||||
return typeParameterErasure(typeParameter, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
@@ -1122,9 +1124,10 @@ public class TypeConversionUtil {
|
||||
return erasure(type, PsiSubstitutor.EMPTY);
|
||||
}
|
||||
|
||||
public static PsiType erasure(PsiType type, final PsiSubstitutor beforeSubstitutor) {
|
||||
public static PsiType erasure(final PsiType type, final PsiSubstitutor beforeSubstitutor) {
|
||||
if (type == null) return null;
|
||||
return type.accept(new PsiTypeVisitor<PsiType>() {
|
||||
@Override
|
||||
public PsiType visitClassType(PsiClassType classType) {
|
||||
final PsiClass aClass = classType.resolve();
|
||||
if (aClass instanceof PsiTypeParameter) {
|
||||
@@ -1135,14 +1138,17 @@ public class TypeConversionUtil {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitWildcardType(PsiWildcardType wildcardType) {
|
||||
return wildcardType.getExtendsBound().accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitPrimitiveType(PsiPrimitiveType primitiveType) {
|
||||
return primitiveType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitEllipsisType(PsiEllipsisType ellipsisType) {
|
||||
final PsiType componentType = ellipsisType.getComponentType();
|
||||
final PsiType newComponentType = componentType.accept(this);
|
||||
@@ -1150,12 +1156,23 @@ public class TypeConversionUtil {
|
||||
return new PsiArrayType(newComponentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitArrayType(PsiArrayType arrayType) {
|
||||
final PsiType componentType = arrayType.getComponentType();
|
||||
final PsiType newComponentType = componentType.accept(this);
|
||||
if (newComponentType == componentType) return arrayType;
|
||||
return newComponentType.createArrayType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiType visitDisjunctionType(PsiDisjunctionType disjunctionType) {
|
||||
final List<PsiType> original = disjunctionType.getDisjunctions();
|
||||
final List<PsiType> erased = new ArrayList<PsiType>(original.size());
|
||||
for (PsiType psiType : original) {
|
||||
erased.add(erasure(psiType, beforeSubstitutor));
|
||||
}
|
||||
return new PsiDisjunctionType(erased, disjunctionType.getManager());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1539,6 +1556,5 @@ public class TypeConversionUtil {
|
||||
}
|
||||
|
||||
return new ClassCandidateInfo(clazz, result.getSubstitutor());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user