Support KPackage.members, functions and properties

This commit is contained in:
Alexander Udalov
2015-07-15 23:50:45 +03:00
parent 95be8b11f5
commit 93656c93c1
11 changed files with 184 additions and 72 deletions
@@ -0,0 +1,23 @@
import kotlin.reflect.*
import kotlin.reflect.jvm.*
import kotlin.test.assertEquals
fun foo() {}
fun Int.bar() {}
val baz = 42
val Int.quux: Int get() = this
fun box(): String {
fun check(actual: Collection<KCallable<*>>, expected: Set<String>) {
assertEquals(expected, actual.map { it.name }.toSet())
}
val kp = Class.forName("_DefaultPackage").kotlinPackage ?: return "Fail: package class not found"
check(kp.members, setOf("bar", "baz", "foo", "box", "quux"))
check(kp.functions, setOf("bar", "foo", "box"))
check(kp.properties, setOf("baz"))
check(kp.extensionProperties, setOf("quux"))
return "OK"
}
@@ -3214,6 +3214,21 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
}
}
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/packages")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Packages extends AbstractBlackBoxCodegenTest {
public void testAllFilesPresentInPackages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/packages"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("simpleGetMembers.kt")
public void testSimpleGetMembers() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/packages/simpleGetMembers.kt");
doTestWithStdlib(fileName);
}
}
@TestMetadata("compiler/testData/codegen/boxWithStdlib/reflection/parameters")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
+1 -1
View File
@@ -42,7 +42,7 @@ public interface KClass<T> : KDeclarationContainer {
* All functions and properties accessible in this class, including those declared in this class
* and all of its superclasses. Does not include constructors.
*/
public val members: Collection<KCallable<*>>
override val members: Collection<KCallable<*>>
/**
* All constructors declared in this class.
@@ -20,4 +20,9 @@ package kotlin.reflect
* Represents an entity which may contain declarations of any other entities,
* such as a class or a package.
*/
public interface KDeclarationContainer
public interface KDeclarationContainer {
/**
* All functions and properties accessible in this container.
*/
public val members: Collection<KCallable<*>>
}
@@ -18,17 +18,6 @@ package kotlin.reflect
import kotlin.reflect.jvm.internal.KClassImpl
/**
* Returns all functions declared in this class and all of its superclasses.
* If this is a Java class, it includes all non-static methods declared in the class and the superclasses,
* as well as static methods declared in the class.
*/
public val <T> KClass<T>.functions: Collection<KFunction<*>>
get() = (this as KClassImpl<T>)
.getMembers(declaredOnly = false, nonExtensions = true, extensions = true)
.filterIsInstance<KFunction<*>>()
.toList()
/**
* Returns all functions declared in this class.
* If this is a Java class, it includes both non-static and static methods.
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2015 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 kotlin.reflect
import kotlin.reflect.jvm.internal.KCallableContainerImpl
/**
* Returns all functions declared in this container.
* If this container is a Java class, it includes all non-static methods declared in the class
* and the superclasses, as well as static methods declared in the class.
*/
public val KDeclarationContainer.functions: Collection<KFunction<*>>
get() = (this as KCallableContainerImpl)
.getMembers(declaredOnly = false, nonExtensions = true, extensions = true)
.filterIsInstance<KFunction<*>>()
.toList()
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2015 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 kotlin.reflect
import kotlin.reflect.jvm.internal.KPackageImpl
/**
* Returns all non-extension properties declared in this package.
*/
public val KPackage.properties: Collection<KProperty0<*>>
get() = (this as KPackageImpl)
.getMembers(declaredOnly = false, nonExtensions = true, extensions = false)
.filterIsInstance<KProperty0<*>>()
.toList()
/**
* Returns all extension properties declared in this package.
*/
public val KPackage.extensionProperties: Collection<KProperty1<*, *>>
get() = (this as KPackageImpl)
.getMembers(declaredOnly = false, nonExtensions = false, extensions = true)
.filterIsInstance<KProperty1<*, *>>()
.toList()
@@ -16,9 +16,8 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
import org.jetbrains.kotlin.load.java.structure.reflect.classId
import org.jetbrains.kotlin.load.java.structure.reflect.classLoader
import org.jetbrains.kotlin.load.java.structure.reflect.createArrayType
@@ -31,6 +30,7 @@ import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf
import org.jetbrains.kotlin.serialization.jvm.JvmProtoBuf.JvmType.PrimitiveType.*
import java.lang.reflect.Field
import java.lang.reflect.Method
import kotlin.reflect.KCallable
import kotlin.reflect.KDeclarationContainer
import kotlin.reflect.KotlinReflectionInternalError
@@ -46,6 +46,64 @@ abstract class KCallableContainerImpl : KDeclarationContainer {
abstract val constructorDescriptors: Collection<ConstructorDescriptor>
override val members: Collection<KCallable<*>>
get() = getMembers(declaredOnly = false, nonExtensions = true, extensions = true).toList()
fun getMembers(declaredOnly: Boolean, nonExtensions: Boolean, extensions: Boolean): Sequence<KCallable<*>> {
val visitor = object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Unit>() {
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
if (declaredOnly && !descriptor.getKind().isReal()) return true
val isExtension = descriptor.getExtensionReceiverParameter() != null
if (isExtension && !extensions) return true
if (!isExtension && !nonExtensions) return true
return false
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Unit): KCallable<*>? {
return if (skipCallable(descriptor)) null else createProperty(descriptor)
}
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Unit): KCallable<*>? {
return if (skipCallable(descriptor)) null else KFunctionImpl(this@KCallableContainerImpl, descriptor)
}
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Unit): KCallable<*>? {
throw IllegalStateException("No constructors should appear in this scope: $descriptor")
}
}
return scope.getAllDescriptors().asSequence()
.filter { descriptor ->
descriptor !is MemberDescriptor || descriptor.getVisibility() != Visibilities.INVISIBLE_FAKE
}
.map { descriptor ->
descriptor.accept(visitor, Unit)
}
.filterNotNull()
}
private fun createProperty(descriptor: PropertyDescriptor): KPropertyImpl<*> {
val receiverCount = (descriptor.dispatchReceiverParameter?.let { 1 } ?: 0) +
(descriptor.extensionReceiverParameter?.let { 1 } ?: 0)
when {
descriptor.isVar -> when (receiverCount) {
0 -> return KMutableProperty0Impl<Any?>(this, descriptor)
1 -> return KMutableProperty1Impl<Any?, Any?>(this, descriptor)
2 -> return KMutableProperty2Impl<Any?, Any?, Any?>(this, descriptor)
}
else -> when (receiverCount) {
0 -> return KProperty0Impl<Any?>(this, descriptor)
1 -> return KProperty1Impl<Any?, Any?>(this, descriptor)
2 -> return KProperty2Impl<Any?, Any?, Any?>(this, descriptor)
}
}
throw KotlinReflectionInternalError("Unsupported property: $descriptor")
}
fun findPropertyDescriptor(name: String, signature: String): PropertyDescriptor {
val properties = scope
.getProperties(Name.guess(name))
@@ -16,13 +16,12 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.DeclarationDescriptorVisitorEmptyBodies
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.resolve.scopes.ChainedScope
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.serialization.deserialization.findClassAcrossModuleDependencies
import kotlin.reflect.KCallable
import kotlin.reflect.KClass
import kotlin.reflect.KFunction
import kotlin.reflect.KotlinReflectionInternalError
@@ -84,61 +83,12 @@ class KClassImpl<T>(override val jClass: Class<T>) : KCallableContainerImpl(), K
}
}
override val members: Collection<KCallable<*>>
get() = getMembers(declaredOnly = false, nonExtensions = true, extensions = true).toList()
@suppress("UNCHECKED_CAST")
override val constructors: Collection<KFunction<T>>
get() = constructorDescriptors.map {
KFunctionImpl(this, it) as KFunction<T>
}
fun getMembers(declaredOnly: Boolean, nonExtensions: Boolean, extensions: Boolean): Sequence<KCallable<*>> {
val visitor = object : DeclarationDescriptorVisitorEmptyBodies<KCallable<*>?, Nothing>() {
private fun skipCallable(descriptor: CallableMemberDescriptor): Boolean {
if (declaredOnly && !descriptor.getKind().isReal()) return true
val isExtension = descriptor.getExtensionReceiverParameter() != null
if (isExtension && !extensions) return true
if (!isExtension && !nonExtensions) return true
return false
}
override fun visitPropertyDescriptor(descriptor: PropertyDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
return if (descriptor.getExtensionReceiverParameter() == null) {
if (descriptor.isVar()) KMutableProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
else KProperty1Impl<T, Any?>(this@KClassImpl, descriptor)
}
else {
if (descriptor.isVar()) KMutableProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
else KProperty2Impl<T, Any?, Any?>(this@KClassImpl, descriptor)
}
}
override fun visitFunctionDescriptor(descriptor: FunctionDescriptor, data: Nothing?): KCallable<*>? {
if (skipCallable(descriptor)) return null
return KFunctionImpl(this@KClassImpl, descriptor)
}
override fun visitConstructorDescriptor(descriptor: ConstructorDescriptor, data: Nothing?): KCallable<*>? {
throw IllegalStateException("No constructors should appear in this scope: $descriptor")
}
}
return scope.getAllDescriptors().asSequence()
.filter { descriptor ->
descriptor !is MemberDescriptor || descriptor.getVisibility() != Visibilities.INVISIBLE_FAKE
}
.map { descriptor ->
descriptor.accept(visitor, null)
}
.filterNotNull()
}
override fun equals(other: Any?): Boolean =
other is KClassImpl<*> && jClass == other.jClass
@@ -16,6 +16,7 @@
package kotlin.reflect.jvm.internal
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import java.lang.reflect.Method
import kotlin.jvm.internal.MutablePropertyReference0
import kotlin.jvm.internal.PropertyReference0
@@ -24,6 +25,8 @@ import kotlin.reflect.KMutableProperty0
import kotlin.reflect.KProperty0
open class KProperty0Impl<out R> : DescriptorBasedProperty<R>, KProperty0<R>, KPropertyImpl<R> {
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
constructor(container: KCallableContainerImpl, name: String, signature: String) : super(container, name, signature)
override val name: String get() = descriptor.getName().asString()
@@ -48,6 +51,8 @@ open class KProperty0Impl<out R> : DescriptorBasedProperty<R>, KProperty0<R>, KP
}
open class KMutableProperty0Impl<R> : KProperty0Impl<R>, KMutableProperty0<R>, KMutablePropertyImpl<R> {
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
constructor(container: KCallableContainerImpl, name: String, signature: String) : super(container, name, signature)
override val setter by ReflectProperties.lazy { Setter(this) }
@@ -24,9 +24,9 @@ import kotlin.reflect.KMutableProperty2
import kotlin.reflect.KProperty2
open class KProperty2Impl<D, E, out R> : DescriptorBasedProperty<R>, KProperty2<D, E, R>, KPropertyImpl<R> {
constructor(container: KClassImpl<D>, name: String, signature: String) : super(container, name, signature)
constructor(container: KCallableContainerImpl, name: String, signature: String) : super(container, name, signature)
constructor(container: KClassImpl<D>, descriptor: PropertyDescriptor) : super(container, descriptor)
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
override val name: String get() = descriptor.getName().asString()
@@ -53,9 +53,9 @@ open class KProperty2Impl<D, E, out R> : DescriptorBasedProperty<R>, KProperty2<
class KMutableProperty2Impl<D, E, R> : KProperty2Impl<D, E, R>, KMutableProperty2<D, E, R>, KMutablePropertyImpl<R> {
constructor(container: KClassImpl<D>, name: String, signature: String) : super(container, name, signature)
constructor(container: KCallableContainerImpl, name: String, signature: String) : super(container, name, signature)
constructor(container: KClassImpl<D>, descriptor: PropertyDescriptor) : super(container, descriptor)
constructor(container: KCallableContainerImpl, descriptor: PropertyDescriptor) : super(container, descriptor)
override val setter by ReflectProperties.lazy { Setter(this) }