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 7282344f297..01aff8833b1 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 @@ -43,8 +43,9 @@ public final class DescriptorResolverUtils { private DescriptorResolverUtils() { } - public static boolean isCompiledKotlinPackageClass(@NotNull JavaClass javaClass) { - if (javaClass.getPsi() instanceof ClsClassImpl) { + public static boolean isCompiledKotlinPackageClass(@NotNull PsiClass psiClass) { + if (psiClass instanceof ClsClassImpl) { + JavaClass javaClass = new JavaClass(psiClass); FqName fqName = javaClass.getFqName(); if (fqName != null && PackageClassUtils.isPackageClassFqName(fqName)) { return hasAnnotation(javaClass, JvmAnnotationNames.KOTLIN_PACKAGE.getFqName()); @@ -53,9 +54,9 @@ public final class DescriptorResolverUtils { return false; } - public static boolean isCompiledKotlinClass(@NotNull JavaClass javaClass) { - if (javaClass.getPsi() instanceof ClsClassImpl) { - return hasAnnotation(javaClass, JvmAnnotationNames.KOTLIN_CLASS.getFqName()); + public static boolean isCompiledKotlinClass(@NotNull PsiClass psiClass) { + if (psiClass instanceof ClsClassImpl) { + return hasAnnotation(new JavaClass(psiClass), JvmAnnotationNames.KOTLIN_CLASS.getFqName()); } return false; } @@ -64,8 +65,8 @@ public final class DescriptorResolverUtils { return javaClass.findAnnotation(annotationFqName.asString()) != null; } - public static boolean isCompiledKotlinClassOrPackageClass(@NotNull JavaClass javaClass) { - return isCompiledKotlinClass(javaClass) || isCompiledKotlinPackageClass(javaClass); + public static boolean isCompiledKotlinClassOrPackageClass(@NotNull PsiClass psiClass) { + return isCompiledKotlinClass(psiClass) || isCompiledKotlinPackageClass(psiClass); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java index 1eccaa4dc59..bf13edbd6e7 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaNamespaceResolver.java @@ -187,10 +187,10 @@ public final class JavaNamespaceResolver { return null; } - if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(javaClass)) { + PsiClass psiClass = javaClass.getPsi(); + if (DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(psiClass)) { return null; } - PsiClass psiClass = javaClass.getPsi(); if (!hasStaticMembers(psiClass)) { return null; } @@ -257,7 +257,7 @@ public final class JavaNamespaceResolver { Collection classes = DescriptorResolverUtils.filterDuplicateClasses(javaPackage.getClasses()); List result = new ArrayList(classes.size()); for (JavaClass javaClass : classes) { - if (DescriptorResolverUtils.isCompiledKotlinClass(javaClass)) { + if (DescriptorResolverUtils.isCompiledKotlinClass(javaClass.getPsi())) { result.add(javaClass.getName()); } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypeResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypeResolver.java index 0a5b9c0fd66..aedfd65174b 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypeResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaSupertypeResolver.java @@ -27,6 +27,7 @@ import org.jetbrains.jet.lang.resolve.java.TypeUsage; import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver; import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.java.structure.JavaClassType; +import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetType; @@ -116,9 +117,10 @@ public final class JavaSupertypeResolver { ) { List result = new ArrayList(supertypes.size()); for (JavaClassType type : supertypes) { - JavaClass resolved = type.resolve(); + JavaClassifier resolved = type.resolve(); if (resolved != null) { - FqName fqName = resolved.getFqName(); + assert resolved instanceof JavaClass : "Supertype should be a class: " + resolved; + FqName fqName = ((JavaClass) resolved).getFqName(); assert fqName != null : "Unresolved supertype: " + resolved; if (JvmAbi.JET_OBJECT.getFqName().equals(fqName)) { continue; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaTypeTransformer.java index d69b003bb18..aefcb56a71e 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaTypeTransformer.java @@ -19,8 +19,10 @@ package org.jetbrains.jet.lang.resolve.java.resolver; import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.intellij.openapi.diagnostic.Logger; -import com.intellij.psi.*; +import com.intellij.psi.PsiModifierListOwner; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; @@ -89,7 +91,12 @@ public class JavaTypeTransformer { @NotNull TypeVariableResolver typeVariableResolver ) { if (type instanceof JavaClassType) { - return transformClassType((JavaClassType) type, howThisTypeIsUsed, typeVariableResolver); + JavaClassType classType = (JavaClassType) type; + JetType jetType = transformClassType(classType, howThisTypeIsUsed, typeVariableResolver); + if (jetType == null) { + return ErrorUtils.createErrorType("Unresolved java class: " + classType.getPresentableText()); + } + return jetType; } else if (type instanceof JavaPrimitiveType) { String canonicalText = ((JavaPrimitiveType) type).getCanonicalText(); @@ -105,125 +112,130 @@ public class JavaTypeTransformer { } } - @NotNull + @Nullable private JetType transformClassType( @NotNull JavaClassType classType, @NotNull TypeUsage howThisTypeIsUsed, @NotNull TypeVariableResolver typeVariableResolver ) { - JavaClass javaClass = classType.resolve(); - if (javaClass == null) { - return ErrorUtils.createErrorType("Unresolved java class: " + classType.getPresentableText()); + JavaClassifier javaClassifier = classType.resolve(); + if (javaClassifier == null) { + return null; + } + if (javaClassifier instanceof JavaTypeParameter) { + return transformTypeParameter((JavaTypeParameter) javaClassifier, howThisTypeIsUsed, typeVariableResolver); + } + else if (javaClassifier instanceof JavaClass) { + FqName fqName = ((JavaClass) javaClassifier).getFqName(); + assert fqName != null : "Class type should have a FQ name: " + javaClassifier; + return transformClassType(fqName, classType, howThisTypeIsUsed, typeVariableResolver); + } + else { + throw new UnsupportedOperationException("Unsupported classifier: " + javaClassifier); + } + } + + @Nullable + private JetType transformTypeParameter( + @NotNull JavaTypeParameter typeParameter, + @NotNull TypeUsage howThisTypeIsUsed, + @NotNull TypeVariableResolver typeVariableResolver + ) { + JavaTypeParameterListOwner owner = typeParameter.getOwner(); + if (owner instanceof JavaMethod && ((JavaMethod) owner).isConstructor()) { + Set supertypesJet = Sets.newHashSet(); + for (JavaClassType supertype : typeParameter.getUpperBounds()) { + supertypesJet.add(transformToType(supertype, UPPER_BOUND, typeVariableResolver)); + } + return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet); } - PsiClass psiClass = javaClass.getPsi(); + TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName().asString()); - if (psiClass instanceof PsiTypeParameter) { - PsiTypeParameter typeParameter = (PsiTypeParameter) psiClass; + // In Java: ArrayList + // In Kotlin: ArrayList, not ArrayList + // nullability will be taken care of in individual member signatures + boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed); - PsiTypeParameterListOwner typeParameterListOwner = typeParameter.getOwner(); - if (typeParameterListOwner instanceof PsiMethod) { - PsiMethod psiMethod = (PsiMethod) typeParameterListOwner; - if (psiMethod.isConstructor()) { - Set supertypesJet = Sets.newHashSet(); - for (PsiClassType supertype : typeParameter.getExtendsListTypes()) { - supertypesJet.add(transformToType(JavaType.create(supertype), UPPER_BOUND, typeVariableResolver)); - } - JetType type = TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet); - if (type == null) { - return ErrorUtils.createErrorType("Unresolved java class: " + classType.getPresentableText()); - } - return type; - } - } + return TypeUtils.makeNullableIfNeeded(typeParameterDescriptor.getDefaultType(), nullable); + } - TypeParameterDescriptor typeParameterDescriptor = typeVariableResolver.getTypeVariable(typeParameter.getName()); + @Nullable + private JetType transformClassType( + @NotNull FqName fqName, + @NotNull JavaClassType classType, + @NotNull TypeUsage howThisTypeIsUsed, + @NotNull TypeVariableResolver typeVariableResolver + ) { + // 'L extends List' in Java is a List in Kotlin, not a List + boolean nullable = !EnumSet.of(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed); - // In Java: ArrayList - // In Kotlin: ArrayList, not ArrayList - // nullability will be taken care of in individual member signatures - boolean nullable = !EnumSet.of(TYPE_ARGUMENT, UPPER_BOUND, SUPERTYPE_ARGUMENT).contains(howThisTypeIsUsed); - if (nullable) { - return TypeUtils.makeNullable(typeParameterDescriptor.getDefaultType()); - } - else { - return typeParameterDescriptor.getDefaultType(); + ClassDescriptor classData = JavaToKotlinClassMap.getInstance().mapKotlinClass(fqName, howThisTypeIsUsed); + + if (classData == null) { + classData = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES); + } + if (classData == null) { + return null; + } + + List arguments = Lists.newArrayList(); + List parameters = classData.getTypeConstructor().getParameters(); + if (isRaw(classType, !parameters.isEmpty())) { + for (TypeParameterDescriptor parameter : parameters) { + // not making a star projection because of this case: + // Java: + // class C {} + // The upper bound is raw here, and we can't compute the projection: it would be infinite: + // C<*> = C>> + // this way we loose some type information, even when the case is not so bad, but it doesn't seem to matter + + // projections are not allowed in immediate arguments of supertypes + Variance projectionKind = parameter.getVariance() == OUT_VARIANCE || howThisTypeIsUsed == SUPERTYPE + ? INVARIANT + : OUT_VARIANCE; + arguments.add(new TypeProjection(projectionKind, KotlinBuiltIns.getInstance().getNullableAnyType())); } } else { - // 'L extends List' in Java is a List in Kotlin, not a List - boolean nullable = !EnumSet.of(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed); + PsiType[] psiArguments = classType.getPsi().getParameters(); - FqName fqName = javaClass.getFqName(); - assert fqName != null : "Class type should have a FQ name: " + javaClass; + if (parameters.size() != psiArguments.length) { + // Most of the time this means there is an error in the Java code + LOG.warn("parameters = " + parameters.size() + ", actual arguments = " + psiArguments.length + + " in " + classType.getPresentableText() + "\n fqName: \n" + fqName); - ClassDescriptor classData = JavaToKotlinClassMap.getInstance().mapKotlinClass(fqName, howThisTypeIsUsed); - - if (classData == null) { - classData = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES); - } - if (classData == null) { - return ErrorUtils.createErrorType("Unresolved java class: " + classType.getPresentableText()); - } - - List arguments = Lists.newArrayList(); - List parameters = classData.getTypeConstructor().getParameters(); - if (isRaw(classType, !parameters.isEmpty())) { for (TypeParameterDescriptor parameter : parameters) { - // not making a star projection because of this case: - // Java: - // class C {} - // The upper bound is raw here, and we can't compute the projection: it would be infinite: - // C<*> = C>> - // this way we loose some type information, even when the case is not so bad, but it doesn't seem to matter - - // projections are not allowed in immediate arguments of supertypes - Variance projectionKind = parameter.getVariance() == OUT_VARIANCE || howThisTypeIsUsed == SUPERTYPE - ? INVARIANT - : OUT_VARIANCE; - arguments.add(new TypeProjection(projectionKind, KotlinBuiltIns.getInstance().getNullableAnyType())); + arguments.add(new TypeProjection(ErrorUtils.createErrorType(parameter.getName().asString()))); } } else { - PsiType[] psiArguments = classType.getPsi().getParameters(); + for (int i = 0; i < parameters.size(); i++) { + PsiType psiArgument = psiArguments[i]; + TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); - if (parameters.size() != psiArguments.length) { - // Most of the time this means there is an error in the Java code - LOG.warn("parameters = " + parameters.size() + ", actual arguments = " + psiArguments.length + - " in " + classType.getPresentableText() + "\n PsiClass: \n" + psiClass.getText()); + TypeUsage howTheProjectionIsUsed = howThisTypeIsUsed == SUPERTYPE ? SUPERTYPE_ARGUMENT : TYPE_ARGUMENT; + TypeProjection typeProjection = transformToTypeProjection( + JavaType.create(psiArgument), typeParameterDescriptor, typeVariableResolver, + howTheProjectionIsUsed); - for (TypeParameterDescriptor parameter : parameters) { - arguments.add(new TypeProjection(ErrorUtils.createErrorType(parameter.getName().asString()))); + if (typeProjection.getProjectionKind() == typeParameterDescriptor.getVariance()) { + // remove redundant 'out' and 'in' + arguments.add(new TypeProjection(INVARIANT, typeProjection.getType())); } - } - else { - for (int i = 0; i < parameters.size(); i++) { - PsiType psiArgument = psiArguments[i]; - TypeParameterDescriptor typeParameterDescriptor = parameters.get(i); - - TypeUsage howTheProjectionIsUsed = howThisTypeIsUsed == SUPERTYPE ? SUPERTYPE_ARGUMENT : TYPE_ARGUMENT; - TypeProjection typeProjection = transformToTypeProjection( - JavaType.create(psiArgument), typeParameterDescriptor, typeVariableResolver, - howTheProjectionIsUsed); - - if (typeProjection.getProjectionKind() == typeParameterDescriptor.getVariance()) { - // remove redundant 'out' and 'in' - arguments.add(new TypeProjection(INVARIANT, typeProjection.getType())); - } - else { - arguments.add(typeProjection); - } + else { + arguments.add(typeProjection); } } } - - return new JetTypeImpl( - Collections.emptyList(), - classData.getTypeConstructor(), - nullable, - arguments, - classData.getMemberScope(arguments)); } + + return new JetTypeImpl( + Collections.emptyList(), + classData.getTypeConstructor(), + nullable, + arguments, + classData.getMemberScope(arguments)); } @NotNull 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 99e3eb1fa99..6b4c71c6b6a 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 @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmByte import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesUtil; import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.java.structure.JavaClassType; +import org.jetbrains.jet.lang.resolve.java.structure.JavaClassifier; 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; @@ -378,10 +379,12 @@ public class SingleAbstractMethodUtils { private boolean find(@NotNull JavaClassType classType) { PsiClassType.ClassResolveResult classResolveResult = classType.getPsi().resolveGenerics(); PsiSubstitutor classSubstitutor = classResolveResult.getSubstitutor(); - JavaClass javaClass = classType.resolve(); - if (javaClass == null) { + JavaClassifier javaClassifier = classType.resolve(); + if (javaClassifier == null) { return false; // can't resolve class -> not a SAM interface } + assert javaClassifier instanceof JavaClass : "Classifier should be a class here: " + javaClassifier; + JavaClass javaClass = (JavaClass) javaClassifier; if (new FqName(CommonClassNames.JAVA_LANG_OBJECT).equals(javaClass.getFqName())) { return true; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/scope/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/scope/JavaPackageScope.java index b36949fc1dc..612bda75993 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/scope/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/scope/JavaPackageScope.java @@ -97,7 +97,7 @@ public final class JavaPackageScope extends JavaBaseScope { } for (JavaClass javaClass : DescriptorResolverUtils.filterDuplicateClasses(javaPackage.getClasses())) { - if (DescriptorResolverUtils.isCompiledKotlinPackageClass(javaClass)) continue; + if (DescriptorResolverUtils.isCompiledKotlinPackageClass(javaClass.getPsi())) continue; if (isKotlinLightClass(javaClass)) continue; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java index 8ebbaf3e638..8b97125f72f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClass.java @@ -19,11 +19,13 @@ package org.jetbrains.jet.lang.resolve.java.structure; import com.intellij.psi.PsiAnnotation; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiModifierList; +import com.intellij.psi.PsiTypeParameter; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.Modality; +import org.jetbrains.jet.lang.descriptors.Visibility; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; @@ -31,15 +33,11 @@ import java.util.Collection; import static org.jetbrains.jet.lang.resolve.java.structure.JavaElementCollectionFromPsiArrayUtil.*; -public class JavaClass extends JavaModifierListOwnerImpl implements JavaNamedElement, JavaTypeParameterListOwner { +public class JavaClass extends JavaClassifier implements JavaNamedElement, JavaTypeParameterListOwner, JavaModifierListOwner { public JavaClass(@NotNull PsiClass psiClass) { super(psiClass); - } - - @NotNull - @Override - public PsiClass getPsi() { - return (PsiClass) super.getPsi(); + assert !(psiClass instanceof PsiTypeParameter) + : "PsiTypeParameter should be wrapped in JavaTypeParameter, not JavaClass: use JavaClassifier.create()"; } @NotNull @@ -136,4 +134,31 @@ public class JavaClass extends JavaModifierListOwnerImpl implements JavaNamedEle public Collection getConstructors() { return methods(getPsi().getConstructors()); } + + @Override + public boolean isAbstract() { + return JavaElementUtil.isAbstract(this); + } + + @Override + public boolean isStatic() { + return JavaElementUtil.isStatic(this); + } + + @Override + public boolean isFinal() { + return JavaElementUtil.isFinal(this); + } + + @NotNull + @Override + public Visibility getVisibility() { + return JavaElementUtil.getVisibility(this); + } + + @NotNull + @Override + public Collection getAnnotations() { + return JavaElementUtil.getAnnotations(this); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassType.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassType.java index 491b592792f..ba9f4f9c028 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassType.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassType.java @@ -39,9 +39,9 @@ public class JavaClassType extends JavaType { } @Nullable - public JavaClass resolve() { + public JavaClassifier resolve() { PsiClass psiClass = getPsi().resolve(); - return psiClass == null ? null : new JavaClass(psiClass); + return psiClass == null ? null : JavaClassifier.create(psiClass); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassifier.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassifier.java new file mode 100644 index 00000000000..187e9c2a5c6 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassifier.java @@ -0,0 +1,43 @@ +/* + * 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.PsiClass; +import com.intellij.psi.PsiTypeParameter; +import org.jetbrains.annotations.NotNull; + +public abstract class JavaClassifier extends JavaElementImpl { + protected JavaClassifier(@NotNull PsiClass psiClass) { + super(psiClass); + } + + @NotNull + @Override + public PsiClass getPsi() { + return (PsiClass) super.getPsi(); + } + + @NotNull + public static JavaClassifier create(@NotNull PsiClass psiClass) { + if (psiClass instanceof PsiTypeParameter) { + return new JavaTypeParameter((PsiTypeParameter) psiClass); + } + else { + return new JavaClass(psiClass); + } + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwnerImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementUtil.java similarity index 54% rename from compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwnerImpl.java rename to compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementUtil.java index aebabfd0234..3bf0167e759 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwnerImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementUtil.java @@ -18,7 +18,6 @@ package org.jetbrains.jet.lang.resolve.java.structure; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiModifierList; -import com.intellij.psi.PsiModifierListOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.Visibilities; import org.jetbrains.jet.lang.descriptors.Visibility; @@ -29,51 +28,39 @@ import java.util.Collections; import static org.jetbrains.jet.lang.resolve.java.structure.JavaElementCollectionFromPsiArrayUtil.annotations; -public abstract class JavaModifierListOwnerImpl extends JavaElementImpl implements JavaModifierListOwner { - protected JavaModifierListOwnerImpl(@NotNull PsiModifierListOwner psiModifierListOwner) { - super(psiModifierListOwner); +/* package */ class JavaElementUtil { + private JavaElementUtil() { + } + + public static boolean isAbstract(@NotNull JavaModifierListOwner owner) { + return owner.getPsi().hasModifierProperty(PsiModifier.ABSTRACT); + } + + public static boolean isStatic(@NotNull JavaModifierListOwner owner) { + return owner.getPsi().hasModifierProperty(PsiModifier.STATIC); + } + + public static boolean isFinal(@NotNull JavaModifierListOwner owner) { + return owner.getPsi().hasModifierProperty(PsiModifier.FINAL); } @NotNull - @Override - public PsiModifierListOwner getPsi() { - return (PsiModifierListOwner) super.getPsi(); - } - - @Override - public boolean isAbstract() { - return getPsi().hasModifierProperty(PsiModifier.ABSTRACT); - } - - @Override - public boolean isStatic() { - return getPsi().hasModifierProperty(PsiModifier.STATIC); - } - - @Override - public boolean isFinal() { - return getPsi().hasModifierProperty(PsiModifier.FINAL); - } - - @NotNull - @Override - public Visibility getVisibility() { - if (getPsi().hasModifierProperty(PsiModifier.PUBLIC)) { + public static Visibility getVisibility(@NotNull JavaModifierListOwner owner) { + if (owner.getPsi().hasModifierProperty(PsiModifier.PUBLIC)) { return Visibilities.PUBLIC; } - if (getPsi().hasModifierProperty(PsiModifier.PRIVATE)) { + if (owner.getPsi().hasModifierProperty(PsiModifier.PRIVATE)) { return Visibilities.PRIVATE; } - if (getPsi().hasModifierProperty(PsiModifier.PROTECTED)) { - return isStatic() ? JavaVisibilities.PROTECTED_STATIC_VISIBILITY : JavaVisibilities.PROTECTED_AND_PACKAGE; + if (owner.getPsi().hasModifierProperty(PsiModifier.PROTECTED)) { + return owner.isStatic() ? JavaVisibilities.PROTECTED_STATIC_VISIBILITY : JavaVisibilities.PROTECTED_AND_PACKAGE; } return JavaVisibilities.PACKAGE_VISIBILITY; } @NotNull - @Override - public Collection getAnnotations() { - PsiModifierList modifierList = getPsi().getModifierList(); + public static Collection getAnnotations(@NotNull JavaModifierListOwner owner) { + PsiModifierList modifierList = owner.getPsi().getModifierList(); if (modifierList != null) { return annotations(modifierList.getAnnotations()); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaField.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaField.java index 00e78c18a37..bdea076189d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaField.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaField.java @@ -16,11 +16,9 @@ package org.jetbrains.jet.lang.resolve.java.structure; -import com.intellij.psi.PsiClass; import com.intellij.psi.PsiEnumConstant; import com.intellij.psi.PsiField; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public class JavaField extends JavaMemberImpl { public JavaField(@NotNull PsiField psiField) { @@ -33,13 +31,6 @@ public class JavaField extends JavaMemberImpl { return (PsiField) super.getPsi(); } - @Nullable - @Override - public JavaClass getContainingClass() { - PsiClass psiClass = getPsi().getContainingClass(); - return psiClass == null ? null : new JavaClass(psiClass); - } - public boolean isEnumEntry() { return getPsi() instanceof PsiEnumConstant; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMemberImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMemberImpl.java index 21d8dfd7653..9277c7c6ff0 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMemberImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMemberImpl.java @@ -16,11 +16,16 @@ package org.jetbrains.jet.lang.resolve.java.structure; +import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMember; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.Visibility; import org.jetbrains.jet.lang.resolve.name.Name; -public abstract class JavaMemberImpl extends JavaModifierListOwnerImpl implements JavaMember { +import java.util.Collection; + +public abstract class JavaMemberImpl extends JavaElementImpl implements JavaMember, JavaModifierListOwner { protected JavaMemberImpl(@NotNull PsiMember psiMember) { super(psiMember); } @@ -38,4 +43,39 @@ public abstract class JavaMemberImpl extends JavaModifierListOwnerImpl implement assert name != null : "Member must have a name: " + getPsi(); return Name.identifier(name); } + + // TODO: NotNull? + @Nullable + @Override + public JavaClass getContainingClass() { + PsiClass psiClass = getPsi().getContainingClass(); + return psiClass == null ? null : new JavaClass(psiClass); + } + + @Override + public boolean isAbstract() { + return JavaElementUtil.isAbstract(this); + } + + @Override + public boolean isStatic() { + return JavaElementUtil.isStatic(this); + } + + @Override + public boolean isFinal() { + return JavaElementUtil.isFinal(this); + } + + @NotNull + @Override + public Visibility getVisibility() { + return JavaElementUtil.getVisibility(this); + } + + @NotNull + @Override + public Collection getAnnotations() { + return JavaElementUtil.getAnnotations(this); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMethod.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMethod.java index 60675098dba..ca695bf71e1 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMethod.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaMethod.java @@ -17,7 +17,6 @@ package org.jetbrains.jet.lang.resolve.java.structure; import com.intellij.psi.PsiAnnotationMethod; -import com.intellij.psi.PsiClass; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; @@ -46,14 +45,6 @@ public class JavaMethod extends JavaMemberImpl implements JavaTypeParameterListO return Name.identifier(getPsi().getName()); } - // TODO: NotNull? - @Nullable - @Override - public JavaClass getContainingClass() { - PsiClass psiClass = getPsi().getContainingClass(); - return psiClass == null ? null : new JavaClass(psiClass); - } - @NotNull @Override public Collection getTypeParameters() { @@ -83,4 +74,9 @@ public class JavaMethod extends JavaMemberImpl implements JavaTypeParameterListO public boolean isVararg() { return getPsi().isVarArgs(); } + + public boolean isConstructor() { + // TODO: class JavaConstructor extends JavaMethod + return getPsi().isConstructor(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwner.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwner.java index fa51410262a..f508497dab1 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwner.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaModifierListOwner.java @@ -16,12 +16,17 @@ package org.jetbrains.jet.lang.resolve.java.structure; +import com.intellij.psi.PsiModifierListOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.lang.descriptors.Visibility; import java.util.Collection; public interface JavaModifierListOwner extends JavaElement { + @NotNull + @Override + PsiModifierListOwner getPsi(); + boolean isAbstract(); boolean isStatic(); 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 67129603884..b1fea7354ea 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 @@ -16,15 +16,19 @@ package org.jetbrains.jet.lang.resolve.java.structure; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiTypeParameter; +import com.intellij.psi.PsiTypeParameterListOwner; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.name.Name; import java.util.Collection; import static org.jetbrains.jet.lang.resolve.java.structure.JavaElementCollectionFromPsiArrayUtil.classTypes; -public class JavaTypeParameter extends JavaElementImpl implements JavaNamedElement { +public class JavaTypeParameter extends JavaClassifier implements JavaNamedElement { public JavaTypeParameter(@NotNull PsiTypeParameter psiTypeParameter) { super(psiTypeParameter); } @@ -49,4 +53,21 @@ public class JavaTypeParameter extends JavaElementImpl implements JavaNamedEleme public Collection getUpperBounds() { return classTypes(getPsi().getExtendsList().getReferencedTypes()); } + + @Nullable + public JavaTypeParameterListOwner getOwner() { + PsiTypeParameterListOwner owner = getPsi().getOwner(); + // TODO: a separate factory for such things + if (owner instanceof PsiMethod) { + return new JavaMethod((PsiMethod) owner); + } + else if (owner instanceof PsiClass) { + return new JavaClass((PsiClass) owner); + } + else if (owner != null) { + throw new UnsupportedOperationException("Unsupported type parameter list owner: " + owner); + } + + return null; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java index 92b4831a0a3..59cb0c1e830 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java @@ -30,7 +30,6 @@ import org.jetbrains.jet.descriptors.serialization.*; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; import org.jetbrains.jet.lang.resolve.java.resolver.KotlinClassFileHeader; -import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.util.QualifiedNamesUtil; @@ -139,7 +138,7 @@ public class JetFromJavaDescriptorHelper { FqName classFQN = new FqName(qualifiedName); - if (DescriptorResolverUtils.isCompiledKotlinPackageClass(new JavaClass(containingClass))) { + if (DescriptorResolverUtils.isCompiledKotlinPackageClass(containingClass)) { FqName classParentFQN = QualifiedNamesUtil.withoutLastSegment(classFQN); return QualifiedNamesUtil.combine(classParentFQN, Name.identifier(method.getName())); } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java index d9b34800bed..5c051a6dd4f 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/DescriptorLookupConverter.java @@ -33,7 +33,6 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; -import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.lazy.KotlinCodeAnalyzer; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; @@ -130,14 +129,14 @@ public final class DescriptorLookupConverter { private static LookupElement createJavaLookupElementIfPossible(@NotNull PsiElement declaration, @NotNull DeclarationDescriptor descriptor) { if (declaration instanceof PsiClass) { PsiClass psiClass = (PsiClass) declaration; - if (!DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(new JavaClass(psiClass))) { + if (!DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(psiClass)) { return setCustomInsertHandler(new JavaPsiClassReferenceElement(psiClass)); } } if (declaration instanceof PsiMember) { PsiClass containingClass = ((PsiMember) declaration).getContainingClass(); - if (containingClass != null && !DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(new JavaClass(containingClass))) { + if (containingClass != null && !DescriptorResolverUtils.isCompiledKotlinClassOrPackageClass(containingClass)) { if (declaration instanceof PsiMethod) { InsertHandler handler = getInsertHandler(descriptor); assert handler != null: "Special kotlin handler is expected for function: " + declaration.getText() + " and descriptor" + DescriptorRenderer.TEXT.render(descriptor); diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java b/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java index f1f4ec69b31..c6e5867491d 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java @@ -27,7 +27,6 @@ import org.jetbrains.jet.asJava.KotlinLightClass; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; -import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; @@ -93,7 +92,7 @@ public class JetTypesCompletionHelper { return true; } - if (DescriptorResolverUtils.isCompiledKotlinClass(new JavaClass(aClass))) { + if (DescriptorResolverUtils.isCompiledKotlinClass(aClass)) { if (JetFromJavaDescriptorHelper.getCompiledClassKind(aClass) != ClassKind.CLASS_OBJECT) { String qualifiedName = aClass.getQualifiedName(); if (qualifiedName != null) { diff --git a/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java b/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java index a0e06e63333..5976d749118 100644 --- a/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java +++ b/idea/src/org/jetbrains/jet/plugin/editor/importOptimizer/JetImportOptimizer.java @@ -32,7 +32,6 @@ import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; -import org.jetbrains.jet.lang.resolve.java.structure.JavaClass; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; import org.jetbrains.jet.lang.resolve.name.Name; @@ -284,7 +283,7 @@ public class JetImportOptimizer implements ImportOptimizer { if (memberName == null) { return null; } - if (DescriptorResolverUtils.isCompiledKotlinPackageClass(new JavaClass(containingClass))) { + if (DescriptorResolverUtils.isCompiledKotlinPackageClass(containingClass)) { return QualifiedNamesUtil.combine(classFQN.parent(), Name.identifier(memberName)); } else {