Resolve functions in packages loaded from Java classes

This commit is contained in:
Andrey Breslav
2013-10-23 14:36:25 +04:00
parent eb56550c54
commit 297bfd2903
5 changed files with 142 additions and 102 deletions
@@ -53,7 +53,7 @@ class LazyJavaClassDescriptor(
private val _typeConstructor = c.storageManager.createLazyValue { LazyJavaClassTypeConstructor() }
override fun getTypeConstructor(): TypeConstructor = _typeConstructor()
private val _scopeForMemberLookup = LazyJavaClassMemberScope(innerC, this, jClass, false)
private val _scopeForMemberLookup = LazyJavaClassMemberScope(innerC, this, jClass)
override fun getScopeForMemberLookup() = _scopeForMemberLookup
private val _thisAsReceiverParameter = c.storageManager.createLazyValue { DescriptorFactory.createLazyReceiverParameterDescriptor(this) }
@@ -54,101 +54,10 @@ import org.jetbrains.jet.lang.types.JetType
public class LazyJavaClassMemberScope(
c: LazyJavaResolverContextWithTypes,
containingDeclaration: LazyJavaClassDescriptor,
private val jClass: JavaClass,
classAsPackage: Boolean
private val jClass: JavaClass
) : LazyJavaMemberScope(c, containingDeclaration) {
private val methodIndex = c.storageManager.createLazyValue {
jClass.getMethods().iterator().filter { m -> m.isStatic() == classAsPackage && !m.isConstructor() }.groupBy { m -> m.getName() }
}
private val _functions = c.storageManager.createMemoizedFunction {
(name: Name): Collection<FunctionDescriptor>
->
val methods = methodIndex()[name] ?: listOf()
val functions = methods.map {
method ->
val function = JavaMethodDescriptor(
containingDeclaration,
c.resolveAnnotations(method.getAnnotations()),
name
)
val innerC = c.child(function, method.getTypeParameters().toSet())
val valueParameters = resolveValueParameters(innerC, function, method.getValueParameters())
val returnTypeAttrs = LazyJavaTypeAttributes(c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT) {
if (method.hasReadOnlyAnnotation() && !method.hasMutableAnnotation())
TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
else
TypeUsage.MEMBER_SIGNATURE_COVARIANT
}
function.initialize(
null,
DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration),
method.getTypeParameters().map { p -> innerC.typeParameterResolver.resolveTypeParameter(p) },
valueParameters,
c.typeResolver.transformJavaType(method.getReturnType()!!, returnTypeAttrs),
Modality.convertFromFlags(method.isAbstract(), !method.isFinal()),
method.getVisibility(),
false
)
function
}
// Make sure that lazy things are computed before we release the lock
for (f in functions) {
for (p in f.getValueParameters()) {
p.hasDefaultValue()
}
}
functions
}
override fun getFunctions(name: Name) = _functions(name)
override fun getAllFunctionNames(): Collection<Name> = methodIndex().keySet()
private fun resolveValueParameters(
innerC: LazyJavaResolverContextWithTypes,
function: FunctionDescriptor,
jValueParameters: List<JavaValueParameter>
): List<ValueParameterDescriptor> {
return jValueParameters.withIndices().map {
pair ->
val (index, javaParameter) = pair
val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_COVARIANT) {
javaParameter.hasMutableAnnotation().iif(TypeUsage.MEMBER_SIGNATURE_COVARIANT, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT)
}
val (outType, varargElementType) =
if (javaParameter.isVararg()) {
val paramType = javaParameter.getType()
assert (paramType is JavaArrayType, "Vararg parameter should be an array: $paramType")
val arrayType = c.typeResolver.transformArrayType(paramType as JavaArrayType, typeUsage, true)
val outType = TypeUtils.makeNotNullable(arrayType)
Pair(outType, KotlinBuiltIns.getInstance().getArrayElementType(outType))
}
else {
val jetType = c.typeResolver.transformJavaType(javaParameter.getType(), typeUsage)
if (jetType.isNullable() && javaParameter.hasNotNullAnnotation())
Pair(TypeUtils.makeNotNullable(jetType), null)
else Pair(jetType, null)
}
ValueParameterDescriptorImpl(
function,
index,
innerC.resolveAnnotations(javaParameter.getAnnotations()),
// TODO: parameter names may be drawn from attached sources, which is slow; it's better to make them lazy
javaParameter.getName() ?: Name.identifier("p$index"),
outType,
false,
varargElementType
)
}.toList()
}
override fun computeMemberIndex(): MemberIndex = ClassMemberIndex(jClass, mustBeStatic = false)
internal val _constructors = c.storageManager.createLazyValue {
jClass.getConstructors().map {
@@ -24,6 +24,7 @@ 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.lang.resolve.java.structure.JavaValueParameter
import org.jetbrains.jet.lang.resolve.java.lazy.LazyJavaResolverContext
import org.jetbrains.annotations.TestOnly
import org.jetbrains.jet.utils.Printer
@@ -36,6 +37,99 @@ public abstract class LazyJavaMemberScope(
override fun getContainingDeclaration() = _containingDeclaration
private val memberIndex = c.storageManager.createLazyValue {
computeMemberIndex()
}
protected abstract fun computeMemberIndex(): MemberIndex
private val _functions = c.storageManager.createMemoizedFunction {
(name: Name): Collection<FunctionDescriptor>
->
val methods = memberIndex().findMethodsByName(name)
val functions = methods.map {
method ->
val function = JavaMethodDescriptor(
_containingDeclaration,
c.resolveAnnotations(method.getAnnotations()),
name
)
val innerC = c.child(function, method.getTypeParameters().toSet())
val valueParameters = resolveValueParameters(innerC, function, method.getValueParameters())
val returnTypeAttrs = LazyJavaTypeAttributes(c, method, TypeUsage.MEMBER_SIGNATURE_COVARIANT) {
if (method.hasReadOnlyAnnotation() && !method.hasMutableAnnotation())
TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT
else
TypeUsage.MEMBER_SIGNATURE_COVARIANT
}
function.initialize(
null,
DescriptorUtils.getExpectedThisObjectIfNeeded(_containingDeclaration),
method.getTypeParameters().map { p -> innerC.typeParameterResolver.resolveTypeParameter(p) },
valueParameters,
c.typeResolver.transformJavaType(method.getReturnType()!!, returnTypeAttrs),
Modality.convertFromFlags(method.isAbstract(), !method.isFinal()),
method.getVisibility(),
false
)
function
}
// Make sure that lazy things are computed before we release the lock
for (f in functions) {
for (p in f.getValueParameters()) {
p.hasDefaultValue()
}
}
functions
}
protected fun resolveValueParameters(
c: LazyJavaResolverContextWithTypes,
function: FunctionDescriptor,
jValueParameters: List<JavaValueParameter>
): List<ValueParameterDescriptor> {
return jValueParameters.withIndices().map {
pair ->
val (index, javaParameter) = pair
val typeUsage = LazyJavaTypeAttributes(c, javaParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT) {
javaParameter.hasMutableAnnotation().iif(TypeUsage.MEMBER_SIGNATURE_COVARIANT, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT)
}
val (outType, varargElementType) =
if (javaParameter.isVararg()) {
val paramType = javaParameter.getType()
assert (paramType is JavaArrayType, "Vararg parameter should be an array: $paramType")
val arrayType = c.typeResolver.transformArrayType(paramType as JavaArrayType, typeUsage, true)
val outType = TypeUtils.makeNotNullable(arrayType)
Pair(outType, KotlinBuiltIns.getInstance().getArrayElementType(outType))
}
else {
val jetType = c.typeResolver.transformJavaType(javaParameter.getType(), typeUsage)
if (jetType.isNullable() && javaParameter.hasNotNullAnnotation())
Pair(TypeUtils.makeNotNullable(jetType), null)
else Pair(jetType, null)
}
ValueParameterDescriptorImpl(
function,
index,
c.resolveAnnotations(javaParameter.getAnnotations()),
// TODO: parameter names may be drawn from attached sources, which is slow; it's better to make them lazy
javaParameter.getName() ?: Name.identifier("p$index"),
outType,
false,
varargElementType
)
}.toList()
}
override fun getFunctions(name: Name) = _functions(name)
protected open fun getAllFunctionNames(): Collection<Name> = memberIndex().getAllMetodNames()
// No object can be defined in Java
override fun getObjectDescriptor(name: Name): ClassDescriptor? = null
override fun getObjectDescriptors() = emptyList<ClassDescriptor>()
@@ -75,7 +169,6 @@ public abstract class LazyJavaMemberScope(
protected abstract fun getAllPackageNames(): Collection<Name>
protected abstract fun getAllClassNames(): Collection<Name>
protected abstract fun getAllPropertyNames(): Collection<Name>
protected abstract fun getAllFunctionNames(): Collection<Name>
protected abstract fun addExtraDescriptors(result: MutableCollection<in DeclarationDescriptor>)
override fun toString() = "Lazy scope for ${getContainingDeclaration()}"
@@ -48,6 +48,8 @@ public class LazyPackageFragmentScopeForJavaPackage(
packageFragment: LazyJavaPackageFragment
) : LazyJavaPackageFragmentScope(c, packageFragment) {
override fun computeMemberIndex(): MemberIndex = EMPTY_MEMBER_INDEX
override fun getAllClassNames(): Collection<Name> {
val javaPackage = c.finder.findPackage(fqName)
assert(javaPackage != null) { "Package not found: $fqName" }
@@ -63,9 +65,6 @@ public class LazyPackageFragmentScopeForJavaPackage(
override fun getProperties(name: Name): Collection<VariableDescriptor> = Collections.emptyList()
override fun getAllPropertyNames() = Collections.emptyList<Name>()
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = Collections.emptyList()
override fun getAllFunctionNames() = Collections.emptyList<Name>()
}
public class LazyPackageFragmentScopeForJavaClass(
@@ -74,6 +73,8 @@ public class LazyPackageFragmentScopeForJavaClass(
packageFragment: LazyJavaPackageFragment
) : LazyJavaPackageFragmentScope(c, packageFragment) {
override fun computeMemberIndex(): MemberIndex = ClassMemberIndex(jClass, mustBeStatic = true)
override fun getAllClassNames(): Collection<Name> = listOf() // nested classes are loaded as members of their outer classes, not packages
override fun getAllPackageNames(): Collection<Name> = jClass.getInnerClasses().iterator()
.filter { c -> c.isStatic() && JavaNamespaceResolver.hasStaticMembers(c) }
@@ -82,8 +83,4 @@ public class LazyPackageFragmentScopeForJavaClass(
// TODO
override fun getProperties(name: Name): Collection<VariableDescriptor> = Collections.emptyList()
override fun getAllPropertyNames() = Collections.emptyList<Name>()
// TODO
override fun getFunctions(name: Name): Collection<FunctionDescriptor> = Collections.emptyList()
override fun getAllFunctionNames() = Collections.emptyList<Name>()
}
@@ -0,0 +1,41 @@
/*
* 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.lazy.descriptors
import org.jetbrains.jet.lang.resolve.name.Name
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass
trait MemberIndex {
fun findMethodsByName(name: Name): Collection<JavaMethod>
fun getAllMetodNames(): Collection<Name>
}
object EMPTY_MEMBER_INDEX : MemberIndex {
override fun findMethodsByName(name: Name) = listOf<JavaMethod>()
override fun getAllMetodNames() = listOf<Name>()
}
class ClassMemberIndex(jClass: JavaClass, mustBeStatic: Boolean) : MemberIndex {
private val methods = jClass.getMethods().iterator().filter { m -> m.isStatic() == mustBeStatic && !m.isConstructor() }.groupBy { m -> m.getName() }
override fun findMethodsByName(name: Name): Collection<JavaMethod> {
return methods[name] ?: listOf()
}
override fun getAllMetodNames(): Collection<Name> = methods.keySet()
}