Migrate PropagationHeuristics from PSI to JavaElement
Aside from refactorings, minor changes in logic are made:
- to find out if a type of a value parameter is vararg ('ellipsis type'), we
now check if the method is vararg and the parameter is its last parameter
(instead of 'instanceof PsiEllipsisType')
- 'visitedSuperclasses' is now a Set: this better reflects what it's supposed
to represent. Also result check of the 'add()' method on a List was useless
This commit is contained in:
+7
-13
@@ -18,8 +18,6 @@ package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiMember;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.psi.util.PsiFormatUtil;
|
||||
@@ -118,23 +116,19 @@ public final class DescriptorResolverUtils {
|
||||
return isEnumClassObject(ownerDescriptor) == shouldBeInEnumClassObject(member);
|
||||
}
|
||||
|
||||
public static boolean isObjectMethodInInterface(@NotNull PsiMember member) {
|
||||
if (!(member instanceof PsiMethod)) {
|
||||
public static boolean isObjectMethodInInterface(@NotNull JavaMember member) {
|
||||
if (!(member instanceof JavaMethod)) {
|
||||
return false;
|
||||
}
|
||||
PsiClass containingClass = member.getContainingClass();
|
||||
assert containingClass != null : "containing class is null for " + member;
|
||||
JavaClass containingClass = member.getContainingClass();
|
||||
assert containingClass != null : "Containing class is null for member: " + member;
|
||||
|
||||
if (!containingClass.isInterface()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isObjectMethod((PsiMethod) member);
|
||||
return containingClass.isInterface() && isObjectMethod((JavaMethod) member);
|
||||
}
|
||||
|
||||
public static boolean isObjectMethod(@NotNull PsiMethod method) {
|
||||
public static boolean isObjectMethod(@NotNull JavaMethod method) {
|
||||
String formattedMethod = PsiFormatUtil.formatMethod(
|
||||
method, PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS, SHOW_TYPE | SHOW_FQ_CLASS_NAMES);
|
||||
method.getPsi(), PsiSubstitutor.EMPTY, SHOW_NAME | SHOW_PARAMETERS, SHOW_TYPE | SHOW_FQ_CLASS_NAMES);
|
||||
return OBJECT_METHODS.contains(formattedMethod);
|
||||
}
|
||||
|
||||
|
||||
+15
-8
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.jetbrains.jet.lang.resolve.java.kotlinSignature;
|
||||
|
||||
import com.google.common.collect.*;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
@@ -25,6 +28,8 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
@@ -45,24 +50,26 @@ public class JavaToKotlinMethodMap {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<FunctionDescriptor> getFunctions(@NotNull PsiMethod psiMethod, @NotNull ClassDescriptor containingClass) {
|
||||
ImmutableCollection<ClassData> classDatas = mapContainer.map.get(psiMethod.getContainingClass().getQualifiedName());
|
||||
public List<FunctionDescriptor> getFunctions(
|
||||
@NotNull JavaMethod javaMethod,
|
||||
@NotNull FqName classFqName,
|
||||
@NotNull ClassDescriptor containingClass
|
||||
) {
|
||||
ImmutableCollection<ClassData> classDatas = mapContainer.map.get(classFqName.asString());
|
||||
|
||||
List<FunctionDescriptor> result = Lists.newArrayList();
|
||||
|
||||
Set<ClassDescriptor> allSuperClasses = DescriptorUtils.getAllSuperClasses(containingClass);
|
||||
|
||||
String serializedPsiMethod = serializePsiMethod(psiMethod);
|
||||
String serializedMethod = serializePsiMethod(javaMethod.getPsi());
|
||||
for (ClassData classData : classDatas) {
|
||||
String expectedSerializedFunction = classData.method2Function.get(serializedPsiMethod);
|
||||
String expectedSerializedFunction = classData.method2Function.get(serializedMethod);
|
||||
if (expectedSerializedFunction == null) continue;
|
||||
|
||||
ClassDescriptor kotlinClass = classData.kotlinClass;
|
||||
if (!allSuperClasses.contains(kotlinClass)) continue;
|
||||
|
||||
|
||||
Collection<FunctionDescriptor> functions =
|
||||
kotlinClass.getDefaultType().getMemberScope().getFunctions(Name.identifier(psiMethod.getName()));
|
||||
Collection<FunctionDescriptor> functions = kotlinClass.getDefaultType().getMemberScope().getFunctions(javaMethod.getName());
|
||||
|
||||
for (FunctionDescriptor function : functions) {
|
||||
if (expectedSerializedFunction.equals(serializeFunction(function))) {
|
||||
|
||||
+71
-64
@@ -18,15 +18,18 @@ package org.jetbrains.jet.lang.resolve.java.kotlinSignature;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.google.common.collect.Sets;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.Visibilities;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaSupertypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.*;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.JetTypeImpl;
|
||||
@@ -36,12 +39,7 @@ import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||
import org.jetbrains.jet.renderer.DescriptorRenderer;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static com.intellij.psi.util.TypeConversionUtil.erasure;
|
||||
import java.util.*;
|
||||
|
||||
// This class contains heuristics for processing corner cases in propagation
|
||||
class PropagationHeuristics {
|
||||
@@ -123,7 +121,7 @@ class PropagationHeuristics {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static List<PsiMethod> getSuperMethods(@NotNull PsiMethod method) {
|
||||
static List<JavaMethod> getSuperMethods(@NotNull JavaMethod method) {
|
||||
return new SuperMethodCollector(method).collect();
|
||||
}
|
||||
|
||||
@@ -131,79 +129,83 @@ class PropagationHeuristics {
|
||||
}
|
||||
|
||||
private static class SuperMethodCollector {
|
||||
private final PsiMethod initialMethod;
|
||||
private final String initialMethodName;
|
||||
private final List<PsiType> initialParametersErasure;
|
||||
private final JavaMethod initialMethod;
|
||||
private final Name initialMethodName;
|
||||
private final List<JavaType> initialParametersErasure;
|
||||
|
||||
private final List<PsiClass> visitedSuperclasses = Lists.newArrayList();
|
||||
private final List<PsiMethod> collectedMethods = Lists.newArrayList();
|
||||
private final Set<JavaClass> visitedSuperclasses = Sets.newHashSet();
|
||||
private final List<JavaMethod> collectedMethods = Lists.newArrayList();
|
||||
|
||||
private SuperMethodCollector(@NotNull PsiMethod initialMethod) {
|
||||
private SuperMethodCollector(@NotNull JavaMethod initialMethod) {
|
||||
this.initialMethod = initialMethod;
|
||||
initialMethodName = initialMethod.getName();
|
||||
|
||||
PsiParameterList parameterList = initialMethod.getParameterList();
|
||||
initialParametersErasure = Lists.newArrayListWithExpectedSize(parameterList.getParametersCount());
|
||||
for (PsiParameter parameter : parameterList.getParameters()) {
|
||||
initialParametersErasure.add(erasureNoEllipsis(parameter.getType()));
|
||||
Collection<JavaValueParameter> valueParameters = initialMethod.getValueParameters();
|
||||
initialParametersErasure = Lists.newArrayListWithExpectedSize(valueParameters.size());
|
||||
for (Iterator<JavaValueParameter> iterator = valueParameters.iterator(); iterator.hasNext(); ) {
|
||||
JavaType type = iterator.next().getType();
|
||||
boolean isVararg = initialMethod.isVararg() && !iterator.hasNext();
|
||||
initialParametersErasure.add(erasure(varargToArray(type, isVararg)));
|
||||
}
|
||||
}
|
||||
|
||||
public List<PsiMethod> collect() {
|
||||
@NotNull
|
||||
public List<JavaMethod> collect() {
|
||||
if (!canHaveSuperMethod(initialMethod)) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
PsiClass containingClass = initialMethod.getContainingClass();
|
||||
JavaClass containingClass = initialMethod.getContainingClass();
|
||||
assert containingClass != null : " containing class is null for " + initialMethod;
|
||||
|
||||
for (PsiClassType superType : containingClass.getSuperTypes()) {
|
||||
collectFromSupertype(superType);
|
||||
for (JavaClassifierType supertype : containingClass.getSupertypes()) {
|
||||
collectFromSupertype(supertype);
|
||||
}
|
||||
|
||||
return collectedMethods;
|
||||
}
|
||||
|
||||
private void collectFromSupertype(PsiClassType type) {
|
||||
PsiClass klass = type.resolve();
|
||||
if (klass == null) {
|
||||
return;
|
||||
}
|
||||
if (!visitedSuperclasses.add(klass)) {
|
||||
return;
|
||||
}
|
||||
private void collectFromSupertype(@NotNull JavaClassifierType type) {
|
||||
JavaClassifier classifier = type.getClassifier();
|
||||
if (!(classifier instanceof JavaClass)) return;
|
||||
|
||||
PsiSubstitutor supertypeSubstitutor = getErasedSubstitutor(type);
|
||||
for (PsiMethod methodFromSuper : klass.getMethods()) {
|
||||
JavaClass klass = (JavaClass) classifier;
|
||||
if (!visitedSuperclasses.add(klass)) return;
|
||||
|
||||
JavaTypeSubstitutor supertypeSubstitutor = getErasedSubstitutor(type);
|
||||
for (JavaMethod methodFromSuper : klass.getMethods()) {
|
||||
if (isSubMethodOf(methodFromSuper, supertypeSubstitutor)) {
|
||||
collectedMethods.add(methodFromSuper);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (PsiType superType : type.getSuperTypes()) {
|
||||
assert superType instanceof PsiClassType : "supertype is not a PsiClassType for " + type + ": " + superType;
|
||||
collectFromSupertype((PsiClassType) superType);
|
||||
for (JavaClassifierType supertype : type.getSupertypes()) {
|
||||
collectFromSupertype(supertype);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSubMethodOf(@NotNull PsiMethod methodFromSuper, @NotNull PsiSubstitutor supertypeSubstitutor) {
|
||||
private boolean isSubMethodOf(@NotNull JavaMethod methodFromSuper, @NotNull JavaTypeSubstitutor supertypeSubstitutor) {
|
||||
if (!methodFromSuper.getName().equals(initialMethodName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PsiParameterList fromSuperParameterList = methodFromSuper.getParameterList();
|
||||
|
||||
if (fromSuperParameterList.getParametersCount() != initialParametersErasure.size()) {
|
||||
Collection<JavaValueParameter> fromSuperParameters = methodFromSuper.getValueParameters();
|
||||
if (fromSuperParameters.size() != initialParametersErasure.size()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < initialParametersErasure.size(); i++) {
|
||||
PsiType originalType = initialParametersErasure.get(i);
|
||||
PsiType typeFromSuper = fromSuperParameterList.getParameters()[i].getType();
|
||||
PsiType typeFromSuperErased = erasureNoEllipsis(supertypeSubstitutor.substitute(typeFromSuper));
|
||||
Iterator<JavaType> originalIterator = initialParametersErasure.iterator();
|
||||
Iterator<JavaValueParameter> superIterator = fromSuperParameters.iterator();
|
||||
while (originalIterator.hasNext()) {
|
||||
JavaType originalType = originalIterator.next();
|
||||
JavaType typeFromSuper = superIterator.next().getType();
|
||||
|
||||
if (!Comparing.equal(originalType, typeFromSuperErased)) {
|
||||
boolean isVarargType = methodFromSuper.isVararg() && !superIterator.hasNext();
|
||||
|
||||
JavaType typeFromSuperErased = erasure(varargToArray(supertypeSubstitutor.substitute(typeFromSuper), isVarargType));
|
||||
|
||||
if (!originalType.equals(typeFromSuperErased)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -211,28 +213,33 @@ class PropagationHeuristics {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static PsiType erasureNoEllipsis(PsiType type) {
|
||||
if (type instanceof PsiEllipsisType) {
|
||||
return erasureNoEllipsis(((PsiEllipsisType) type).toArrayType());
|
||||
}
|
||||
return erasure(type);
|
||||
@NotNull
|
||||
private static JavaType varargToArray(@NotNull JavaType type, boolean isVararg) {
|
||||
return isVararg ? JavaArrayType.create(((JavaArrayType) type).getComponentType()) : type;
|
||||
}
|
||||
|
||||
private static PsiSubstitutor getErasedSubstitutor(PsiClassType type) {
|
||||
Map<PsiTypeParameter, PsiType> unerasedMap = type.resolveGenerics().getSubstitutor().getSubstitutionMap();
|
||||
Map<PsiTypeParameter, PsiType> erasedMap = Maps.newHashMapWithExpectedSize(unerasedMap.size());
|
||||
for (Map.Entry<PsiTypeParameter, PsiType> entry : unerasedMap.entrySet()) {
|
||||
erasedMap.put(entry.getKey(), erasure(entry.getValue()));
|
||||
}
|
||||
return PsiSubstitutorImpl.createSubstitutor(erasedMap);
|
||||
@NotNull
|
||||
private static JavaType erasure(@NotNull JavaType type) {
|
||||
return JavaType.create(TypeConversionUtil.erasure(type.getPsi()));
|
||||
}
|
||||
|
||||
private static boolean canHaveSuperMethod(PsiMethod method) {
|
||||
if (method.isConstructor()) return false;
|
||||
if (method.hasModifierProperty(PsiModifier.STATIC)) return false;
|
||||
if (method.hasModifierProperty(PsiModifier.PRIVATE)) return false;
|
||||
PsiClass containingClass = method.getContainingClass();
|
||||
return containingClass != null && !CommonClassNames.JAVA_LANG_OBJECT.equals(containingClass.getQualifiedName());
|
||||
@NotNull
|
||||
private static JavaTypeSubstitutor getErasedSubstitutor(@NotNull JavaClassifierType type) {
|
||||
Map<JavaTypeParameter, JavaType> unerasedMap = type.getSubstitutor().getSubstitutionMap();
|
||||
Map<JavaTypeParameter, JavaType> erasedMap = Maps.newHashMapWithExpectedSize(unerasedMap.size());
|
||||
for (Map.Entry<JavaTypeParameter, JavaType> entry : unerasedMap.entrySet()) {
|
||||
JavaType value = entry.getValue();
|
||||
erasedMap.put(entry.getKey(), value == null ? null : erasure(value));
|
||||
}
|
||||
return JavaTypeSubstitutor.create(erasedMap);
|
||||
}
|
||||
|
||||
private static boolean canHaveSuperMethod(@NotNull JavaMethod method) {
|
||||
if (method.isConstructor() || method.isStatic() || method.getVisibility() == Visibilities.PRIVATE) {
|
||||
return false;
|
||||
}
|
||||
JavaClass containingClass = method.getContainingClass();
|
||||
return containingClass != null && !JavaSupertypeResolver.OBJECT_FQ_NAME.equals(containingClass.getFqName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-22
@@ -20,7 +20,6 @@ import com.google.common.collect.*;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiManager;
|
||||
import com.intellij.psi.PsiMethod;
|
||||
@@ -40,6 +39,7 @@ import org.jetbrains.jet.lang.resolve.java.TypeUsage;
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.JetClsMethod;
|
||||
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe;
|
||||
@@ -217,30 +217,29 @@ public class SignaturesPropagationData {
|
||||
|
||||
Map<ClassDescriptor, JetType> superclassToSupertype = getSuperclassToSupertypeMap(containingClass);
|
||||
|
||||
Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> superclassToFunctions =
|
||||
Multimap<FqName, Pair<FunctionDescriptor, JavaMethod>> superclassToFunctions =
|
||||
getSuperclassToFunctionsMultimap(method, trace.getBindingContext(), containingClass);
|
||||
|
||||
for (PsiMethod superMethod : PropagationHeuristics.getSuperMethods(method.getPsi())) {
|
||||
PsiClass psiClass = superMethod.getContainingClass();
|
||||
assert psiClass != null;
|
||||
String classFqNameString = psiClass.getQualifiedName();
|
||||
assert classFqNameString != null;
|
||||
FqName classFqName = new FqName(classFqNameString);
|
||||
for (JavaMethod superMethod : PropagationHeuristics.getSuperMethods(method)) {
|
||||
JavaClass javaClass = superMethod.getContainingClass();
|
||||
assert javaClass != null : "Super method doesn't have a containing class: " + superMethod;
|
||||
FqName classFqName = javaClass.getFqName();
|
||||
assert classFqName != null : "Class FQ name should not be null: " + javaClass;
|
||||
|
||||
if (!JavaToKotlinClassMap.getInstance().mapPlatformClass(classFqName).isEmpty()) {
|
||||
for (FunctionDescriptor superFun : JavaToKotlinMethodMap.INSTANCE.getFunctions(superMethod, containingClass)) {
|
||||
for (FunctionDescriptor superFun : JavaToKotlinMethodMap.INSTANCE.getFunctions(superMethod, classFqName, containingClass)) {
|
||||
superFunctions.add(substituteSuperFunction(superclassToSupertype, superFun));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
DeclarationDescriptor superFun = superMethod instanceof JetClsMethod
|
||||
? trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, ((JetClsMethod) superMethod).getOrigin())
|
||||
DeclarationDescriptor superFun = superMethod.getPsi() instanceof JetClsMethod
|
||||
? trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, ((JetClsMethod) superMethod.getPsi()).getOrigin())
|
||||
: findSuperFunction(superclassToFunctions.get(classFqName), superMethod);
|
||||
if (superFun == null) {
|
||||
// Super methods which are Object methods in interfaces are not loaded by JDR.
|
||||
if (!DescriptorResolverUtils.isObjectMethodInInterface(superMethod)) {
|
||||
reportCantFindSuperFunction(method.getPsi());
|
||||
reportCantFindSuperFunction(method);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -264,12 +263,12 @@ public class SignaturesPropagationData {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> getSuperclassToFunctionsMultimap(
|
||||
private static Multimap<FqName, Pair<FunctionDescriptor, JavaMethod>> getSuperclassToFunctionsMultimap(
|
||||
@NotNull JavaMethod method,
|
||||
@NotNull BindingContext bindingContext,
|
||||
@NotNull ClassDescriptor containingClass
|
||||
) {
|
||||
Multimap<FqName, Pair<FunctionDescriptor, PsiMethod>> result = HashMultimap.create();
|
||||
Multimap<FqName, Pair<FunctionDescriptor, JavaMethod>> result = HashMultimap.create();
|
||||
|
||||
Name functionName = method.getName();
|
||||
int parameterCount = method.getValueParameters().size();
|
||||
@@ -285,7 +284,7 @@ public class SignaturesPropagationData {
|
||||
fun.getValueParameters().size() + (fun.getReceiverParameter() != null ? 1 : 0) == parameterCount) {
|
||||
PsiElement declaration = BindingContextUtils.descriptorToDeclaration(bindingContext, fun);
|
||||
if (declaration instanceof PsiMethod) {
|
||||
result.put(fqName, Pair.create(fun, (PsiMethod) declaration));
|
||||
result.put(fqName, Pair.create(fun, new JavaMethod((PsiMethod) declaration)));
|
||||
} // else declaration is null or JetNamedFunction: both cases are processed later
|
||||
}
|
||||
}
|
||||
@@ -295,12 +294,12 @@ public class SignaturesPropagationData {
|
||||
|
||||
@Nullable
|
||||
private static DeclarationDescriptor findSuperFunction(
|
||||
@NotNull Collection<Pair<FunctionDescriptor, PsiMethod>> superFunctionCandidates,
|
||||
@NotNull PsiMethod superMethod
|
||||
@NotNull Collection<Pair<FunctionDescriptor, JavaMethod>> superFunctionCandidates,
|
||||
@NotNull JavaMethod superMethod
|
||||
) {
|
||||
PsiManager psiManager = PsiManager.getInstance(superMethod.getProject());
|
||||
for (Pair<FunctionDescriptor, PsiMethod> candidate : superFunctionCandidates) {
|
||||
if (psiManager.areElementsEquivalent(candidate.second, superMethod)) {
|
||||
PsiManager psiManager = PsiManager.getInstance(superMethod.getPsi().getProject());
|
||||
for (Pair<FunctionDescriptor, JavaMethod> candidate : superFunctionCandidates) {
|
||||
if (psiManager.areElementsEquivalent(candidate.second.getPsi(), superMethod.getPsi())) {
|
||||
return candidate.first;
|
||||
}
|
||||
}
|
||||
@@ -693,8 +692,8 @@ public class SignaturesPropagationData {
|
||||
return builtIns.isArray(type) || builtIns.isPrimitiveArray(type);
|
||||
}
|
||||
|
||||
private static void reportCantFindSuperFunction(@NotNull PsiMethod psiMethod) {
|
||||
String errorMessage = "Can't find super function for " + psiMethod + " defined in " + psiMethod.getContainingClass();
|
||||
private static void reportCantFindSuperFunction(@NotNull JavaMethod javaMethod) {
|
||||
String errorMessage = "Can't find super function for " + javaMethod + " defined in " + javaMethod.getContainingClass();
|
||||
if (SystemInfo.isMac) {
|
||||
LOG.error("Remove duplicates from your JDK definition\n" + errorMessage);
|
||||
}
|
||||
|
||||
+1
-1
@@ -375,7 +375,7 @@ public class SingleAbstractMethodUtils {
|
||||
return true;
|
||||
}
|
||||
for (JavaMethod method : javaClass.getMethods()) {
|
||||
if (DescriptorResolverUtils.isObjectMethod(method.getPsi())) { // e.g., ignore toString() declared in interface
|
||||
if (DescriptorResolverUtils.isObjectMethod(method)) { // e.g., ignore toString() declared in interface
|
||||
continue;
|
||||
}
|
||||
if (!method.getTypeParameters().isEmpty()) {
|
||||
|
||||
+1
-1
@@ -211,7 +211,7 @@ import java.util.Map;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (DescriptorResolverUtils.isObjectMethodInInterface(member.getPsi())) {
|
||||
if (DescriptorResolverUtils.isObjectMethodInInterface(member)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+5
@@ -30,6 +30,11 @@ public class JavaArrayType extends JavaType {
|
||||
return (PsiArrayType) super.getPsi();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JavaArrayType create(@NotNull JavaType elementType) {
|
||||
return new JavaArrayType(elementType.getPsi().createArrayType());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaType getComponentType() {
|
||||
return JavaType.create(getPsi().getComponentType());
|
||||
|
||||
+37
@@ -17,25 +17,62 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.structure;
|
||||
|
||||
import com.intellij.psi.PsiSubstitutor;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiTypeParameter;
|
||||
import com.intellij.psi.impl.PsiSubstitutorImpl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class JavaTypeSubstitutor {
|
||||
private final PsiSubstitutor psiSubstitutor;
|
||||
private Map<JavaTypeParameter, JavaType> substitutionMap;
|
||||
|
||||
public JavaTypeSubstitutor(@NotNull PsiSubstitutor psiSubstitutor) {
|
||||
this.psiSubstitutor = psiSubstitutor;
|
||||
}
|
||||
|
||||
public JavaTypeSubstitutor(@NotNull PsiSubstitutor psiSubstitutor, @NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
|
||||
this(psiSubstitutor);
|
||||
this.substitutionMap = substitutionMap;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiSubstitutor getPsi() {
|
||||
return psiSubstitutor;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static JavaTypeSubstitutor create(@NotNull Map<JavaTypeParameter, JavaType> substitutionMap) {
|
||||
Map<PsiTypeParameter, PsiType> psiMap = new HashMap<PsiTypeParameter, PsiType>();
|
||||
for (Map.Entry<JavaTypeParameter, JavaType> entry : substitutionMap.entrySet()) {
|
||||
JavaType value = entry.getValue();
|
||||
psiMap.put(entry.getKey().getPsi(), value == null ? null : value.getPsi());
|
||||
}
|
||||
PsiSubstitutor psiSubstitutor = PsiSubstitutorImpl.createSubstitutor(psiMap);
|
||||
return new JavaTypeSubstitutor(psiSubstitutor, substitutionMap);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public JavaType substitute(@NotNull JavaType type) {
|
||||
return JavaType.create(getPsi().substitute(type.getPsi()));
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Map<JavaTypeParameter, JavaType> getSubstitutionMap() {
|
||||
if (substitutionMap == null) {
|
||||
Map<PsiTypeParameter, PsiType> psiMap = psiSubstitutor.getSubstitutionMap();
|
||||
substitutionMap = new HashMap<JavaTypeParameter, JavaType>();
|
||||
for (Map.Entry<PsiTypeParameter, PsiType> entry : psiMap.entrySet()) {
|
||||
PsiType value = entry.getValue();
|
||||
substitutionMap.put(new JavaTypeParameter(entry.getKey()), value == null ? null : JavaType.create(value));
|
||||
}
|
||||
}
|
||||
|
||||
return substitutionMap;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return getPsi().hashCode();
|
||||
|
||||
Reference in New Issue
Block a user