Introduce JavaClassifier

JavaClassifier is a common type for JavaClass and JavaTypeParameter. In almost
all of the places JavaClass remains to be JavaClass, except for the resolution
result of JavaClassType, which can be a type parameter. Add an assertion that
JavaClass is created only for a class and not for a type parameter. Delete
different creations of JavaClass in 'idea' (where there can be a type
parameter) by changing the interface of util functions.

Delete JavaModifierListOwnerImpl, extract its methods into JavaElementUtil and
use these implementations for every JavaModifierListOwner

Continue refactoring JavaTypeTransformer to work with JavaType, not PsiType
This commit is contained in:
Alexander Udalov
2013-07-31 17:33:46 +04:00
parent 787d8a5234
commit c1d40f1e15
19 changed files with 303 additions and 181 deletions
@@ -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
@@ -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<JavaClass> classes = DescriptorResolverUtils.filterDuplicateClasses(javaPackage.getClasses());
List<Name> result = new ArrayList<Name>(classes.size());
for (JavaClass javaClass : classes) {
if (DescriptorResolverUtils.isCompiledKotlinClass(javaClass)) {
if (DescriptorResolverUtils.isCompiledKotlinClass(javaClass.getPsi())) {
result.add(javaClass.getName());
}
}
@@ -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<JetType> result = new ArrayList<JetType>(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;
@@ -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<JetType> 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<T>
// In Kotlin: ArrayList<T>, not ArrayList<T?>
// 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<JetType> 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<T>' in Java is a List<T> in Kotlin, not a List<T?>
boolean nullable = !EnumSet.of(TYPE_ARGUMENT, SUPERTYPE_ARGUMENT, SUPERTYPE).contains(howThisTypeIsUsed);
// In Java: ArrayList<T>
// In Kotlin: ArrayList<T>, not ArrayList<T?>
// 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<TypeProjection> arguments = Lists.newArrayList();
List<TypeParameterDescriptor> 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<T extends C> {}
// The upper bound is raw here, and we can't compute the projection: it would be infinite:
// C<*> = C<out C<out 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<T>' in Java is a List<T> in Kotlin, not a List<T?>
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<TypeProjection> arguments = Lists.newArrayList();
List<TypeParameterDescriptor> 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<T extends C> {}
// The upper bound is raw here, and we can't compute the projection: it would be infinite:
// C<*> = C<out C<out 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.<AnnotationDescriptor>emptyList(),
classData.getTypeConstructor(),
nullable,
arguments,
classData.getMemberScope(arguments));
}
return new JetTypeImpl(
Collections.<AnnotationDescriptor>emptyList(),
classData.getTypeConstructor(),
nullable,
arguments,
classData.getMemberScope(arguments));
}
@NotNull
@@ -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;
}
@@ -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;
@@ -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<JavaMethod> 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<JavaAnnotation> getAnnotations() {
return JavaElementUtil.getAnnotations(this);
}
}
@@ -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
@@ -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);
}
}
}
@@ -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<JavaAnnotation> getAnnotations() {
PsiModifierList modifierList = getPsi().getModifierList();
public static Collection<JavaAnnotation> getAnnotations(@NotNull JavaModifierListOwner owner) {
PsiModifierList modifierList = owner.getPsi().getModifierList();
if (modifierList != null) {
return annotations(modifierList.getAnnotations());
}
@@ -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;
}
@@ -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<JavaAnnotation> getAnnotations() {
return JavaElementUtil.getAnnotations(this);
}
}
@@ -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<JavaTypeParameter> 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();
}
}
@@ -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();
@@ -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<JavaClassType> 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;
}
}