Use descriptors for reflection on class properties

- use ConcurrentHashMap as a cache of class loaders to module descriptors
- KClassImpl now has a lazy class descriptor and it manages property creation
  by looking (also lazily) for the property descriptor in the corresponding
  scope
- since deserialized descriptors have full information about where a JVM symbol
  is located and what signature it has, new tests will begin to pass where
  Kotlin model and Java reflection model differ, see classObjectVar.kt
This commit is contained in:
Alexander Udalov
2015-02-19 17:27:58 +03:00
parent ba0ea1515b
commit 64fdb18ad3
11 changed files with 409 additions and 73 deletions
@@ -21,7 +21,9 @@ import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.load.java.JavaVisibilities
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.FqNameUnsafe
import org.jetbrains.kotlin.name.Name
import java.lang.reflect.Array
import java.lang.reflect.Modifier
private fun calculateVisibility(modifiers: Int): Visibility {
@@ -34,6 +36,9 @@ private fun calculateVisibility(modifiers: Int): Visibility {
}
}
public val Class<*>.classLoader: ClassLoader
get() = getClassLoader() ?: ClassLoader.getSystemClassLoader()
public fun Class<*>.isEnumClassOrSpecializedEnumEntryClass(): Boolean =
javaClass<Enum<*>>().isAssignableFrom(this)
@@ -41,4 +46,15 @@ public val Class<*>.fqName: FqName
get() = classId.asSingleFqName().toSafe()
public val Class<*>.classId: ClassId
get() = getDeclaringClass()?.classId?.createNestedClassId(Name.identifier(getSimpleName())) ?: ClassId.topLevel(FqName(getName()))
get() = when {
isPrimitive() -> throw IllegalArgumentException("Can't compute ClassId for primitive type: $this")
isArray() -> throw IllegalArgumentException("Can't compute ClassId for array type: $this")
getEnclosingMethod() != null, getEnclosingConstructor() != null, getSimpleName().isEmpty() -> {
val fqName = FqName(getName())
ClassId(fqName.parent(), FqNameUnsafe.topLevel(fqName.shortName()), /* local = */ true)
}
else -> getDeclaringClass()?.classId?.createNestedClassId(Name.identifier(getSimpleName())) ?: ClassId.topLevel(FqName(getName()))
}
public fun Class<*>.createArrayType(): Class<*> =
Array.newInstance(this, 0).javaClass