diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java index 18503b4b0fb..c0fb6eb0c5f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java @@ -151,4 +151,78 @@ public final class DescriptorResolverUtils { return result; } + + /** + * @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType) + */ + @Nullable + public static JavaType erasure(@NotNull JavaType type) { + return erasure(type, JavaTypeSubstitutor.EMPTY); + } + + /** + * @see com.intellij.psi.util.TypeConversionUtil#erasure(com.intellij.psi.PsiType, com.intellij.psi.PsiSubstitutor) + */ + @Nullable + public static JavaType erasure(@NotNull JavaType type, @NotNull JavaTypeSubstitutor substitutor) { + if (type instanceof JavaClassifierType) { + JavaClassifier classifier = ((JavaClassifierType) type).getClassifier(); + if (classifier instanceof JavaClass) { + return ((JavaClass) classifier).getDefaultType(); + } + else if (classifier instanceof JavaTypeParameter) { + JavaTypeParameter typeParameter = (JavaTypeParameter) classifier; + return typeParameterErasure(typeParameter, new HashSet(), substitutor); + } + else { + return null; + } + } + else if (type instanceof JavaPrimitiveType) { + return type; + } + else if (type instanceof JavaArrayType) { + JavaType erasure = erasure(((JavaArrayType) type).getComponentType(), substitutor); + return erasure == null ? null : JavaArrayType.create(erasure); + } + else if (type instanceof JavaWildcardType) { + JavaWildcardType wildcardType = (JavaWildcardType) type; + JavaType bound = wildcardType.getBound(); + if (bound != null && wildcardType.isExtends()) { + return erasure(bound, substitutor); + } + return wildcardType.getTypeProvider().createJavaLangObjectType(); + } + else { + throw new IllegalStateException("Unsupported type: " + type); + } + } + + /** + * @see com.intellij.psi.util.TypeConversionUtil#typeParameterErasure(com.intellij.psi.PsiTypeParameter) + */ + @Nullable + private static JavaType typeParameterErasure( + @NotNull JavaTypeParameter typeParameter, + @NotNull HashSet visited, + @NotNull JavaTypeSubstitutor substitutor + ) { + Collection upperBounds = typeParameter.getUpperBounds(); + if (!upperBounds.isEmpty()) { + JavaClassifier classifier = upperBounds.iterator().next().getClassifier(); + if (classifier instanceof JavaTypeParameter && !visited.contains(classifier)) { + JavaTypeParameter typeParameterBound = (JavaTypeParameter) classifier; + visited.add(typeParameterBound); + JavaType substitutedType = substitutor.substitute(typeParameterBound); + if (substitutedType != null) { + return erasure(substitutedType); + } + return typeParameterErasure(typeParameterBound, visited, substitutor); + } + else if (classifier instanceof JavaClass) { + return ((JavaClass) classifier).getDefaultType(); + } + } + return typeParameter.getTypeProvider().createJavaLangObjectType(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java index 2c1e64bcecd..0da61817941 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/PropagationHeuristics.java @@ -19,8 +19,8 @@ package org.jetbrains.jet.lang.resolve.java.kotlinSignature; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; +import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.Condition; -import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -41,6 +41,8 @@ import org.jetbrains.jet.renderer.DescriptorRenderer; import java.util.*; +import static org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils.erasure; + // This class contains heuristics for processing corner cases in propagation class PropagationHeuristics { // Checks for case when method returning Super[] is overridden with method returning Sub[] @@ -201,7 +203,7 @@ class PropagationHeuristics { parameterFromSuper.isVararg() )); - if (!originalType.equals(typeFromSuper)) { + if (!Comparing.equal(originalType, typeFromSuper)) { return false; } } @@ -214,11 +216,6 @@ class PropagationHeuristics { return isVararg ? JavaArrayType.create(((JavaArrayType) type).getComponentType()) : type; } - @NotNull - private static JavaType erasure(@NotNull JavaType type) { - return JavaType.create(TypeConversionUtil.erasure(type.getPsi())); - } - @NotNull private static JavaTypeSubstitutor getErasedSubstitutor(@NotNull JavaClassifierType type) { Map unerasedMap = type.getSubstitutor().getSubstitutionMap(); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java index 3ae0e421388..6d30b56e005 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/sam/SingleAbstractMethodUtils.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.resolve.java.sam; import com.google.common.collect.Lists; -import com.intellij.psi.util.TypeConversionUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; @@ -38,6 +37,7 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.util.*; +import static org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils.erasure; import static org.jetbrains.jet.lang.types.Variance.INVARIANT; public class SingleAbstractMethodUtils { @@ -407,17 +407,12 @@ public class SingleAbstractMethodUtils { for (Iterator it1 = parameters1.iterator(), it2 = parameters2.iterator(); it1.hasNext(); ) { JavaType type1 = erasure(substitutor1.substitute(it1.next().getType()), substitutor1); JavaType type2 = erasure(substitutor2.substitute(it2.next().getType()), substitutor2); - if (!type1.equals(type2)) return false; + if (!(type1 == null ? type2 == null : type1.equals(type2))) return false; } return true; } - @NotNull - private static JavaType erasure(@NotNull JavaType type, @NotNull JavaTypeSubstitutor substitutor) { - return JavaType.create(TypeConversionUtil.erasure(type.getPsi(), substitutor.getPsi())); - } - @Nullable private JavaMethod getFoundMethod() { return foundMethod; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeParameter.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeParameter.java index 5a95457664a..4e2b1639cb2 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeParameter.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeParameter.java @@ -70,4 +70,9 @@ public class JavaTypeParameter extends JavaClassifier implements JavaNamedElemen return null; } + + @NotNull + public JavaTypeProvider getTypeProvider() { + return new JavaTypeProvider(getPsi().getManager()); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java new file mode 100644 index 00000000000..38262731613 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeProvider.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2013 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.jet.lang.resolve.java.structure; + +import com.intellij.psi.PsiManager; +import com.intellij.psi.PsiType; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; + +public class JavaTypeProvider { + private final PsiManager manager; + + public JavaTypeProvider(@NotNull PsiManager manager) { + this.manager = manager; + } + + @NotNull + public JavaType createJavaLangObjectType() { + return JavaType.create(PsiType.getJavaLangObject(manager, GlobalSearchScope.allScope(manager.getProject()))); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeSubstitutor.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeSubstitutor.java index ee941e08dda..0aa5657bfc6 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeSubstitutor.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaTypeSubstitutor.java @@ -21,11 +21,14 @@ import com.intellij.psi.PsiType; import com.intellij.psi.PsiTypeParameter; import com.intellij.psi.impl.PsiSubstitutorImpl; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; public class JavaTypeSubstitutor { + public static final JavaTypeSubstitutor EMPTY = new JavaTypeSubstitutor(PsiSubstitutor.EMPTY); + private final PsiSubstitutor psiSubstitutor; private Map substitutionMap; @@ -59,6 +62,12 @@ public class JavaTypeSubstitutor { return JavaType.create(getPsi().substitute(type.getPsi())); } + @Nullable + public JavaType substitute(@NotNull JavaTypeParameter typeParameter) { + PsiType psiType = getPsi().substitute(typeParameter.getPsi()); + return psiType == null ? null : JavaType.create(psiType); + } + @NotNull public Map getSubstitutionMap() { if (substitutionMap == null) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaWildcardType.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaWildcardType.java index c3867f0d3a8..7b2d841993a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaWildcardType.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaWildcardType.java @@ -41,4 +41,9 @@ public class JavaWildcardType extends JavaType { public boolean isExtends() { return getPsi().isExtends(); } + + @NotNull + public JavaTypeProvider getTypeProvider() { + return new JavaTypeProvider(getPsi().getManager()); + } }