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
@@ -59,6 +59,9 @@ class JavaClassImpl(psiClass: PsiClass) : JavaClassifierImpl<PsiClass>(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>(psiClass)
return constructors(psi.constructors.filter { method -> method.isConstructor })
}
override val recordComponents: Collection<JavaRecordComponent>
get() {
assertNotLightClass()
return psi.recordComponents.convert(::JavaRecordComponentImpl)
}
override fun hasDefaultConstructor() = !isInterface && constructors.isEmpty()
override val isAbstract: Boolean
@@ -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 <Psi, Java> Array<Psi>.convert(factory: (Psi) -> Java): List<Java> =
inline fun <Psi, Java> Array<Psi>.convert(factory: (Psi) -> Java): List<Java> =
when (size) {
0 -> emptyList()
1 -> listOf(factory(first()))
else -> map(factory)
}
private fun <Psi, Java> Collection<Psi>.convert(factory: (Psi) -> Java): List<Java> =
fun <Psi, Java> Collection<Psi>.convert(factory: (Psi) -> Java): List<Java> =
when (size) {
0 -> emptyList()
1 -> listOf(factory(first()))
@@ -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>(psiRecordComponent), JavaRecordComponent {
override val type: JavaType
get() = JavaTypeImpl.create(psi.type)
override val isVararg: Boolean
get() = psi.isVarArgs
}
@@ -47,6 +47,8 @@ class BinaryJavaClass(
override val methods = arrayListOf<JavaMethod>()
override val fields = arrayListOf<JavaField>()
override val constructors = arrayListOf<JavaConstructor>()
override val recordComponents = arrayListOf<JavaRecordComponent>()
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
*/
@@ -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<JavaAnnotation>
get() = emptyList()
override val access: Int
get() = 0
override val annotationsByFqName: Map<FqName?, JavaAnnotation>
get() = emptyMap()
}
fun isNotTopLevelClass(classContent: ByteArray): Boolean {
var isNotTopLevelClass = false
ClassReader(classContent).accept(