Support loading Java records

^KT-43677 In Progress
This commit is contained in:
Denis.Zharkov
2020-11-23 16:02:26 +03:00
parent f25b7672a7
commit 513f7177ca
45 changed files with 688 additions and 61 deletions
@@ -23,19 +23,18 @@ import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.load.java.structure.JavaClass
import org.jetbrains.kotlin.load.java.structure.JavaElement
import org.jetbrains.kotlin.load.java.structure.JavaField
import org.jetbrains.kotlin.load.java.structure.JavaMethod
import org.jetbrains.kotlin.load.java.structure.JavaMember
import org.jetbrains.kotlin.load.java.structure.impl.JavaClassImpl
import org.jetbrains.kotlin.load.java.structure.impl.JavaElementImpl
import org.jetbrains.kotlin.load.java.structure.impl.JavaFieldImpl
import org.jetbrains.kotlin.load.java.structure.impl.JavaMethodImpl
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.BindingContextUtils
import org.jetbrains.kotlin.resolve.lazy.ResolveSession
class LazyResolveBasedCache(resolveSession: ResolveSession) : AbstractJavaResolverCache(resolveSession) {
override fun recordMethod(method: JavaMethod, descriptor: SimpleFunctionDescriptor) {
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, (method as? JavaMethodImpl)?.psi ?: return, descriptor)
override fun recordMethod(member: JavaMember, descriptor: SimpleFunctionDescriptor) {
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, (member as? JavaElementImpl<*>)?.psi ?: return, descriptor)
}
override fun recordConstructor(element: JavaElement, descriptor: ConstructorDescriptor) {
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.name.Name;
@NotNull Kind kind,
@NotNull JavaMethodDescriptor declaration
) {
super(containingDeclaration, original, declaration.getAnnotations(), declaration.getName(), kind, declaration.getSource());
super(containingDeclaration, original, declaration.getAnnotations(), declaration.getName(), kind, declaration.getSource(), false);
this.declaration = declaration;
setParameterNamesStatus(declaration.hasStableParameterNames(), declaration.hasSynthesizedParameterNames());
}
@@ -88,7 +88,8 @@ public class SignaturesPropagationData {
Annotations.Companion.getEMPTY(),
method.getName(),
//TODO: what to do?
SourceElement.NO_SOURCE
SourceElement.NO_SOURCE,
false
);
autoMethodDescriptor.initialize(
null,
@@ -27,6 +27,8 @@ import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.incremental.record
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.DescriptorUtils
@@ -113,20 +115,37 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
}
private fun syntheticPropertyInClassNotCached(ownerClass: ClassDescriptor, name: Name): SyntheticPropertyHolder {
val forBean = syntheticPropertyHolderForBeanConvention(name, ownerClass)
if (forBean.descriptor != null) return forBean
fun result(descriptor: PropertyDescriptor?, getterNames: List<Name>, setterName: Name? = null): SyntheticPropertyHolder {
if (lookupTracker === LookupTracker.DO_NOTHING) {
return if (descriptor == null) SyntheticPropertyHolder.EMPTY else SyntheticPropertyHolder(descriptor, emptyList())
}
if (!ownerClass.isRecord()) return forBean
val names = ArrayList<Name>(getterNames.size + (setterName?.let { 1 } ?: 0))
val propertyForComponent = syntheticPropertyDescriptorForRecordComponent(name, ownerClass)
names.addAll(getterNames)
names.addIfNotNull(setterName)
return createSyntheticPropertyHolder(propertyForComponent, forBean.lookedNames, name)
}
return SyntheticPropertyHolder(descriptor, names)
private fun createSyntheticPropertyHolder(
descriptor: PropertyDescriptor?,
lookedNames: List<Name>,
additionalName: Name? = null
): SyntheticPropertyHolder {
if (lookupTracker === LookupTracker.DO_NOTHING) {
return if (descriptor == null) SyntheticPropertyHolder.EMPTY else SyntheticPropertyHolder(descriptor, emptyList())
}
val names = ArrayList<Name>(lookedNames.size + (additionalName?.let { 1 } ?: 0))
names.addAll(lookedNames)
names.addIfNotNull(additionalName)
return SyntheticPropertyHolder(descriptor, names)
}
private fun syntheticPropertyHolderForBeanConvention(
name: Name,
ownerClass: ClassDescriptor
): SyntheticPropertyHolder {
if (name.isSpecial) return SyntheticPropertyHolder.EMPTY
val identifier = name.identifier
@@ -142,7 +161,7 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
.flatMap { memberScope.getContributedFunctions(it, NoLookupLocation.FROM_SYNTHETIC_SCOPE) }
.singleOrNull {
it.hasJavaOriginInHierarchy() && isGoodGetMethod(it)
} ?: return result(null, possibleGetMethodNames)
} ?: return createSyntheticPropertyHolder(null, possibleGetMethodNames)
val setMethodName = setMethodName(getMethod.name)
@@ -152,7 +171,25 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
val propertyType = getMethod.returnType!!
val descriptor = MyPropertyDescriptor.create(ownerClass, getMethod.original, setMethod?.original, name, propertyType)
return result(descriptor, possibleGetMethodNames, setMethodName)
return createSyntheticPropertyHolder(descriptor, possibleGetMethodNames, setMethodName)
}
private fun syntheticPropertyDescriptorForRecordComponent(
name: Name,
ownerClass: ClassDescriptor
): PropertyDescriptor? {
val componentLikeMethod =
ownerClass.unsubstitutedMemberScope
.getContributedFunctions(name, NoLookupLocation.FROM_SYNTHETIC_SCOPE)
.singleOrNull(this::isGoodGetMethod) ?: return null
if (componentLikeMethod !is JavaMethodDescriptor || !componentLikeMethod.isForRecordComponent) {
return null
}
val propertyType = componentLikeMethod.returnType!!
return MyPropertyDescriptor.create(ownerClass, componentLikeMethod.original, null, name, propertyType)
}
private fun isGoodGetMethod(descriptor: FunctionDescriptor): Boolean {
@@ -249,8 +286,14 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
if (classifier is ClassDescriptor) {
for (descriptor in classifier.unsubstitutedMemberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)) {
if (descriptor is FunctionDescriptor) {
val propertyName = SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(descriptor.getName()) ?: continue
addIfNotNull(syntheticPropertyInClass(Pair(classifier, propertyName)).descriptor)
val propertyName = SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(descriptor.getName())
if (propertyName != null) {
addIfNotNull(syntheticPropertyInClass(Pair(classifier, propertyName)).descriptor)
}
if (classifier.isRecord()) {
addIfNotNull(syntheticPropertyInClass(Pair(classifier, descriptor.name)).descriptor)
}
}
}
} else {
@@ -258,6 +301,9 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
}
}
private fun ClassifierDescriptor.isRecord() =
this is JavaClassDescriptor && isRecord
private fun SmartList<PropertyDescriptor>?.add(property: PropertyDescriptor?): SmartList<PropertyDescriptor>? {
if (property == null) return this
val list = if (this != null) this else SmartList()
@@ -280,15 +326,15 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
}
private class MyPropertyDescriptor(
containingDeclaration: DeclarationDescriptor,
original: PropertyDescriptor?,
annotations: Annotations,
modality: Modality,
visibility: DescriptorVisibility,
isVar: Boolean,
name: Name,
kind: CallableMemberDescriptor.Kind,
source: SourceElement
containingDeclaration: DeclarationDescriptor,
original: PropertyDescriptor?,
annotations: Annotations,
modality: Modality,
visibility: DescriptorVisibility,
isVar: Boolean,
name: Name,
kind: CallableMemberDescriptor.Kind,
source: SourceElement
) : SyntheticJavaPropertyDescriptor, PropertyDescriptorImpl(
containingDeclaration, original, annotations, modality, visibility, isVar, name, kind, source,
/* lateInit = */ false, /* isConst = */ false, /* isExpect = */ false, /* isActual = */ false, /* isExternal = */ false,
@@ -374,13 +420,13 @@ class JavaSyntheticPropertiesScope(storageManager: StorageManager, private val l
}
override fun createSubstitutedCopy(
newOwner: DeclarationDescriptor,
newModality: Modality,
newVisibility: DescriptorVisibility,
original: PropertyDescriptor?,
kind: CallableMemberDescriptor.Kind,
newName: Name,
source: SourceElement
newOwner: DeclarationDescriptor,
newModality: Modality,
newVisibility: DescriptorVisibility,
original: PropertyDescriptor?,
kind: CallableMemberDescriptor.Kind,
newName: Name,
source: SourceElement
): PropertyDescriptorImpl {
return MyPropertyDescriptor(newOwner, this, annotations, newModality, newVisibility, isVar, newName, kind, this.source).apply {
getMethod = this@MyPropertyDescriptor.getMethod