Delete JavaTypeSubstitutorImpl, use PsiSubstitutor in JavaClassImpl
Also delete related tests
This commit is contained in:
-24
@@ -17,7 +17,6 @@
|
||||
package org.jetbrains.kotlin.load.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import kotlin.collections.ArraysKt;
|
||||
import kotlin.jvm.functions.Function1;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -29,9 +28,7 @@ import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.*;
|
||||
|
||||
@@ -169,27 +166,6 @@ public class JavaClassImpl extends JavaClassifierImpl<PsiClass> implements JavaC
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/* package */ JavaTypeImpl<?> createImmediateType(@NotNull Map<JavaTypeParameterImpl, JavaTypeImpl<?>> substitutionMap) {
|
||||
return new JavaClassifierTypeImpl(
|
||||
JavaPsiFacade.getElementFactory(getPsi().getProject()).createType(getPsi(), createPsiSubstitutor(substitutionMap))
|
||||
);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static PsiSubstitutor createPsiSubstitutor(@NotNull Map<JavaTypeParameterImpl, JavaTypeImpl<?>> substitutionMap) {
|
||||
if (substitutionMap.isEmpty()) return PsiSubstitutor.EMPTY;
|
||||
|
||||
Map<PsiTypeParameter, PsiType> result = new HashMap<PsiTypeParameter, PsiType>();
|
||||
for (Map.Entry<JavaTypeParameterImpl, JavaTypeImpl<?>> entry : substitutionMap.entrySet()) {
|
||||
PsiTypeParameter key = entry.getKey().getPsi();
|
||||
JavaTypeImpl<?> value = entry.getValue();
|
||||
result.put(key, value == null ? null : value.getPsi());
|
||||
}
|
||||
|
||||
return PsiSubstitutorImpl.createSubstitutor(result);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiAnnotationOwner getAnnotationOwnerPsi() {
|
||||
|
||||
+14
-27
@@ -22,15 +22,17 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implements JavaClassifierType {
|
||||
private static class ResolutionResult {
|
||||
private final JavaClassifierImpl<?> classifier;
|
||||
private final JavaTypeSubstitutorImpl substitutor;
|
||||
private final PsiSubstitutor substitutor;
|
||||
private final boolean isRaw;
|
||||
|
||||
private ResolutionResult(@Nullable JavaClassifierImpl<?> classifier, @NotNull JavaTypeSubstitutorImpl substitutor, boolean isRaw) {
|
||||
private ResolutionResult(@Nullable JavaClassifierImpl<?> classifier, @NotNull PsiSubstitutor substitutor, boolean isRaw) {
|
||||
this.classifier = classifier;
|
||||
this.substitutor = substitutor;
|
||||
this.isRaw = isRaw;
|
||||
@@ -51,7 +53,7 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaTypeSubstitutorImpl getSubstitutor() {
|
||||
public PsiSubstitutor getSubstitutor() {
|
||||
resolve();
|
||||
return resolutionResult.substitutor;
|
||||
}
|
||||
@@ -62,26 +64,11 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
PsiClass psiClass = result.getElement();
|
||||
PsiSubstitutor substitutor = result.getSubstitutor();
|
||||
resolutionResult = new ResolutionResult(
|
||||
psiClass == null ? null : JavaClassifierImpl.create(psiClass),
|
||||
new JavaTypeSubstitutorImpl(convertSubstitutionMap(substitutor.getSubstitutionMap())),
|
||||
PsiClassType.isRaw(result)
|
||||
psiClass == null ? null : JavaClassifierImpl.create(psiClass), substitutor, PsiClassType.isRaw(result)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Map<JavaTypeParameterImpl, JavaTypeImpl<?>> convertSubstitutionMap(@NotNull Map<PsiTypeParameter, PsiType> psiMap) {
|
||||
if (psiMap.isEmpty()) return Collections.emptyMap();
|
||||
|
||||
Map<JavaTypeParameterImpl, JavaTypeImpl<?>> result = new HashMap<JavaTypeParameterImpl, JavaTypeImpl<?>>();
|
||||
for (Map.Entry<PsiTypeParameter, PsiType> entry : psiMap.entrySet()) {
|
||||
PsiType value = entry.getValue();
|
||||
result.put(new JavaTypeParameterImpl(entry.getKey()), value == null ? null : JavaTypeImpl.create(value));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
public String getPresentableText() {
|
||||
@@ -98,17 +85,17 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
@NotNull
|
||||
public List<JavaType> getTypeArguments() {
|
||||
JavaClassifierImpl<?> classifier = getClassifier();
|
||||
if (!(classifier instanceof JavaClassImpl)) return Collections.emptyList();
|
||||
|
||||
// parameters including ones from outer class
|
||||
Iterable<PsiTypeParameter> parameters = classifier instanceof JavaClassImpl
|
||||
? getTypeParameters(classifier.getPsi())
|
||||
: Collections.<PsiTypeParameter>emptyList();
|
||||
List<PsiTypeParameter> parameters = getTypeParameters(classifier.getPsi());
|
||||
|
||||
JavaTypeSubstitutorImpl substitutor = getSubstitutor();
|
||||
PsiSubstitutor substitutor = getSubstitutor();
|
||||
|
||||
List<JavaType> result = new ArrayList<JavaType>();
|
||||
List<JavaType> result = new ArrayList<JavaType>(parameters.size());
|
||||
for (PsiTypeParameter typeParameter : parameters) {
|
||||
result.add(substitutor.substitute(new JavaTypeParameterImpl(typeParameter)));
|
||||
PsiType substitutedType = substitutor.substitute(typeParameter);
|
||||
result.add(substitutedType == null ? null : JavaTypeImpl.create(substitutedType));
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -124,7 +111,7 @@ public class JavaClassifierTypeImpl extends JavaTypeImpl<PsiClassType> implement
|
||||
// PsiUtil.typeParametersIterable returns H3, H2, H1
|
||||
// But we would like to have H2, H3, H1 as such order is consistent with our type representation
|
||||
@NotNull
|
||||
public static List<PsiTypeParameter> getTypeParameters(@NotNull PsiClass owner) {
|
||||
private static List<PsiTypeParameter> getTypeParameters(@NotNull PsiClass owner) {
|
||||
List<PsiTypeParameter> result = null;
|
||||
|
||||
PsiTypeParameterListOwner currentOwner = owner;
|
||||
|
||||
-13
@@ -88,14 +88,6 @@ public class JavaElementCollectionFromPsiArrayUtil {
|
||||
}
|
||||
};
|
||||
|
||||
private static final Factory<PsiType, JavaType> TYPES = new Factory<PsiType, JavaType>() {
|
||||
@NotNull
|
||||
@Override
|
||||
public JavaType create(@NotNull PsiType psiType) {
|
||||
return JavaTypeImpl.create(psiType);
|
||||
}
|
||||
};
|
||||
|
||||
private static final Factory<PsiClassType, JavaClassifierType> CLASSIFIER_TYPES = new Factory<PsiClassType, JavaClassifierType>() {
|
||||
@NotNull
|
||||
@Override
|
||||
@@ -192,11 +184,6 @@ public class JavaElementCollectionFromPsiArrayUtil {
|
||||
return convert(typeParameters, Factories.TYPE_PARAMETERS);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static List<JavaType> types(@NotNull PsiType[] types) {
|
||||
return convert(types, Factories.TYPES);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static Collection<JavaClassifierType> classifierTypes(@NotNull PsiClassType[] classTypes) {
|
||||
return convert(classTypes, Factories.CLASSIFIER_TYPES);
|
||||
|
||||
-205
@@ -1,205 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.load.java.structure.impl;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifier;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaClassifierType;
|
||||
import org.jetbrains.kotlin.load.java.structure.JavaPrimitiveType;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class JavaTypeSubstitutorImpl {
|
||||
private final Map<JavaTypeParameterImpl, JavaTypeImpl<?>> substitutionMap;
|
||||
|
||||
public JavaTypeSubstitutorImpl(@NotNull Map<JavaTypeParameterImpl, JavaTypeImpl<?>> substitutionMap) {
|
||||
this.substitutionMap = substitutionMap;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaTypeImpl<?> substitute(@NotNull JavaTypeImpl<?> type) {
|
||||
JavaTypeImpl<?> substitutedType = substituteInternal(type);
|
||||
return substitutedType != null ? substitutedType : correctSubstitutionForRawType(type);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
// In case of raw type we get substitution map like T -> null,
|
||||
// in this case we should substitute upper bound of T or,
|
||||
// if it does not exist, return java.lang.Object
|
||||
private JavaTypeImpl<?> correctSubstitutionForRawType(@NotNull JavaTypeImpl<?> original) {
|
||||
if (original instanceof JavaClassifierType) {
|
||||
JavaClassifier classifier = ((JavaClassifierType) original).getClassifier();
|
||||
if (classifier instanceof JavaTypeParameterImpl) {
|
||||
return rawTypeForTypeParameter((JavaTypeParameterImpl) classifier);
|
||||
}
|
||||
}
|
||||
|
||||
return original;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JavaTypeImpl<?> substituteInternal(@NotNull JavaTypeImpl<?> type) {
|
||||
if (type instanceof JavaClassifierTypeImpl) {
|
||||
JavaClassifierTypeImpl classifierType = (JavaClassifierTypeImpl) type;
|
||||
JavaClassifierImpl<?> classifier = classifierType.getClassifier();
|
||||
|
||||
if (classifier instanceof JavaTypeParameterImpl) {
|
||||
return substitute((JavaTypeParameterImpl) classifier);
|
||||
}
|
||||
else if (classifier instanceof JavaClassImpl) {
|
||||
JavaClassImpl javaClass = (JavaClassImpl) classifier;
|
||||
Map<JavaTypeParameterImpl, JavaTypeImpl<?>> substMap = new HashMap<JavaTypeParameterImpl, JavaTypeImpl<?>>();
|
||||
processClass(javaClass, classifierType.getSubstitutor(), substMap);
|
||||
|
||||
return javaClass.createImmediateType(substMap);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
else if (type instanceof JavaPrimitiveType) {
|
||||
return type;
|
||||
}
|
||||
else if (type instanceof JavaArrayTypeImpl) {
|
||||
JavaTypeImpl<?> componentType = ((JavaArrayTypeImpl) type).getComponentType();
|
||||
JavaTypeImpl<?> substitutedComponentType = substitute(componentType);
|
||||
if (substitutedComponentType == componentType) return type;
|
||||
|
||||
return new JavaArrayTypeImpl(substitutedComponentType.getPsi().createArrayType());
|
||||
}
|
||||
else if (type instanceof JavaWildcardTypeImpl) {
|
||||
return substituteWildcardType((JavaWildcardTypeImpl) type);
|
||||
}
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
private void processClass(
|
||||
@NotNull JavaClassImpl javaClass,
|
||||
@NotNull JavaTypeSubstitutorImpl substitutor,
|
||||
@NotNull Map<JavaTypeParameterImpl, JavaTypeImpl<?>> substMap
|
||||
) {
|
||||
@SuppressWarnings("unchecked")
|
||||
List<JavaTypeParameterImpl> typeParameters = (List) javaClass.getTypeParameters();
|
||||
for (JavaTypeParameterImpl typeParameter : typeParameters) {
|
||||
JavaTypeImpl<?> substitutedParam = substitutor.substitute(typeParameter);
|
||||
substMap.put(typeParameter, substitutedParam == null ? null : substituteInternal(substitutedParam));
|
||||
}
|
||||
|
||||
if (javaClass.isStatic()) {
|
||||
return;
|
||||
}
|
||||
|
||||
JavaClassImpl outerClass = javaClass.getOuterClass();
|
||||
if (outerClass != null) {
|
||||
processClass(outerClass, substitutor, substMap);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private JavaTypeImpl<?> substituteWildcardType(@NotNull JavaWildcardTypeImpl wildcardType) {
|
||||
JavaTypeImpl<?> bound = wildcardType.getBound();
|
||||
if (bound == null) {
|
||||
return wildcardType;
|
||||
}
|
||||
|
||||
JavaTypeImpl<?> newBound = substituteInternal(bound);
|
||||
if (newBound == null) {
|
||||
// This can be in case of substitution wildcard to raw type
|
||||
return null;
|
||||
}
|
||||
|
||||
return rebound(wildcardType, newBound);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JavaWildcardTypeImpl rebound(@NotNull JavaWildcardTypeImpl type, @NotNull JavaTypeImpl<?> newBound) {
|
||||
PsiManager manager = type.getPsi().getManager();
|
||||
if (createJavaLangObjectType(manager).equals(newBound)) {
|
||||
return createUnboundedWildcard(manager);
|
||||
}
|
||||
|
||||
if (type.isExtends()) {
|
||||
return createUpperBoundWildcard(manager, newBound);
|
||||
}
|
||||
else {
|
||||
return createLowerBoundWildcard(manager, newBound);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private JavaTypeImpl<?> rawTypeForTypeParameter(@NotNull JavaTypeParameterImpl typeParameter) {
|
||||
Collection<JavaClassifierType> bounds = typeParameter.getUpperBounds();
|
||||
if (!bounds.isEmpty()) {
|
||||
return substitute(((JavaClassifierTypeImpl) bounds.iterator().next()));
|
||||
}
|
||||
|
||||
return createJavaLangObjectType(typeParameter.getPsi().getManager());
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JavaTypeImpl<?> substitute(@NotNull JavaTypeParameterImpl typeParameter) {
|
||||
if (substitutionMap.containsKey(typeParameter)) {
|
||||
return substitutionMap.get(typeParameter);
|
||||
}
|
||||
|
||||
PsiTypeParameter psiTypeParameter = typeParameter.getPsi();
|
||||
return JavaTypeImpl.create(
|
||||
JavaPsiFacade.getInstance(psiTypeParameter.getProject()).getElementFactory().createType(psiTypeParameter)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return substitutionMap.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return obj instanceof JavaTypeSubstitutorImpl && substitutionMap.equals(((JavaTypeSubstitutorImpl) obj).substitutionMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getSimpleName() + ": " + substitutionMap;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JavaTypeImpl<?> createJavaLangObjectType(@NotNull PsiManager manager) {
|
||||
return JavaTypeImpl.create(PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject())));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JavaWildcardTypeImpl createUpperBoundWildcard(@NotNull PsiManager manager, @NotNull JavaTypeImpl<?> bound) {
|
||||
return new JavaWildcardTypeImpl(PsiWildcardType.createExtends(manager, bound.getPsi()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JavaWildcardTypeImpl createLowerBoundWildcard(@NotNull PsiManager manager, @NotNull JavaTypeImpl<?> bound) {
|
||||
return new JavaWildcardTypeImpl(PsiWildcardType.createSuper(manager, bound.getPsi()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static JavaWildcardTypeImpl createUnboundedWildcard(@NotNull PsiManager manager) {
|
||||
return new JavaWildcardTypeImpl(PsiWildcardType.createUnbounded(manager));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user