diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt index 5c451f766a2fbb5e49cd28477fb11dc4b03eb0de..4ba81f70b4680508ba39af15f9985a073838cc8e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/components/LazyResolveBasedCache.kt @@ -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) { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamAdapterFunctionDescriptor.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamAdapterFunctionDescriptor.java index ab67df6b4affb75c57dc877fe7618e2c89d2d3a7..d53a2d8ded8050bf81a48fbcae1d93c00f83083d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamAdapterFunctionDescriptor.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/sam/SamAdapterFunctionDescriptor.java @@ -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()); } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java index f7384b77a96c5b1de120af67c3d3b967812a33ea..bb1f88ff226da4921ef4abe6030e96b6264d98bd 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/kotlinSignature/SignaturesPropagationData.java @@ -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, diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt index fe9441cbfe0e99b68c367a49fb4be21eac9bd8a0..972a38d8f0135b0a5dc29db96eabcadb64e16f40 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/synthetic/JavaSyntheticPropertiesScope.kt @@ -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, 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(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, + additionalName: Name? = null + ): SyntheticPropertyHolder { + if (lookupTracker === LookupTracker.DO_NOTHING) { + return if (descriptor == null) SyntheticPropertyHolder.EMPTY else SyntheticPropertyHolder(descriptor, emptyList()) } + val names = ArrayList(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?.add(property: PropertyDescriptor?): SmartList? { 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 diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/components/StubJavaResolverCache.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/components/StubJavaResolverCache.kt index 904d7dfa2163a207112b1f39c43a3d76e8e64301..1af897ee21059331904233b823feb28875840df9 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/components/StubJavaResolverCache.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/components/StubJavaResolverCache.kt @@ -24,12 +24,12 @@ import org.jetbrains.kotlin.load.java.components.AbstractJavaResolverCache 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.resolve.lazy.ResolveSession class StubJavaResolverCache(resolveSession: ResolveSession) : AbstractJavaResolverCache(resolveSession) { - override fun recordMethod(method: JavaMethod, descriptor: SimpleFunctionDescriptor) {} + override fun recordMethod(member: JavaMember, descriptor: SimpleFunctionDescriptor) {} override fun recordConstructor(element: JavaElement, descriptor: ConstructorDescriptor) {} @@ -37,4 +37,4 @@ class StubJavaResolverCache(resolveSession: ResolveSession) : AbstractJavaResolv override fun recordClass(javaClass: JavaClass, descriptor: ClassDescriptor) {} -} \ No newline at end of file +} diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/resolve/KotlinClassifiersCache.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/resolve/KotlinClassifiersCache.kt index 7703b7cddb73f20c49308594b8e946f17283df8d..dbf128ce3d63ba6263022e74f238041647939138 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/resolve/KotlinClassifiersCache.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/resolve/KotlinClassifiersCache.kt @@ -157,9 +157,12 @@ class MockKotlinClassifier(override val classId: ClassId, override val isInterface get() = shouldNotBeCalled() override val isAnnotationType get() = shouldNotBeCalled() override val isEnum get() = shouldNotBeCalled() + override val isRecord get() = shouldNotBeCalled() override val methods get() = shouldNotBeCalled() override val fields get() = shouldNotBeCalled() override val constructors get() = shouldNotBeCalled() + override val recordComponents get() = shouldNotBeCalled() + override fun hasDefaultConstructor() = shouldNotBeCalled() override val annotations get() = shouldNotBeCalled() override val isDeprecatedInJavaDoc get() = shouldNotBeCalled() diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/FakeSymbolBasedClass.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/FakeSymbolBasedClass.kt index 0a6ad55ad9ee7240a2158e2e5d2f71d8b434beff..a1c37ddff5b435c5c54086154a500c6fb9464f0d 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/FakeSymbolBasedClass.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/FakeSymbolBasedClass.kt @@ -65,6 +65,9 @@ class FakeSymbolBasedClass( override val isEnum: Boolean get() = false + override val isRecord: Boolean get() = false + + override val recordComponents: Collection get() = emptyList() override val lightClassOriginKind: LightClassOriginKind? get() = null override val methods: Collection get() = emptyList() diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedClass.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedClass.kt index 2366edc88d93e2e2ad8deeb5e6e23b8f74f0bf0d..e731f775ec9f885e7f07a2394083dae463ba45c9 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedClass.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/symbols/SymbolBasedClass.kt @@ -133,6 +133,12 @@ class SymbolBasedClass( .filter { it.kind == ElementKind.CONSTRUCTOR } .map { SymbolBasedConstructor(it as ExecutableElement, this, javac) } + override val isRecord: Boolean + get() = false + + override val recordComponents: Collection + get() = emptyList() + override fun hasDefaultConstructor() = false // default constructors are explicit in symbols override val innerClassNames: Collection diff --git a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedClass.kt b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedClass.kt index 187811ccdabe07816113fa2954c644e30a4f2974..686ba9f020115aa5e0d666697fa26ebed87c1f61 100644 --- a/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedClass.kt +++ b/compiler/javac-wrapper/src/org/jetbrains/kotlin/javac/wrappers/trees/TreeBasedClass.kt @@ -114,6 +114,10 @@ class TreeBasedClass( override val isEnum: Boolean get() = tree.modifiers.flags and Flags.ENUM.toLong() != 0L + // TODO: Support + override val isRecord: Boolean + get() = false + override val lightClassOriginKind: LightClassOriginKind? get() = null @@ -134,6 +138,9 @@ class TreeBasedClass( TreeBasedConstructor(constructor as JCTree.JCMethodDecl, compilationUnit, this, javac) } + override val recordComponents: Collection + get() = emptyList() + override fun hasDefaultConstructor() = !isInterface && constructors.isEmpty() override val innerClassNames: Collection diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt index f5085cd102167efd3a3f6b7dc1dbcea95ff49e12..359e4e5a2dc2e67e2b60e01eb1e312d8d3837266 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassImpl.kt @@ -59,6 +59,9 @@ class JavaClassImpl(psiClass: PsiClass) : JavaClassifierImpl(psiClass) override val isEnum: Boolean get() = psi.isEnum + override val isRecord: Boolean + get() = psi.isRecord + override val outerClass: JavaClassImpl? get() { val outer = psi.containingClass @@ -100,6 +103,13 @@ class JavaClassImpl(psiClass: PsiClass) : JavaClassifierImpl(psiClass) return constructors(psi.constructors.filter { method -> method.isConstructor }) } + override val recordComponents: Collection + get() { + assertNotLightClass() + + return psi.recordComponents.convert(::JavaRecordComponentImpl) + } + override fun hasDefaultConstructor() = !isInterface && constructors.isEmpty() override val isAbstract: Boolean diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt index e793e0e6a014eafd677fbf1b5295ea5909ddc55b..3889abe9d17fca044aa745bf0e35391bb42e1f86 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaElementCollectionFromPsiArrayUtil.kt @@ -24,14 +24,14 @@ import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.name.Name -private inline fun Array.convert(factory: (Psi) -> Java): List = +inline fun Array.convert(factory: (Psi) -> Java): List = when (size) { 0 -> emptyList() 1 -> listOf(factory(first())) else -> map(factory) } -private fun Collection.convert(factory: (Psi) -> Java): List = +fun Collection.convert(factory: (Psi) -> Java): List = when (size) { 0 -> emptyList() 1 -> listOf(factory(first())) diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaRecordComponentImpl.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaRecordComponentImpl.kt new file mode 100644 index 0000000000000000000000000000000000000000..09e353cb50a900e0d9b7be5466137d8ad69735a2 --- /dev/null +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/JavaRecordComponentImpl.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.load.java.structure.impl + +import com.intellij.psi.PsiRecordComponent +import org.jetbrains.kotlin.load.java.structure.JavaRecordComponent +import org.jetbrains.kotlin.load.java.structure.JavaType + +class JavaRecordComponentImpl(psiRecordComponent: PsiRecordComponent) : JavaMemberImpl(psiRecordComponent), JavaRecordComponent { + override val type: JavaType + get() = JavaTypeImpl.create(psi.type) + + override val isVararg: Boolean + get() = psi.isVarArgs +} diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt index dba70a0a5bc8361da881fd3473daa364b1c76a07..73e75d17baabe411f0953b3220def648917ace2d 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/BinaryJavaClass.kt @@ -47,6 +47,8 @@ class BinaryJavaClass( override val methods = arrayListOf() override val fields = arrayListOf() override val constructors = arrayListOf() + override val recordComponents = arrayListOf() + override fun hasDefaultConstructor() = false // never: all constructors explicit in bytecode override val annotationsByFqName by buildLazyValueForMap() @@ -63,6 +65,9 @@ class BinaryJavaClass( override val isInterface get() = isSet(Opcodes.ACC_INTERFACE) override val isAnnotationType get() = isSet(Opcodes.ACC_ANNOTATION) override val isEnum get() = isSet(Opcodes.ACC_ENUM) + + override val isRecord get() = isSet(Opcodes.ACC_RECORD) + override val lightClassOriginKind: LightClassOriginKind? get() = null override fun isFromSourceCodeInScope(scope: SearchScope): Boolean = false @@ -184,6 +189,16 @@ class BinaryJavaClass( } } + + override fun visitRecordComponent(name: String, descriptor: String, signature: String?): RecordComponentVisitor? { + val type = signatureParser.parseTypeString(StringCharacterIterator(signature ?: descriptor), context) + // TODO: Read isVararg properly + val isVararg = false + recordComponents.add(BinaryJavaRecordComponent(Name.identifier(name), this, type, isVararg)) + + return null + } + /** * All the int-like values (including Char/Boolean) come in visitor as Integer instances */ diff --git a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt index 72fc2c3d979995fa38316e4a164605d9e11a74c1..9328dbcc8fa609079a9168f8513084681e64676e 100644 --- a/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt +++ b/compiler/resolution.common.jvm/src/org/jetbrains/kotlin/load/java/structure/impl/classFiles/Other.kt @@ -64,6 +64,22 @@ class BinaryJavaValueParameter( } } +class BinaryJavaRecordComponent( + override val name: Name, + override val containingClass: JavaClass, + override val type: JavaType, + override val isVararg: Boolean, +) : JavaRecordComponent, BinaryJavaModifierListOwner { + override val annotations: Collection + get() = emptyList() + + override val access: Int + get() = 0 + + override val annotationsByFqName: Map + get() = emptyMap() +} + fun isNotTopLevelClass(classContent: ByteArray): Boolean { var isNotTopLevelClass = false ClassReader(classContent).accept( diff --git a/compiler/testData/diagnostics/testsWithJava15/simpleRecords.kt b/compiler/testData/diagnostics/testsWithJava15/simpleRecords.kt new file mode 100644 index 0000000000000000000000000000000000000000..0517df7484f6e0e0fa6df42c4c092baf5ca52d7c --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava15/simpleRecords.kt @@ -0,0 +1,16 @@ +// FILE: MyRecord.java +public record MyRecord(int x, CharSequence y) { + +} + +// FILE: main.kt + +fun foo(mr: MyRecord) { + MyRecord(1, "") + + mr.x() + mr.y() + + mr.x + mr.y +} diff --git a/compiler/testData/diagnostics/testsWithJava15/simpleRecords.txt b/compiler/testData/diagnostics/testsWithJava15/simpleRecords.txt new file mode 100644 index 0000000000000000000000000000000000000000..b7fd8e172d0e59fdb9a2fe9c14f2e11a5df913d0 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithJava15/simpleRecords.txt @@ -0,0 +1,12 @@ +package + +public fun foo(/*0*/ mr: MyRecord): kotlin.Unit + +/*record*/ public final class MyRecord : java.lang.Record { + public constructor MyRecord(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.CharSequence!) + public abstract override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public abstract override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public abstract override /*1*/ /*fake_override*/ fun toString(): kotlin.String + /*record component*/ public open fun x(): kotlin.Int + /*record component*/ public open fun y(): kotlin.CharSequence! +} diff --git a/compiler/testData/loadJava15/GenericRecord.compiled.psi.txt b/compiler/testData/loadJava15/GenericRecord.compiled.psi.txt new file mode 100644 index 0000000000000000000000000000000000000000..f43c4c8da678183009a068b0c1cff5d19a4c072c --- /dev/null +++ b/compiler/testData/loadJava15/GenericRecord.compiled.psi.txt @@ -0,0 +1,11 @@ +package test + +public final class GenericRecord : java.lang.Record { + public constructor GenericRecord(/*0*/ x: T!, /*1*/ y: E!) + private final val x: T! + private final val y: E! + public open fun x(): T! + public open fun y(): E! + public open fun y(/*0*/ p0: E!): E! + public open fun z(): kotlin.Double +} diff --git a/compiler/testData/loadJava15/GenericRecord.compiled.txt b/compiler/testData/loadJava15/GenericRecord.compiled.txt new file mode 100644 index 0000000000000000000000000000000000000000..8b9536b6638b5671e17431326a7e332d3f2f08d2 --- /dev/null +++ b/compiler/testData/loadJava15/GenericRecord.compiled.txt @@ -0,0 +1,11 @@ +package test + +/*record*/ public final class GenericRecord : java.lang.Record { + public constructor GenericRecord(/*0*/ x: T!, /*1*/ y: E!) + private final val x: T! + private final val y: E! + /*record component*/ public open fun x(): T! + /*record component*/ public open fun y(): E! + public open fun y(/*0*/ p0: E!): E! + public open fun z(): kotlin.Double +} diff --git a/compiler/testData/loadJava15/GenericRecord.java b/compiler/testData/loadJava15/GenericRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..cf0ab9019113b44000374d492374d709fbcfcd43 --- /dev/null +++ b/compiler/testData/loadJava15/GenericRecord.java @@ -0,0 +1,6 @@ +package test; +public record GenericRecord(T x, E y) { + public E y() { return y; } + public E y(E n) { return y; } + public double z() { return 0.0; } +} diff --git a/compiler/testData/loadJava15/GenericRecord.txt b/compiler/testData/loadJava15/GenericRecord.txt new file mode 100644 index 0000000000000000000000000000000000000000..1d86e74f6112b9e6b47b8545887fcf6f73e995c1 --- /dev/null +++ b/compiler/testData/loadJava15/GenericRecord.txt @@ -0,0 +1,9 @@ +package test + +/*record*/ public final class GenericRecord : java.lang.Record { + public constructor GenericRecord(/*0*/ x: T!, /*1*/ y: E!) + /*record component*/ public open fun x(): T! + /*record component*/ public open fun y(): E! + public open fun y(/*0*/ n: E!): E! + public open fun z(): kotlin.Double +} diff --git a/compiler/testData/loadJava15/SimpleRecord.compiled.psi.txt b/compiler/testData/loadJava15/SimpleRecord.compiled.psi.txt new file mode 100644 index 0000000000000000000000000000000000000000..39fe6007beb815519ea7696f0a6fefe69d6a67dd --- /dev/null +++ b/compiler/testData/loadJava15/SimpleRecord.compiled.psi.txt @@ -0,0 +1,11 @@ +package test + +public final class SimpleRecord : java.lang.Record { + public constructor SimpleRecord(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.CharSequence!) + private final val x: kotlin.Int + private final val y: kotlin.CharSequence! + public open fun x(): kotlin.Int + public open fun y(): kotlin.CharSequence! + public open fun y(/*0*/ p0: kotlin.Int): kotlin.CharSequence! + public open fun z(): kotlin.Double +} diff --git a/compiler/testData/loadJava15/SimpleRecord.compiled.txt b/compiler/testData/loadJava15/SimpleRecord.compiled.txt new file mode 100644 index 0000000000000000000000000000000000000000..2698f4198429cc9548012488c5e2d64f55ddfd8e --- /dev/null +++ b/compiler/testData/loadJava15/SimpleRecord.compiled.txt @@ -0,0 +1,11 @@ +package test + +/*record*/ public final class SimpleRecord : java.lang.Record { + public constructor SimpleRecord(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.CharSequence!) + private final val x: kotlin.Int + private final val y: kotlin.CharSequence! + /*record component*/ public open fun x(): kotlin.Int + /*record component*/ public open fun y(): kotlin.CharSequence! + public open fun y(/*0*/ p0: kotlin.Int): kotlin.CharSequence! + public open fun z(): kotlin.Double +} diff --git a/compiler/testData/loadJava15/SimpleRecord.java b/compiler/testData/loadJava15/SimpleRecord.java new file mode 100644 index 0000000000000000000000000000000000000000..163ae7619e39218ff61c4ebd82ad55d540ddaf83 --- /dev/null +++ b/compiler/testData/loadJava15/SimpleRecord.java @@ -0,0 +1,6 @@ +package test; +public record SimpleRecord(int x, CharSequence y) { + public CharSequence y() { return y; } + public CharSequence y(int n) { return y; } + public double z() { return 0.0; } +} diff --git a/compiler/testData/loadJava15/SimpleRecord.txt b/compiler/testData/loadJava15/SimpleRecord.txt new file mode 100644 index 0000000000000000000000000000000000000000..210be160dd42b0c1ca84fb971afaaf1232e31584 --- /dev/null +++ b/compiler/testData/loadJava15/SimpleRecord.txt @@ -0,0 +1,9 @@ +package test + +/*record*/ public final class SimpleRecord : java.lang.Record { + public constructor SimpleRecord(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.CharSequence!) + /*record component*/ public open fun x(): kotlin.Int + /*record component*/ public open fun y(): kotlin.CharSequence! + public open fun y(/*0*/ n: kotlin.Int): kotlin.CharSequence! + public open fun z(): kotlin.Double +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsWithJdk15Test.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsWithJdk15Test.kt new file mode 100644 index 0000000000000000000000000000000000000000..12c227f4d59052d227e12652950576610c784176 --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/checkers/AbstractDiagnosticsWithJdk15Test.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2010-2017 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.kotlin.checkers + +import org.jetbrains.kotlin.test.TestJdkKind + +abstract class AbstractDiagnosticsWithJdk15Test : AbstractDiagnosticsTest() { + + override fun getTestJdkKind(files: List): TestJdkKind { + return TestJdkKind.FULL_JDK_15 + } +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJava15Test.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJava15Test.kt new file mode 100644 index 0000000000000000000000000000000000000000..f55f166d6a40dd1e8e957f58b08c88dd76edf65b --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJava15Test.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.compiler + +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TestJdkKind +import java.io.File + +abstract class AbstractLoadJava15Test : AbstractLoadJavaTest() { + override fun getJdkKind(): TestJdkKind = TestJdkKind.FULL_JDK_15 + override fun getJdkHomeForJavac(): File = KotlinTestUtils.getJdk15Home() + override fun getAdditionalJavacArgs(): List = ADDITIONAL_JAVAC_ARGS_FOR_15 +} + +val ADDITIONAL_JAVAC_ARGS_FOR_15 = listOf("--release", "15", "--enable-preview") \ No newline at end of file diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJava15WithPsiClassReadingTest.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJava15WithPsiClassReadingTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..65f174495d0aa50707da5b598b44f0ca1d6f4f3d --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJava15WithPsiClassReadingTest.kt @@ -0,0 +1,16 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.compiler + +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TestJdkKind +import java.io.File + +abstract class AbstractLoadJava15WithPsiClassReadingTest : AbstractLoadJavaWithPsiClassReadingTest() { + override fun getJdkKind(): TestJdkKind = TestJdkKind.FULL_JDK_15 + override fun getJdkHomeForJavac(): File = KotlinTestUtils.getJdk15Home() + override fun getAdditionalJavacArgs(): List = ADDITIONAL_JAVAC_ARGS_FOR_15 +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java index 4f244b25362326d12565df5e6568531684ce3aae..8937b36687e8450ba2b535a0c43d0ec99fb73ade 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/AbstractLoadJavaTest.java @@ -9,6 +9,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import junit.framework.ComparisonFailure; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.analyzer.AnalysisResult; import org.jetbrains.kotlin.checkers.CompilerTestLanguageVersionSettingsKt; import org.jetbrains.kotlin.cli.common.config.ContentRootsKt; @@ -299,7 +300,19 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { Pair javaPackageAndContext = compileJavaAndLoadTestPackageAndBindingContextFromBinary( srcFiles, compiledDir, ConfigurationKind.ALL ); - checkJavaPackage(getExpectedFile(javaFileName.replaceFirst("\\.java$", ".txt")), javaPackageAndContext.first, javaPackageAndContext.second, configuration); + + + + checkJavaPackage(getExpectedFile( + useTxtSuffixIfFileExists(javaFileName.replaceFirst("\\.java$", ".txt"), "compiled") + ), javaPackageAndContext.first, javaPackageAndContext.second, configuration); + } + + public static String useTxtSuffixIfFileExists(String name, String suffix) { + File differentResultFile = KotlinTestUtils.replaceExtension(new File(name), suffix + ".txt"); + if (differentResultFile.exists()) return differentResultFile.getPath(); + + return name; } @NotNull @@ -308,12 +321,21 @@ public abstract class AbstractLoadJavaTest extends TestCaseWithTmpdir { @NotNull File outDir, @NotNull ConfigurationKind configurationKind ) throws IOException { - compileJavaWithAnnotationsJar(javaFiles, outDir); + compileJavaWithAnnotationsJar(javaFiles, outDir, getAdditionalJavacArgs(), getJdkHomeForJavac()); return loadTestPackageAndBindingContextFromJavaRoot(outDir, getTestRootDisposable(), getJdkKind(), configurationKind, true, usePsiClassFilesReading(), useJavacWrapper(), null, getExtraClasspath(), this::configureEnvironment); } + protected List getAdditionalJavacArgs() { + return Collections.emptyList(); + } + + @Nullable + protected File getJdkHomeForJavac() { + return null; + } + private static void checkJavaPackage( File txtFile, PackageViewDescriptor javaPackage, diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java index e5291ecc78f191c77c396719fafd8e66019aff26..149e68e72ca14657a68ce80747d24aa5449f283e 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/jvm/compiler/LoadDescriptorUtil.java @@ -142,7 +142,12 @@ public class LoadDescriptorUtil { return Pair.create(packageView, analysisResult.getBindingContext()); } - public static void compileJavaWithAnnotationsJar(@NotNull Collection javaFiles, @NotNull File outDir) throws IOException { + public static void compileJavaWithAnnotationsJar( + @NotNull Collection javaFiles, + @NotNull File outDir, + @NotNull List additionalArgs, + @Nullable File customJdkHomeForJavac + ) throws IOException { List args = new ArrayList<>(Arrays.asList( "-sourcepath", "compiler/testData/loadJava/include", "-d", outDir.getPath()) @@ -170,7 +175,14 @@ public class LoadDescriptorUtil { args.add("-classpath"); args.add(classpath.stream().map(File::getPath).collect(Collectors.joining(File.pathSeparator))); - KotlinTestUtils.compileJavaFiles(javaFiles, args); + args.addAll(additionalArgs); + + if (customJdkHomeForJavac != null) { + KotlinTestUtils.compileJavaFilesExternally(javaFiles, args, customJdkHomeForJavac); + } + else { + KotlinTestUtils.compileJavaFiles(javaFiles, args); + } } @NotNull diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java index 81a13679807dcfdc34ff340b3aa2757bf3dd586d..56267d438ccd74d12fc66fb2ace079207e8b31b5 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/KotlinTestUtils.java @@ -680,6 +680,10 @@ public class KotlinTestUtils { } public static boolean compileJavaFilesExternallyWithJava9(@NotNull Collection files, @NotNull List options) { + return compileJavaFilesExternally(files, options, getJdk9Home()); + } + + public static boolean compileJavaFilesExternally(@NotNull Collection files, @NotNull List options, @NotNull File jdkHome) { List command = new ArrayList<>(); command.add(new File(jdkHome, "bin/javac").getPath()); command.addAll(options); diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java b/compiler/tests-common/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java index 515a32be7555085135c1f9a8de370308ae7173da..8977f5ace0a242b4b5ba830b31a2e7ea76b38fa5 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/test/util/RecursiveDescriptorComparator.java @@ -27,6 +27,8 @@ import org.jetbrains.kotlin.contracts.description.*; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.impl.SubpackagesScope; import org.jetbrains.kotlin.jvm.compiler.ExpectedLoadErrorsUtil; +import org.jetbrains.kotlin.load.java.descriptors.JavaClassDescriptor; +import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.platform.TargetPlatformKt; import org.jetbrains.kotlin.renderer.*; @@ -193,7 +195,24 @@ public class RecursiveDescriptorComparator { boolean isPrimaryConstructor = conf.checkPrimaryConstructors && descriptor instanceof ConstructorDescriptor && ((ConstructorDescriptor) descriptor).isPrimary(); - printer.print(isPrimaryConstructor ? "/*primary*/ " : "", conf.renderer.render(descriptor)); + boolean isRecord = descriptor instanceof JavaClassDescriptor && ((JavaClassDescriptor) descriptor).isRecord(); + boolean isRecordComponent = descriptor instanceof JavaMethodDescriptor && ((JavaMethodDescriptor) descriptor).isForRecordComponent(); + + StringBuilder prefix = new StringBuilder(); + + if (isPrimaryConstructor) { + prefix.append("/*primary*/ "); + } + + if (isRecord) { + prefix.append("/*record*/ "); + } + + if (isRecordComponent) { + prefix.append("/*record component*/ "); + } + + printer.print(prefix.toString(), conf.renderer.render(descriptor)); if (descriptor instanceof FunctionDescriptor && conf.checkFunctionContracts) { printEffectsIfAny((FunctionDescriptor) descriptor, printer); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJdk15TestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJdk15TestGenerated.java new file mode 100644 index 0000000000000000000000000000000000000000..c2c94de340e2b72181630698e11ba4e8ba5a0b76 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsWithJdk15TestGenerated.java @@ -0,0 +1,35 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.checkers; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/diagnostics/testsWithJava15") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class DiagnosticsWithJdk15TestGenerated extends AbstractDiagnosticsWithJdk15Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInTestsWithJava15() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJava15"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @TestMetadata("simpleRecords.kt") + public void testSimpleRecords() throws Exception { + runTest("compiler/testData/diagnostics/testsWithJava15/simpleRecords.kt"); + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt index 56a73b4b4c89aa52edd4bc1f843824b47ff8ad95..5ebd70e752db540f6feb8672e36cc7224e920ae5 100644 --- a/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt +++ b/compiler/tests/org/jetbrains/kotlin/generators/tests/GenerateCompilerTests.kt @@ -123,6 +123,10 @@ fun main(args: Array) { model("diagnostics/testsWithJava9") } + testClass { + model("diagnostics/testsWithJava15") + } + testClass { model("diagnostics/testsWithUnsignedTypes") } @@ -309,6 +313,15 @@ fun main(args: Array) { model("loadJava/compiledJava", extension = "java", testMethod = "doTestCompiledJava") } + testClass { + model("loadJava15", extension = "java", testMethod = "doTestCompiledJava", testClassName = "CompiledJava") + model("loadJava15", extension = "java", testMethod = "doTestSourceJava", testClassName = "SourceJava") + } + + testClass { + model("loadJava15", extension = "java", testMethod = "doTestCompiledJava") + } + testClass { model( "compileJavaAgainstKotlin", diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava15TestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava15TestGenerated.java new file mode 100644 index 0000000000000000000000000000000000000000..a306af5eb18627882227049797b8aa33da314ff0 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava15TestGenerated.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.compiler; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@RunWith(JUnit3RunnerWithInners.class) +public class LoadJava15TestGenerated extends AbstractLoadJava15Test { + @TestMetadata("compiler/testData/loadJava15") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class CompiledJava extends AbstractLoadJava15Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath); + } + + public void testAllFilesPresentInCompiledJava() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava15"), Pattern.compile("^(.+)\\.java$"), null, true); + } + + @TestMetadata("GenericRecord.java") + public void testGenericRecord() throws Exception { + runTest("compiler/testData/loadJava15/GenericRecord.java"); + } + + @TestMetadata("SimpleRecord.java") + public void testSimpleRecord() throws Exception { + runTest("compiler/testData/loadJava15/SimpleRecord.java"); + } + } + + @TestMetadata("compiler/testData/loadJava15") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SourceJava extends AbstractLoadJava15Test { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestSourceJava, this, testDataFilePath); + } + + public void testAllFilesPresentInSourceJava() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava15"), Pattern.compile("^(.+)\\.java$"), null, true); + } + + @TestMetadata("GenericRecord.java") + public void testGenericRecord() throws Exception { + runTest("compiler/testData/loadJava15/GenericRecord.java"); + } + + @TestMetadata("SimpleRecord.java") + public void testSimpleRecord() throws Exception { + runTest("compiler/testData/loadJava15/SimpleRecord.java"); + } + } +} diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava15WithPsiClassReadingTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava15WithPsiClassReadingTestGenerated.java new file mode 100644 index 0000000000000000000000000000000000000000..aad9d58fcd968838c9bbba8f053cf5dab44c5e51 --- /dev/null +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJava15WithPsiClassReadingTestGenerated.java @@ -0,0 +1,40 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.jvm.compiler; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("compiler/testData/loadJava15") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class LoadJava15WithPsiClassReadingTestGenerated extends AbstractLoadJava15WithPsiClassReadingTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTestCompiledJava, this, testDataFilePath); + } + + public void testAllFilesPresentInLoadJava15() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/loadJava15"), Pattern.compile("^(.+)\\.java$"), null, true); + } + + @TestMetadata("GenericRecord.java") + public void testGenericRecord() throws Exception { + runTest("compiler/testData/loadJava15/GenericRecord.java"); + } + + @TestMetadata("SimpleRecord.java") + public void testSimpleRecord() throws Exception { + runTest("compiler/testData/loadJava15/SimpleRecord.java"); + } +} diff --git a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt index 45e221f9716bd3771208dbecbcf86cc66083d397..72700425946d3e0df4d400b0c6dc36042db78bae 100644 --- a/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt +++ b/core/compiler.common.jvm/src/org/jetbrains/kotlin/load/java/structure/javaElements.kt @@ -85,11 +85,13 @@ interface JavaClass : JavaClassifier, JavaTypeParameterListOwner, JavaModifierLi val isInterface: Boolean val isAnnotationType: Boolean val isEnum: Boolean + val isRecord: Boolean val lightClassOriginKind: LightClassOriginKind? val methods: Collection val fields: Collection val constructors: Collection + val recordComponents: Collection fun hasDefaultConstructor(): Boolean } @@ -133,6 +135,11 @@ interface JavaValueParameter : JavaAnnotationOwner { val isVararg: Boolean } +interface JavaRecordComponent : JavaMember { + val type: JavaType + val isVararg: Boolean +} + interface JavaTypeParameter : JavaClassifier { val upperBounds: Collection } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaResolverCache.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaResolverCache.java index 6b982077d3c8f0968eab1c6294dfb69fa2f4eeb3..9559661ed3c7acd9ae4302b4c7d1f34d75dc8dc4 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaResolverCache.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/components/JavaResolverCache.java @@ -22,10 +22,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor; import org.jetbrains.kotlin.descriptors.ConstructorDescriptor; import org.jetbrains.kotlin.descriptors.PropertyDescriptor; 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.*; import org.jetbrains.kotlin.name.FqName; public interface JavaResolverCache { @@ -37,7 +34,7 @@ public interface JavaResolverCache { } @Override - public void recordMethod(@NotNull JavaMethod method, @NotNull SimpleFunctionDescriptor descriptor) { + public void recordMethod(@NotNull JavaMember member, @NotNull SimpleFunctionDescriptor descriptor) { } @Override @@ -56,7 +53,8 @@ public interface JavaResolverCache { @Nullable ClassDescriptor getClassResolvedFromSource(@NotNull FqName fqName); - void recordMethod(@NotNull JavaMethod method, @NotNull SimpleFunctionDescriptor descriptor); + // It's a JavaMethod or JavaRecordComponent + void recordMethod(@NotNull JavaMember member, @NotNull SimpleFunctionDescriptor descriptor); void recordConstructor(@NotNull JavaElement element, @NotNull ConstructorDescriptor descriptor); diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java index 23f0232716f0314ffe8e53bfe417ac2c1804961c..01f1d282008aafc411c6a65259a10169495a5dca 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaClassDescriptor.java @@ -19,4 +19,5 @@ package org.jetbrains.kotlin.load.java.descriptors; import org.jetbrains.kotlin.descriptors.ClassDescriptor; public interface JavaClassDescriptor extends ClassDescriptor { + boolean isRecord(); } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java index 9259258a755c439bdde5f235af0dae0b1e891835..06954c9959ecf222709606f14b8aee9181fd7ff0 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/descriptors/JavaMethodDescriptor.java @@ -60,6 +60,7 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement } private ParameterNamesStatus parameterNamesStatus = null; + private final boolean isForRecordComponent; protected JavaMethodDescriptor( @NotNull DeclarationDescriptor containingDeclaration, @@ -67,9 +68,11 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement @NotNull Annotations annotations, @NotNull Name name, @NotNull Kind kind, - @NotNull SourceElement source + @NotNull SourceElement source, + boolean isForRecordComponent ) { super(containingDeclaration, original, annotations, name, kind, source); + this.isForRecordComponent = isForRecordComponent; } @NotNull @@ -77,9 +80,10 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement @NotNull DeclarationDescriptor containingDeclaration, @NotNull Annotations annotations, @NotNull Name name, - @NotNull SourceElement source + @NotNull SourceElement source, + boolean isForRecordComponent ) { - return new JavaMethodDescriptor(containingDeclaration, null, annotations, name, Kind.DECLARATION, source); + return new JavaMethodDescriptor(containingDeclaration, null, annotations, name, Kind.DECLARATION, source, isForRecordComponent); } @NotNull @@ -118,6 +122,10 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement this.parameterNamesStatus = ParameterNamesStatus.get(hasStableParameterNames, hasSynthesizedParameterNames); } + public boolean isForRecordComponent() { + return isForRecordComponent; + } + @NotNull @Override protected JavaMethodDescriptor createSubstitutedCopy( @@ -134,7 +142,8 @@ public class JavaMethodDescriptor extends SimpleFunctionDescriptorImpl implement annotations, newName != null ? newName : getName(), kind, - source + source, + isForRecordComponent ); result.setParameterNamesStatus(hasStableParameterNames(), hasSynthesizedParameterNames()); return result; diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/DeclaredMemberIndex.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/DeclaredMemberIndex.kt index bb22d28182dd2d1b94d12eaf3e4aa77d85c39a44..a4ee63a8d09da3568084cec7174529a4d689893a 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/DeclaredMemberIndex.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/DeclaredMemberIndex.kt @@ -26,12 +26,18 @@ interface DeclaredMemberIndex { fun findFieldByName(name: Name): JavaField? fun getFieldNames(): Set + fun getRecordComponentNames(): Set + fun findRecordComponentByName(name: Name): JavaRecordComponent? + object Empty : DeclaredMemberIndex { override fun findMethodsByName(name: Name) = listOf() override fun getMethodNames() = emptySet() override fun findFieldByName(name: Name): JavaField? = null override fun getFieldNames() = emptySet() + + override fun getRecordComponentNames(): Set = emptySet() + override fun findRecordComponentByName(name: Name): JavaRecordComponent? = null } } @@ -45,11 +51,15 @@ open class ClassDeclaredMemberIndex( private val methods = jClass.methods.asSequence().filter(methodFilter).groupBy { m -> m.name } private val fields = jClass.fields.asSequence().filter(memberFilter).associateBy { m -> m.name } + private val components = jClass.recordComponents.filter(memberFilter).associateBy { it.name } override fun findMethodsByName(name: Name): Collection = methods[name] ?: listOf() override fun getMethodNames(): Set = jClass.methods.asSequence().filter(methodFilter).mapTo(mutableSetOf(), JavaMethod::name) override fun findFieldByName(name: Name): JavaField? = fields[name] override fun getFieldNames(): Set = jClass.fields.asSequence().filter(memberFilter).mapTo(mutableSetOf(), JavaField::name) + + override fun getRecordComponentNames(): Set = components.keys + override fun findRecordComponentByName(name: Name): JavaRecordComponent? = components[name] } diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 5a5c60b822d87c58eed953c494af8335a8aee617..d352a0a4a47496ea10dedc0344dd382b5ea113ed 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -84,6 +84,8 @@ class LazyJavaClassDescriptor( override fun getKind() = kind override fun getModality() = modality + override fun isRecord(): Boolean = jClass.isRecord + // To workaround a problem with Scala compatibility (KT-9700), // we consider private visibility of a Java top level class as package private // Shortly: Scala plugin introduces special kind of "private in package" classes diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt index 63878923dafb52fb86534b70c0155d3b4e982dee..7a0399d71b147b8e163af4e19fc01a3c7c40e8c5 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassMemberScope.kt @@ -39,10 +39,7 @@ import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext import org.jetbrains.kotlin.load.java.lazy.childForMethod import org.jetbrains.kotlin.load.java.lazy.resolveAnnotations import org.jetbrains.kotlin.load.java.lazy.types.toAttributes -import org.jetbrains.kotlin.load.java.structure.JavaArrayType -import org.jetbrains.kotlin.load.java.structure.JavaClass -import org.jetbrains.kotlin.load.java.structure.JavaConstructor -import org.jetbrains.kotlin.load.java.structure.JavaMethod +import org.jetbrains.kotlin.load.java.structure.* import org.jetbrains.kotlin.load.kotlin.computeJvmDescriptor import org.jetbrains.kotlin.name.FqNameUnsafe import org.jetbrains.kotlin.name.Name @@ -79,23 +76,79 @@ class LazyJavaClassMemberScope( it.memberScope.getFunctionNames() }.apply { addAll(declaredMemberIndex().getMethodNames()) + addAll(declaredMemberIndex().getRecordComponentNames()) addAll(computeClassNames(kindFilter, nameFilter)) } internal val constructors = c.storageManager.createLazyValue { val constructors = jClass.constructors - val result = ArrayList(constructors.size) + val result = ArrayList(constructors.size) for (constructor in constructors) { val descriptor = resolveConstructor(constructor) result.add(descriptor) } + if (jClass.isRecord) { + val defaultConstructor = createDefaultRecordConstructor() + val jvmDescriptor = defaultConstructor.computeJvmDescriptor(withReturnType = false) + + if (result.none { it.computeJvmDescriptor(withReturnType = false) == jvmDescriptor }) { + result.add(defaultConstructor) + c.components.javaResolverCache.recordConstructor(jClass, defaultConstructor) + } + } + c.components.signatureEnhancement.enhanceSignatures( c, result.ifEmpty { listOfNotNull(createDefaultConstructor()) } ).toList() } + private fun createDefaultRecordConstructor(): ClassConstructorDescriptor { + val classDescriptor = ownerDescriptor + val constructorDescriptor = JavaClassConstructorDescriptor.createJavaConstructor( + classDescriptor, Annotations.EMPTY, /* isPrimary = */ true, c.components.sourceElementFactory.source(jClass) + ) + val valueParameters = createRecordConstructorParameters(constructorDescriptor) + constructorDescriptor.setHasSynthesizedParameterNames(false) + + constructorDescriptor.initialize(valueParameters, getConstructorVisibility(classDescriptor)) + constructorDescriptor.setHasStableParameterNames(false) + constructorDescriptor.returnType = classDescriptor.defaultType + return constructorDescriptor + } + + private fun createRecordConstructorParameters(constructor: ClassConstructorDescriptorImpl): List { + val components = jClass.recordComponents + val result = ArrayList(components.size) + + val attr = TypeUsage.COMMON.toAttributes(isForAnnotationParameter = false) + + for ((index, component) in components.withIndex()) { + val parameterType = c.typeResolver.transformJavaType(component.type, attr) + val varargElementType = + if (component.isVararg) c.components.module.builtIns.getArrayElementType(parameterType) else null + + result.add( + ValueParameterDescriptorImpl( + constructor, + null, + index, + Annotations.EMPTY, + component.name, + parameterType, + /* deeclaresDefaultValue = */false, + /* isCrossinline = */ false, + /* isNoinline = */ false, + varargElementType, + c.components.sourceElementFactory.source(component) + ) + ) + } + + return result + } + override fun JavaMethodDescriptor.isVisibleAsFunction(): Boolean { if (jClass.isAnnotationType) return false return isVisibleAsFunctionInCurrentClass(this) @@ -439,6 +492,42 @@ class LazyJavaClassMemberScope( } } + override fun computeImplicitlyDeclaredFunctions(result: MutableCollection, name: Name) { + if (jClass.isRecord && declaredMemberIndex().findRecordComponentByName(name) != null && result.none { it.valueParameters.isEmpty() }) { + result.add(resolveRecordComponentToFunctionDescriptor(declaredMemberIndex().findRecordComponentByName(name)!!)) + } + } + + private fun resolveRecordComponentToFunctionDescriptor(recordComponent: JavaRecordComponent): JavaMethodDescriptor { + val annotations = c.resolveAnnotations(recordComponent) + val functionDescriptorImpl = JavaMethodDescriptor.createJavaMethod( + ownerDescriptor, annotations, recordComponent.name, c.components.sourceElementFactory.source(recordComponent), true + ) + + val returnTypeAttrs = TypeUsage.COMMON.toAttributes(isForAnnotationParameter = false) + val returnType = c.typeResolver.transformJavaType(recordComponent.type, returnTypeAttrs) + + functionDescriptorImpl.initialize( + null, + getDispatchReceiverParameter(), + emptyList(), + emptyList(), + returnType, + // Those functions are generated as open in bytecode + // Actually, it should not be important because the class is final anyway, but leaving them open is convenient for consistency + Modality.convertFromFlags(abstract = false, open = true), + DescriptorVisibilities.PUBLIC, + null, + ) + + functionDescriptorImpl.setParameterNamesStatus(false, false) + + c.components.javaResolverCache.recordMethod(recordComponent, functionDescriptorImpl) + + return functionDescriptorImpl + } + + override fun computeNonDeclaredProperties(name: Name, result: MutableCollection) { if (jClass.isAnnotationType) { computeAnnotationProperties(name, result) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt index cb435ecf92cffddb9584d3545e9554b8f25ca7d6..8642044363f0f150c22c41a9e669650a476cfba5 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaScope.kt @@ -82,6 +82,10 @@ abstract class LazyJavaScope( // Fake overrides, values()/valueOf(), etc. protected abstract fun computeNonDeclaredFunctions(result: MutableCollection, name: Name) + // It has a similar semantics to computeNonDeclaredFunctions, but it's being called just once per class + // While computeNonDeclaredFunctions is being called once per scope instance (once per KotlinTypeRefiner) + protected open fun computeImplicitlyDeclaredFunctions(result: MutableCollection, name: Name) {} + protected abstract fun getDispatchReceiverParameter(): ReceiverParameterDescriptor? private val declaredFunctions: MemoizedFunctionToNotNull> = @@ -98,6 +102,8 @@ abstract class LazyJavaScope( result.add(descriptor) } + computeImplicitlyDeclaredFunctions(result, name) + result } @@ -154,7 +160,8 @@ abstract class LazyJavaScope( protected fun resolveMethodToFunctionDescriptor(method: JavaMethod): JavaMethodDescriptor { val annotations = c.resolveAnnotations(method) val functionDescriptorImpl = JavaMethodDescriptor.createJavaMethod( - ownerDescriptor, annotations, method.name, c.components.sourceElementFactory.source(method) + ownerDescriptor, annotations, method.name, c.components.sourceElementFactory.source(method), + declaredMemberIndex().findRecordComponentByName(method.name) != null && method.valueParameters.isEmpty() ) val c = c.childForMethod(functionDescriptorImpl, method) diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaClass.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaClass.kt index b2097b11e79aace129828309e884fcc57e716e6b..f98ca3118f980dbe99ee977df1fc9fbd776ecf7e 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaClass.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/descriptors/runtime/structure/ReflectJavaClass.kt @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.descriptors.runtime.structure import org.jetbrains.kotlin.load.java.structure.JavaClass import org.jetbrains.kotlin.load.java.structure.JavaClassifierType +import org.jetbrains.kotlin.load.java.structure.JavaRecordComponent import org.jetbrains.kotlin.load.java.structure.LightClassOriginKind import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name @@ -96,6 +97,9 @@ class ReflectJavaClass( .map(::ReflectJavaConstructor) .toList() + override val recordComponents: Collection + get() = emptyList() + override fun hasDefaultConstructor() = false // any default constructor is returned by constructors override val lightClassOriginKind: LightClassOriginKind? @@ -114,6 +118,10 @@ class ReflectJavaClass( override val isEnum: Boolean get() = klass.isEnum + // TODO: Support reflect + override val isRecord: Boolean + get() = false + override fun equals(other: Any?) = other is ReflectJavaClass && klass == other.klass override fun hashCode() = klass.hashCode() diff --git a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt index 243a47f4b1698e0a7a269b119a4e4f45154c1178..dc0007415010c7056f988606ad98178d7ec3a392 100644 --- a/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt +++ b/core/descriptors.runtime/tests/org/jetbrains/kotlin/jvm/runtime/AbstractJvmRuntimeDescriptorLoaderTest.kt @@ -125,7 +125,7 @@ abstract class AbstractJvmRuntimeDescriptorLoaderTest : TestCaseWithTmpdir() { }, "" ) - LoadDescriptorUtil.compileJavaWithAnnotationsJar(sources, tmpdir) + LoadDescriptorUtil.compileJavaWithAnnotationsJar(sources, tmpdir, emptyList(), null) } fileName.endsWith(".kt") -> { val environment = KotlinTestUtils.createEnvironmentWithJdkAndNullabilityAnnotationsFromIdea(