Support enums in Java code
This commit is contained in:
+29
-4
@@ -28,6 +28,12 @@ import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod
|
||||
import org.jetbrains.jet.lang.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.jet.lang.types.TypeUtils
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaClassDescriptor
|
||||
import org.jetbrains.kotlin.util.iif
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaEnumClassObjectDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.Modality
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl
|
||||
import org.jetbrains.jet.lang.resolve.scopes.RedeclarationHandler
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope
|
||||
|
||||
class LazyJavaClassDescriptor(
|
||||
private val c: LazyJavaResolverContextWithTypes,
|
||||
@@ -62,12 +68,31 @@ class LazyJavaClassDescriptor(
|
||||
|
||||
override fun getUnsubstitutedPrimaryConstructor(): ConstructorDescriptor? = null
|
||||
|
||||
private val _classObjectDescriptor = c.storageManager.createNullableLazyValue {
|
||||
if (jClass.isEnum()) {
|
||||
val classObject = JavaEnumClassObjectDescriptor(this)
|
||||
classObject.setModality(Modality.FINAL)
|
||||
classObject.setVisibility(jClass.getVisibility())
|
||||
classObject.setTypeParameterDescriptors(Collections.emptyList<TypeParameterDescriptor>())
|
||||
classObject.createTypeConstructor()
|
||||
|
||||
val scope = LazyJavaClassMemberScope(innerC, classObject, jClass, enumClassObject = true)
|
||||
val writableScope = WritableScopeImpl(scope, classObject, RedeclarationHandler.THROW_EXCEPTION, "Enum class object scope")
|
||||
writableScope.changeLockLevel(WritableScope.LockLevel.BOTH)
|
||||
|
||||
classObject.setScopeForMemberLookup(writableScope)
|
||||
|
||||
JavaClassResolver.createEnumSyntheticMethods(classObject, this.getDefaultType())
|
||||
|
||||
classObject
|
||||
}
|
||||
else null
|
||||
}
|
||||
override fun getClassObjectDescriptor(): ClassDescriptor? = _classObjectDescriptor()
|
||||
override fun getClassObjectType(): JetType? = getClassObjectDescriptor()?.let { d -> d.getDefaultType() }
|
||||
|
||||
override fun getConstructors() = _scopeForMemberLookup._constructors()
|
||||
|
||||
override fun getClassObjectType(): JetType? = null
|
||||
|
||||
override fun getClassObjectDescriptor(): ClassDescriptor? = null
|
||||
|
||||
private val _annotations = c.storageManager.createLazyValue { c.resolveAnnotations(jClass.getAnnotations()) }
|
||||
override fun getAnnotations(): List<AnnotationDescriptor> = _annotations()
|
||||
|
||||
|
||||
+17
-28
@@ -17,49 +17,38 @@
|
||||
package org.jetbrains.jet.lang.resolve.java.lazy.descriptors
|
||||
|
||||
import org.jetbrains.jet.lang.descriptors.*
|
||||
import org.jetbrains.jet.storage.NotNullLazyValue
|
||||
import org.jetbrains.jet.lang.resolve.name.LabelName
|
||||
import org.jetbrains.jet.lang.resolve.name.Name
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope
|
||||
import org.jetbrains.jet.utils.emptyList
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaField
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.LazyJavaResolverContextWithTypes
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaMethodDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.child
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.resolveAnnotations
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaArrayType
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.TypeUsage
|
||||
import org.jetbrains.jet.lang.types.TypeUtils
|
||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.hasNotNullAnnotation
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.types.LazyJavaTypeAttributes
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.hasMutableAnnotation
|
||||
import org.jetbrains.kotlin.util.iif
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.hasReadOnlyAnnotation
|
||||
import org.jetbrains.jet.utils.valuesToMap
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ConstructorDescriptorImpl
|
||||
import java.util.Collections
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver
|
||||
import org.jetbrains.jet.utils.*
|
||||
import java.util.ArrayList
|
||||
import org.jetbrains.jet.lang.resolve.java.lazy.types.toAttributes
|
||||
import org.jetbrains.jet.lang.types.JetType
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.DescriptorResolverUtils
|
||||
import org.jetbrains.jet.lang.resolve.java.structure.JavaMember
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils
|
||||
import org.jetbrains.jet.lang.descriptors.impl.EnumEntrySyntheticClassDescriptor
|
||||
import org.jetbrains.jet.storage.get
|
||||
|
||||
public class LazyJavaClassMemberScope(
|
||||
c: LazyJavaResolverContextWithTypes,
|
||||
containingDeclaration: LazyJavaClassDescriptor,
|
||||
private val jClass: JavaClass
|
||||
containingDeclaration: ClassDescriptor,
|
||||
private val jClass: JavaClass,
|
||||
private val enumClassObject: Boolean = false
|
||||
) : LazyJavaMemberScope(c, containingDeclaration) {
|
||||
|
||||
override fun computeMemberIndex(): MemberIndex = object : ClassMemberIndex(jClass, { m -> !m.isStatic() }) {
|
||||
// For SAM-constructors
|
||||
override fun getAllMetodNames(): Collection<Name> = super.getAllMetodNames() + getAllClassNames()
|
||||
override fun computeMemberIndex(): MemberIndex {
|
||||
return object : ClassMemberIndex(jClass, { !enumClassObject && !it.isStatic() }) {
|
||||
// For SAM-constructors
|
||||
override fun getAllMetodNames(): Collection<Name> = super.getAllMetodNames() + getAllClassNames()
|
||||
}
|
||||
}
|
||||
|
||||
internal val _constructors = c.storageManager.createLazyValue {
|
||||
@@ -165,10 +154,10 @@ public class LazyJavaClassMemberScope(
|
||||
if (jNestedClass == null)
|
||||
null
|
||||
else
|
||||
LazyJavaClassDescriptor(c, getContainingDeclaration(), getContainingDeclaration().fqName.child(name), jNestedClass)
|
||||
LazyJavaClassDescriptor(c, getContainingDeclaration(), jNestedClass.getFqName()!!, jNestedClass)
|
||||
}
|
||||
|
||||
override fun getClassifier(name: Name): ClassifierDescriptor? = nestedClasses(name)
|
||||
override fun getClassifier(name: Name): ClassifierDescriptor? = if (enumClassObject) null else nestedClasses(name)
|
||||
override fun getAllClassNames(): Collection<Name> = nestedClassIndex().keySet()
|
||||
|
||||
override fun addExtraDescriptors(result: MutableCollection<in DeclarationDescriptor>) {
|
||||
@@ -179,8 +168,8 @@ public class LazyJavaClassMemberScope(
|
||||
override fun getImplicitReceiversHierarchy(): List<ReceiverParameterDescriptor> = listOf()
|
||||
|
||||
|
||||
override fun getContainingDeclaration(): LazyJavaClassDescriptor {
|
||||
return super.getContainingDeclaration() as LazyJavaClassDescriptor
|
||||
override fun getContainingDeclaration(): ClassDescriptor {
|
||||
return super.getContainingDeclaration() as ClassDescriptor
|
||||
}
|
||||
|
||||
// namespaces should be resolved elsewhere
|
||||
|
||||
+51
-17
@@ -41,6 +41,8 @@ import org.jetbrains.annotations.TestOnly
|
||||
import org.jetbrains.jet.utils.Printer
|
||||
import org.jetbrains.jet.lang.resolve.java.resolver.ExternalSignatureResolver
|
||||
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.JavaPropertyDescriptorForObject
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl
|
||||
|
||||
public abstract class LazyJavaMemberScope(
|
||||
protected val c: LazyJavaResolverContextWithTypes,
|
||||
@@ -67,15 +69,19 @@ public abstract class LazyJavaMemberScope(
|
||||
(name: Name): Collection<FunctionDescriptor>
|
||||
->
|
||||
val methods = memberIndex().findMethodsByName(name)
|
||||
val functions = LinkedHashSet(methods.flatMap {
|
||||
m ->
|
||||
val function = resolveMethodToFunctionDescriptor(m, true)
|
||||
val samAdapter = JavaFunctionResolver.resolveSamAdapter(function)
|
||||
if (samAdapter != null)
|
||||
listOf(function, samAdapter)
|
||||
else
|
||||
listOf(function)
|
||||
})
|
||||
val functions = LinkedHashSet(
|
||||
methods.iterator()
|
||||
// values() and valueOf() are added manually, see LazyJavaClassDescriptor::getClassObjectDescriptor()
|
||||
.filter{ m -> !DescriptorResolverUtils.shouldBeInEnumClassObject(m) }
|
||||
.flatMap {
|
||||
m ->
|
||||
val function = resolveMethodToFunctionDescriptor(m, true)
|
||||
val samAdapter = JavaFunctionResolver.resolveSamAdapter(function)
|
||||
if (samAdapter != null)
|
||||
listOf(function, samAdapter).iterator()
|
||||
else
|
||||
listOf(function).iterator()
|
||||
}.toList())
|
||||
|
||||
if (_containingDeclaration is NamespaceDescriptor) {
|
||||
val klass = JavaFunctionResolver.findClassInNamespace(_containingDeclaration, name);
|
||||
@@ -211,7 +217,9 @@ public abstract class LazyJavaMemberScope(
|
||||
|
||||
val field = memberIndex().findFieldByName(name)
|
||||
if (field != null) {
|
||||
properties.add(resolveProperty(field))
|
||||
if (DescriptorResolverUtils.shouldBeInEnumClassObject(field) == DescriptorUtils.isEnumClassObject(_containingDeclaration)) {
|
||||
properties.add(resolveProperty(field))
|
||||
}
|
||||
}
|
||||
|
||||
if (_containingDeclaration is ClassDescriptor) {
|
||||
@@ -227,13 +235,7 @@ public abstract class LazyJavaMemberScope(
|
||||
|
||||
private fun resolveProperty(field: JavaField): PropertyDescriptor {
|
||||
val isVar = !field.isFinal()
|
||||
val propertyDescriptor = JavaPropertyDescriptor(
|
||||
getContainingDeclaration(),
|
||||
c.resolveAnnotations(field.getAnnotations()),
|
||||
field.getVisibility(),
|
||||
isVar,
|
||||
field.getName()
|
||||
)
|
||||
val propertyDescriptor = createPropertyDescriptor(field)
|
||||
propertyDescriptor.initialize(null, null)
|
||||
|
||||
val propertyType = getPropertyType(field)
|
||||
@@ -250,6 +252,38 @@ public abstract class LazyJavaMemberScope(
|
||||
return propertyDescriptor
|
||||
}
|
||||
|
||||
private fun createPropertyDescriptor(field: JavaField): PropertyDescriptorImpl {
|
||||
val isVar = !field.isFinal()
|
||||
val visibility = field.getVisibility()
|
||||
val annotations = c.resolveAnnotations(field.getAnnotations())
|
||||
val propertyName = field.getName()
|
||||
|
||||
if (field.isEnumEntry()) {
|
||||
assert(!isVar, "Enum entries should be immutable.")
|
||||
assert(DescriptorUtils.isEnumClassObject(_containingDeclaration), "Enum entries should be put into class object of enum only: " + _containingDeclaration)
|
||||
//TODO: this is a hack to indicate that this enum entry is an object
|
||||
// class descriptor for enum entries is not used by backends so for now this should be safe to use
|
||||
val dummyClassDescriptorForEnumEntryObject = ClassDescriptorImpl(_containingDeclaration, Collections.emptyList(), Modality.FINAL, propertyName)
|
||||
dummyClassDescriptorForEnumEntryObject.initialize(
|
||||
true,
|
||||
Collections.emptyList(),
|
||||
Collections.emptyList(),
|
||||
JetScope.EMPTY,
|
||||
Collections.emptySet(),
|
||||
null,
|
||||
false)
|
||||
return JavaPropertyDescriptorForObject(
|
||||
_containingDeclaration as ClassDescriptor,
|
||||
annotations,
|
||||
visibility,
|
||||
propertyName,
|
||||
dummyClassDescriptorForEnumEntryObject
|
||||
)
|
||||
}
|
||||
|
||||
return JavaPropertyDescriptor(_containingDeclaration, annotations, visibility, isVar, propertyName)
|
||||
}
|
||||
|
||||
private fun getPropertyType(field: JavaField): JetType {
|
||||
// Fields do not have their own generic parameters
|
||||
val propertyType = c.typeResolver.transformJavaType(field.getType(), LazyJavaTypeAttributes(c, field, TypeUsage.MEMBER_SIGNATURE_INVARIANT))
|
||||
|
||||
+2
-2
@@ -305,7 +305,7 @@ public final class JavaClassResolver {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static FqNameUnsafe getFqNameForClassObject(@NotNull JavaClass javaClass) {
|
||||
public static FqNameUnsafe getFqNameForClassObject(@NotNull JavaClass javaClass) {
|
||||
FqName fqName = javaClass.getFqName();
|
||||
assert fqName != null : "Reading java class with no qualified name";
|
||||
return fqName.toUnsafe().child(getClassObjectName(javaClass.getName()));
|
||||
@@ -414,7 +414,7 @@ public final class JavaClassResolver {
|
||||
return javaClass.getOuterClass() != null && !javaClass.isStatic();
|
||||
}
|
||||
|
||||
private static void createEnumSyntheticMethods(@NotNull JavaEnumClassObjectDescriptor classObject, @NotNull JetType enumType) {
|
||||
public static void createEnumSyntheticMethods(@NotNull JavaEnumClassObjectDescriptor classObject, @NotNull JetType enumType) {
|
||||
JetType valuesReturnType = KotlinBuiltIns.getInstance().getArrayType(enumType);
|
||||
SimpleFunctionDescriptor valuesMethod = DescriptorFactory.createEnumClassObjectValuesMethod(classObject, valuesReturnType);
|
||||
classObject.getBuilder().addFunctionDescriptor(valuesMethod);
|
||||
|
||||
Reference in New Issue
Block a user