New J2K: Add support of annotation classes

This commit is contained in:
Ilya Kirillov
2019-02-04 11:59:38 +03:00
committed by Ilya Kirillov
parent 11f4df8173
commit d7962afd05
23 changed files with 505 additions and 86 deletions
@@ -25,7 +25,9 @@ object ConversionsRunner {
batchPipe {
//Java --> Kotlin conversions
+JavaModifiersConversion(context)
+JavaAnnotationsConversion()
+JavaAnnotationsConversion(context)
+AnnotationClassConversion(context)
+AnnotationConversion(context)
+ModalityConversion(context)
+AssignmentAsExpressionToAlsoConversion(context)
+AssignmentStatementValCreationConversion(context)
@@ -37,6 +37,7 @@ class JKSymbolProvider {
is KtNamedFunction -> JKMultiverseFunctionSymbol(psi, this)
is KtProperty -> JKMultiversePropertySymbol(psi, this)
is KtParameter -> JKMultiversePropertySymbol(psi, this)
is PsiParameter -> JKMultiverseFieldSymbol(psi, this)
is PsiLocalVariable -> JKMultiverseFieldSymbol(psi, this)
else -> TODO(psi::class.toString())
}
@@ -173,7 +173,9 @@ class JavaToJKTreeBuilder(
fun PsiPrefixExpression.toJK(): JKExpression {
return JKPrefixExpressionImpl(operand.toJK(), operationSign.tokenType.toJK()).let {
if (it.operator.token.text in listOf("+", "-") && it.expression is JKLiteralExpression) {
if (it.operator.token in listOf(JavaTokenType.PLUS, JavaTokenType.MINUS)
&& it.expression is JKLiteralExpression
) {
JKJavaLiteralExpressionImpl(
it.operator.token.text + (it.expression as JKLiteralExpression).literal,
(it.expression as JKLiteralExpression).type
@@ -423,6 +425,7 @@ class JavaToJKTreeBuilder(
when (it) {
is PsiEnumConstant -> it.toJK()
is PsiClass -> it.toJK()
is PsiAnnotationMethod -> it.toJK()
is PsiMethod -> it.toJK()
is PsiField -> it.toJK()
is PsiClassInitializer -> it.toJK()
@@ -552,8 +555,17 @@ class JavaToJKTreeBuilder(
fun PsiAnnotation.toJK(): JKAnnotation =
JKAnnotationImpl(
symbolProvider.provideSymbol(nameReferenceElement!!),
with(expressionTreeMapper) {
JKExpressionListImpl(parameterList.attributes.map { (it.value as? PsiExpression).toJK() })
parameterList.attributes.map { parameter ->
if (parameter.nameIdentifier != null) {
JKAnnotationNameParameterImpl(
parameter.value?.toJK() ?: JKStubExpressionImpl(),
JKNameIdentifierImpl(parameter.name!!)
)
} else {
JKAnnotationParameterImpl(
parameter.value?.toJK() ?: JKStubExpressionImpl()
)
}
}
)
@@ -561,12 +573,36 @@ class JavaToJKTreeBuilder(
findTagByName("deprecated")?.let { tag ->
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.Deprecated"),
JKExpressionListImpl(
stringLiteral(tag.content(), symbolProvider)
listOf(
JKAnnotationParameterImpl(stringLiteral(tag.content(), symbolProvider))
)
)
}
private fun PsiAnnotationMemberValue.toJK(): JKAnnotationMemberValue =
when (this) {
is PsiExpression -> with(expressionTreeMapper) { toJK() }
is PsiAnnotation -> toJK()
is PsiArrayInitializerMemberValue ->
JKKtAnnotationArrayInitializerExpressionImpl(
initializers.map { it.toJK() }
)
else -> TODO(this::class.toString())
}
fun PsiAnnotationMethod.toJK(): JKJavaAnnotationMethod =
JKJavaAnnotationMethodImpl(
with(expressionTreeMapper) {
returnTypeElement?.toJK()
?: JKTypeElementImpl(JKJavaVoidType).takeIf { isConstructor }
?: TODO()
},
JKNameIdentifierImpl(name),
defaultValue?.toJK() ?: JKStubExpressionImpl()
).also {
it.psi = this
symbolProvider.provideUniverseSymbol(this, it)
}
fun PsiMethod.toJK(): JKJavaMethod {
return JKJavaMethodImpl(
@@ -304,6 +304,11 @@ class NewCodeBuilder {
if (parameter.isVarArgs) {
printer.printWithNoIndent("vararg ")
}
if (parameter.parent is JKKtPrimaryConstructor
&& (parameter.parent?.parent?.parent as? JKClass)?.classKind == JKClass.ClassKind.ANNOTATION
) {//TODO get rid of
printer.print(" val ")
}
parameter.name.accept(this)
if (parameter.type.present() && parameter.type.type !is JKContextType) {
printer.printWithNoIndent(":")
@@ -315,6 +320,14 @@ class NewCodeBuilder {
}
}
override fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression) {
printer.print("[")
renderList(ktAnnotationArrayInitializerExpression.initializers) {
it.accept(this)
}
printer.print("]")
}
override fun visitForLoopVariable(forLoopVariable: JKForLoopVariable) {
forLoopVariable.name.accept(this)
if (forLoopVariable.type.present() && forLoopVariable.type.type !is JKContextType) {
@@ -796,13 +809,23 @@ class NewCodeBuilder {
override fun visitAnnotation(annotation: JKAnnotation) {
printer.printWithNoIndent("@")
printer.printWithNoIndent(annotation.classSymbol.displayName().escapedAsQualifiedName())
if (annotation.arguments.expressions.isNotEmpty()) {
if (annotation.arguments.isNotEmpty()) {
printer.par {
annotation.arguments.accept(this)
renderList(annotation.arguments) { it.accept(this) }
}
}
}
override fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter) {
annotationNameParameter.name.accept(this)
printer.print(" = ")
annotationNameParameter.value.accept(this)
}
override fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter) {
annotationParameter.value.accept(this)
}
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) {
if (classLiteralExpression.literalType == JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE) {
printer.printWithNoIndent("Void.TYPE")
@@ -852,9 +875,6 @@ private inline fun <T> List<T>.headTail(): Pair<T?, List<T>?> {
return head to tail
}
private inline fun JKClass.primaryConstructor(): JKKtPrimaryConstructor? =
classBody.declarations.firstIsInstanceOrNull()
private inline fun JKDelegationConstructorCall.isCallOfConstructorOf(type: JKType): Boolean {
return when (type) {
@@ -0,0 +1,57 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. 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.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.toExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class AnnotationClassConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
if (element.classKind != JKClass.ClassKind.ANNOTATION) return recurse(element)
val javaAnnotationMethods =
element.classBody.declarations
.filterIsInstance<JKJavaAnnotationMethod>()
val constructor = JKKtPrimaryConstructorImpl(
JKNameIdentifierImpl(""),
javaAnnotationMethods.map { it.asKotlinAnnotationParameter() },
JKStubExpressionImpl(),
JKAnnotationListImpl(),
emptyList(),
Visibility.PUBLIC,
Modality.FINAL
)
element.modality = Modality.FINAL
element.classBody.declarations += constructor
element.classBody.declarations -= javaAnnotationMethods
return recurse(element)
}
private fun JKJavaAnnotationMethod.asKotlinAnnotationParameter(): JKParameterImpl {
val type = returnType.type
.updateNullabilityRecursively(Nullability.NotNull)
.replaceJavaClassWithKotlinClassType(context.symbolProvider)
val initializer = this::defaultValue.detached().toExpression(context.symbolProvider)
val isVarArgs = type is JKJavaArrayType && name.value == "value"
return JKParameterImpl(
JKTypeElementImpl(
if (!isVarArgs) type else (type as JKJavaArrayType).type
),
JKNameIdentifierImpl(name.value),
isVarArgs = isVarArgs,
initializer =
if (type.isArrayType()
&& initializer !is JKKtAnnotationArrayInitializerExpression
&& initializer !is JKStubExpression
) {
JKKtAnnotationArrayInitializerExpressionImpl(initializer)
} else initializer
)
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. 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.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.isVarargsArgument
import org.jetbrains.kotlin.j2k.primaryConstructor
import org.jetbrains.kotlin.j2k.toExpression
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKAnnotationNameParameterImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKAnnotationParameterImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKUniverseClassSymbol
class AnnotationConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKAnnotation) return recurse(element)
fixVarargsInvocation(element)
for (parameter in element.arguments) {
parameter.value = parameter.value.toExpression(context.symbolProvider)
}
return recurse(element)
}
private fun fixVarargsInvocation(annotation: JKAnnotation) {
val newParameters =
annotation.arguments.withIndex()
.flatMap { (index, annotationParameter) ->
when {
annotationParameter !is JKAnnotationNameParameter
&& annotation.isVarargsArgument(index)
&& annotationParameter.value is JKKtAnnotationArrayInitializerExpression ->
(annotationParameter.value as JKKtAnnotationArrayInitializerExpression)::initializers
.detached()
.map { JKAnnotationParameterImpl(it) }
annotationParameter is JKAnnotationNameParameterImpl ->
listOf(
JKAnnotationNameParameterImpl(
annotationParameter::value.detached(),
annotationParameter::name.detached()
)
)
else -> listOf(
JKAnnotationParameterImpl(
annotationParameter::value.detached()
)
)
}
}
annotation.arguments = newParameters
}
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.j2k.conversions
import com.intellij.psi.PsiClass
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.jvmAnnotation
import org.jetbrains.kotlin.j2k.tree.*
@@ -16,7 +15,6 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class DefaultArgumentsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
private fun JKMethod.canNotBeMerged(): Boolean =
modality == Modality.ABSTRACT ||
modality == Modality.OVERRIDE ||
@@ -56,8 +54,8 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur
val targetParameter = calledMethod.parameters[i]
val argument = call.arguments.expressions[i]
if (parameter.name.value != targetParameter.name.value) continue@checkMethod
if (parameter.type.type != targetParameter.type.type) continue@checkMethod
if (argument !is JKFieldAccessExpression || argument.identifier.target != parameter) continue@checkMethod
// if (parameter.type.type != targetParameter.type.type) continue@checkMethod
// if (argument !is JKFieldAccessExpression || argument.identifier.target != parameter) continue@checkMethod
}
@@ -86,7 +84,7 @@ class DefaultArgumentsConversion(private val context: ConversionContext) : Recur
}
for (method in element.declarationList) {
if (method !is JKMethod) continue
if (method !is JKJavaMethod) continue
if (method.hasParametersWithDefaultValues() && (method.visibility == Visibility.PUBLIC || method.visibility == Visibility.INTERNAL)) {
method.annotationList.annotations += jvmAnnotation("JvmOverloads", context.symbolProvider)
}
@@ -12,14 +12,19 @@ import org.jetbrains.kotlin.j2k.tree.*
class InterfaceWithFieldConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKClass) return recurse(element)
if (element.classKind != JKClass.ClassKind.INTERFACE) return recurse(element)
val finalFields = element.declarationList
if (element.classKind != JKClass.ClassKind.INTERFACE
&& element.classKind != JKClass.ClassKind.ANNOTATION
) return recurse(element)
val fieldsToMoveToCompanion = element.declarationList
.filterIsInstance<JKField>()
.filter { it.modality == Modality.FINAL }
if (finalFields.isNotEmpty()) {
element.classBody.declarations -= finalFields
.filter { field ->
field.modality == Modality.FINAL || element.classKind == JKClass.ClassKind.ANNOTATION
}
if (fieldsToMoveToCompanion.isNotEmpty()) {
element.classBody.declarations -= fieldsToMoveToCompanion
val companion = element.getOrCreateCompainonObject()
companion.classBody.declarations += finalFields
companion.classBody.declarations += fieldsToMoveToCompanion
}
return recurse(element)
}
@@ -5,15 +5,69 @@
package org.jetbrains.kotlin.j2k.conversions
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.JKAnnotationParameterImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKFieldAccessExpressionImpl
import org.jetbrains.kotlin.j2k.tree.impl.JKKtLiteralExpressionImpl
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JavaAnnotationsConversion : RecursiveApplicableConversionBase() {
class JavaAnnotationsConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKAnnotation) return recurse(element)
if (element.classSymbol.name == "Deprecated" && element.arguments.expressions.isEmpty()) {
element.arguments.expressions += JKKtLiteralExpressionImpl("\"\"", JKLiteralExpression.LiteralType.STRING)
if (element.classSymbol.name == "Deprecated" && element.arguments.isEmpty()) {
element.arguments +=
JKAnnotationParameterImpl(JKKtLiteralExpressionImpl("\"\"", JKLiteralExpression.LiteralType.STRING))
}
if (element.classSymbol.fqName == "java.lang.annotation.Target") {
element.classSymbol = context.symbolProvider.provideByFqName("kotlin.annotation.Target")
val arguments = element.arguments.singleOrNull()?.let { parameter ->
val value = parameter.value
when (value) {
is JKKtAnnotationArrayInitializerExpression -> value.initializers
else -> listOf(value)
}
}
if (arguments != null) {
val newArguments =
arguments.flatMap { value ->
value.fieldAccessFqName()
?.let { targetMappings[it] }
?.map { fqName ->
JKFieldAccessExpressionImpl(context.symbolProvider.provideByFqName(fqName))
} ?: listOf(value)
}
element.arguments = newArguments.map { JKAnnotationParameterImpl(it) }
}
}
return recurse(element)
}
private fun JKAnnotationMemberValue.fieldAccessFqName(): String? =
(safeAs<JKQualifiedExpression>()?.selector ?: this)
.safeAs<JKFieldAccessExpression>()
?.identifier
?.fqName
companion object {
private val targetMappings =
listOf(
"ANNOTATION_TYPE" to listOf("ANNOTATION_CLASS"),
"CONSTRUCTOR" to listOf("CONSTRUCTOR"),
"FIELD" to listOf("FIELD"),
"LOCAL_VARIABLE" to listOf("LOCAL_VARIABLE"),
"METHOD" to listOf("FUNCTION", "PROPERTY_GETTER", "PROPERTY_SETTER"),
"PACKAGE" to listOf("FILE"),
"PARAMETER" to listOf("VALUE_PARAMETER"),
"TYPE_PARAMETER" to listOf("TYPE_PARAMETER"),
"TYPE" to listOf("ANNOTATION_CLASS", "CLASS"),
"TYPE_USE" to listOf("TYPE_USE")
).map { (java, kotlins) ->
"java.lang.annotation.ElementType.$java" to kotlins.map { "kotlin.annotation.AnnotationTarget.$it" }
}.toMap()
}
}
@@ -30,7 +30,7 @@ class MainFunctionConversion(private val context: ConversionContext) : Recursive
element.annotationList.annotations +=
JKAnnotationImpl(
context.symbolProvider.provideByFqName("kotlin.jvm.JvmStatic"),
JKExpressionListImpl()
emptyList()
)
}
return recurse(element)
@@ -10,29 +10,8 @@ import org.jetbrains.kotlin.j2k.tree.impl.JKBranchElementBase
abstract class MatchBasedConversion : SequentialBaseConversion {
fun <R : JKTreeElement, T> applyRecursive(element: R, data: T, func: (JKTreeElement, T) -> JKTreeElement): R {
if (element is JKBranchElementBase) {
val iter = element.children.listIterator()
while (iter.hasNext()) {
val child = iter.next()
if (child is List<*>) {
iter.set(applyRecursiveToList(element, child as List<JKTreeElement>, iter, data, func))
} else if (child is JKTreeElement) {
val newChild = func(child, data)
if (child !== newChild) {
child.detach(element)
iter.set(newChild)
newChild.attach(element)
onElementChanged(newChild, child)
}
} else {
error("unsupported child type: ${child::class}")
}
}
}
return element
}
fun <R : JKTreeElement, T> applyRecursive(element: R, data: T, func: (JKTreeElement, T) -> JKTreeElement): R =
org.jetbrains.kotlin.j2k.tree.applyRecursive(element, data, ::onElementChanged, func)
inline fun <R : JKTreeElement> applyRecursive(element: R, crossinline func: (JKTreeElement) -> JKTreeElement): R {
return applyRecursive(element, null) { it, _ -> func(it) }
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.math.BigInteger
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider, nullability: Nullability = Nullability.Nullable): JKClassType {
@@ -282,11 +283,11 @@ fun jvmAnnotation(name: String, symbolProvider: JKSymbolProvider) =
fun throwAnnotation(throws: List<JKType>, symbolProvider: JKSymbolProvider) =
JKAnnotationImpl(
symbolProvider.provideByFqName("kotlin.jvm.Throws"),
JKExpressionListImpl(
throws.map {
throws.map {
JKAnnotationParameterImpl(
JKClassLiteralExpressionImpl(JKTypeElementImpl(it), JKClassLiteralExpression.LiteralType.KOTLIN_CLASS)
}
)
)
}
)
fun JKAnnotationList.annotationByFqName(fqName: String): JKAnnotation? =
@@ -473,4 +474,46 @@ fun runExpression(body: JKStatement, symbolProvider: JKSymbolProvider): JKExpres
symbolProvider.provideByFqNameMulti("kotlin.run"),
JKExpressionListImpl(listOf(lambda))
)
}
}
fun JKAnnotationMemberValue.toExpression(symbolProvider: JKSymbolProvider): JKExpression {
fun handleAnnotationParameter(element: JKTreeElement): JKTreeElement =
when (element) {
is JKClassLiteralExpression ->
element.also {
element.literalType = JKClassLiteralExpression.LiteralType.KOTLIN_CLASS
}
is JKTypeElement ->
JKTypeElementImpl(element.type.replaceJavaClassWithKotlinClassType(symbolProvider))
else -> applyRecursive(element, ::handleAnnotationParameter)
}
return handleAnnotationParameter(
when {
this is JKStubExpression -> this
this is JKAnnotation ->
JKJavaNewExpressionImpl(
classSymbol,
JKExpressionListImpl(arguments.map { it.value.detached(this).toExpression(symbolProvider) }),
JKTypeArgumentListImpl()
)
this is JKKtAnnotationArrayInitializerExpression ->
JKKtAnnotationArrayInitializerExpressionImpl(initializers.map { it.detached(this).toExpression(symbolProvider) })
this is JKExpression -> this
else -> error("Bad initializer")
}
) as JKExpression
}
inline fun JKClass.primaryConstructor(): JKKtPrimaryConstructor? =
classBody.declarations.firstIsInstanceOrNull()
fun JKAnnotation.isVarargsArgument(index: Int): Boolean {
val target = classSymbol.target
return when (target) {
is JKClass -> target.primaryConstructor()?.parameters?.getOrNull(index)?.isVarArgs
is PsiClass -> target.methods.getOrNull(index)?.isVarArgs
else -> false
} ?: false
}
@@ -382,4 +382,32 @@ class JKJavaSynchronizedStatementImpl(
override val lockExpression: JKExpression by child(lockExpression)
override val body: JKBlock by child(body)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaSynchronizedStatement(this, data)
}
}
class JKJavaAnnotationMethodImpl(
returnType: JKTypeElement,
name: JKNameIdentifier,
defaultValue: JKAnnotationMemberValue
) : JKJavaAnnotationMethod, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var returnType: JKTypeElement by child(returnType)
override var name: JKNameIdentifier by child(name)
override var parameters: List<JKParameter> by children()
override var defaultValue: JKAnnotationMemberValue by child(defaultValue)
override var block: JKBlock by child(JKBodyStub)
override var typeParameterList: JKTypeParameterList by child(JKTypeParameterListImpl())
override var annotationList: JKAnnotationList by child(JKAnnotationListImpl())
override var extraModifiers: List<ExtraModifier> = emptyList()
override var visibility: Visibility = Visibility.PUBLIC
override var modality: Modality = Modality.FINAL
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaAnnotationMethod(this, data)
}
class JKKtAnnotationArrayInitializerExpressionImpl(initializers: List<JKAnnotationMemberValue>) : JKKtAnnotationArrayInitializerExpression,
JKBranchElementBase() {
constructor(vararg initializers: JKAnnotationMemberValue) : this(initializers.toList())
override val initializers: List<JKAnnotationMemberValue> by children(initializers)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtAnnotationArrayInitializerExpression(this, data)
}
@@ -498,10 +498,10 @@ class JKAnnotationListImpl(annotations: List<JKAnnotation> = emptyList()) : JKAn
}
class JKAnnotationImpl(
override val classSymbol: JKClassSymbol,
arguments: JKExpressionList = JKExpressionListImpl()
override var classSymbol: JKClassSymbol,
arguments: List<JKAnnotationParameter> = emptyList()
) : JKAnnotation, JKBranchElementBase() {
override var arguments: JKExpressionList by child(arguments)
override var arguments: List<JKAnnotationParameter> by children(arguments)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotation(this, data)
}
@@ -525,4 +525,20 @@ class JKImportStatementImpl(name: JKNameIdentifier) : JKImportStatement, JKBranc
override val name: JKNameIdentifier by child(name)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitImportStatement(this, data)
}
class JKAnnotationParameterImpl(value: JKAnnotationMemberValue) : JKAnnotationParameter, JKBranchElementBase() {
override var value: JKAnnotationMemberValue by child(value)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotationParameter(this, data)
}
class JKAnnotationNameParameterImpl(
value: JKAnnotationMemberValue,
name: JKNameIdentifier
) : JKAnnotationNameParameter, JKBranchElementBase() {
override var value: JKAnnotationMemberValue by child(value)
override val name: JKNameIdentifier by child(name)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitAnnotationNameParameter(this, data)
}
@@ -175,7 +175,7 @@ class JKKtConstructorImpl(
}
class JKKtPrimaryConstructorImpl(
name: JKNameIdentifier,
name: JKNameIdentifier,//TODO not needed
parameters: List<JKParameter>,
delegationCall: JKExpression,
annotationList: JKAnnotationList,
@@ -101,7 +101,7 @@ fun JKClassSymbol.displayName() =
when (this) {
is JKUniverseClassSymbol ->
target.psi<PsiClass>()
?.let { it.nameWithOuterClasses() }
?.nameWithOuterClasses()
?: name
is JKMultiverseClassSymbol -> target.nameWithOuterClasses()
else -> name
@@ -132,4 +132,8 @@ interface JKJavaContinueStatement: JKStatement
interface JKJavaSynchronizedStatement : JKStatement, JKBranchElement {
val lockExpression: JKExpression
val body: JKBlock
}
interface JKJavaAnnotationMethod : JKMethod, JKBranchElement {
val defaultValue: JKAnnotationMemberValue
}
+16 -6
View File
@@ -83,9 +83,17 @@ interface JKAnnotationList : JKTreeElement {
var annotations: List<JKAnnotation>
}
interface JKAnnotation : JKTreeElement {
val classSymbol: JKClassSymbol
var arguments: JKExpressionList
interface JKAnnotation : JKAnnotationMemberValue {
var classSymbol: JKClassSymbol
var arguments: List<JKAnnotationParameter>
}
interface JKAnnotationParameter : JKTreeElement {
var value: JKAnnotationMemberValue
}
interface JKAnnotationNameParameter : JKAnnotationParameter {
val name: JKNameIdentifier
}
interface JKAnnotationListOwner : JKTreeElement {
@@ -207,7 +215,7 @@ interface JKNameIdentifier : JKIdentifier {
val value: String
}
interface JKExpression : JKTreeElement
interface JKExpression : JKTreeElement, JKAnnotationMemberValue
interface JKExpressionStatement : JKStatement, JKBranchElement {
val expression: JKExpression
@@ -411,7 +419,7 @@ interface JKPackageDeclaration : JKDeclaration {
interface JKClassLiteralExpression : JKExpression {
val classType: JKTypeElement
val literalType: LiteralType
var literalType: LiteralType
enum class LiteralType {
KOTLIN_CLASS,
@@ -419,4 +427,6 @@ interface JKClassLiteralExpression : JKExpression {
JAVA_PRIMITIVE_CLASS,
JAVA_VOID_TYPE
}
}
}
interface JKAnnotationMemberValue : JKTreeElement
@@ -109,4 +109,8 @@ interface JKKtTryExpression : JKExpression {
interface JKKtTryCatchSection : JKTreeElement {
var parameter: JKParameter
var block: JKBlock
}
interface JKKtAnnotationArrayInitializerExpression : JKExpression, JKBranchElement {
val initializers: List<JKAnnotationMemberValue>
}
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.j2k.tree
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.impl.JKBranchElementBase
import org.jetbrains.kotlin.j2k.tree.impl.JKClassSymbol
import org.jetbrains.kotlin.resolve.jvm.JvmPrimitiveType
import kotlin.reflect.KProperty0
@@ -132,4 +133,65 @@ fun <T : JKElement> T.detached(from: JKElement): T =
also { it.detach(from) }
fun <T : JKBranchElement> T.invalidated(): T =
also { it.invalidate() }
also { it.invalidate() }
fun <R : JKTreeElement, T> applyRecursive(
element: R,
data: T,
onElementChanged: (JKTreeElement, JKTreeElement) -> Unit,
func: (JKTreeElement, T) -> JKTreeElement
): R {
fun <T> applyRecursiveToList(
element: JKTreeElement,
child: List<JKTreeElement>,
iter: MutableListIterator<Any>,
data: T,
func: (JKTreeElement, T) -> JKTreeElement
): List<JKTreeElement> {
val newChild = child.map {
func(it, data)
}
child.forEach { it.detach(element) }
iter.set(child)
newChild.forEach { it.attach(element) }
newChild.zip(child).forEach { (old, new) ->
if (old !== new) {
onElementChanged(new, old)
}
}
return newChild
}
if (element is JKBranchElementBase) {
val iter = element.children.listIterator()
while (iter.hasNext()) {
val child = iter.next()
if (child is List<*>) {
iter.set(applyRecursiveToList(element, child as List<JKTreeElement>, iter, data, func))
} else if (child is JKTreeElement) {
val newChild = func(child, data)
if (child !== newChild) {
child.detach(element)
iter.set(newChild)
newChild.attach(element)
onElementChanged(newChild, child)
}
} else {
error("unsupported child type: ${child::class}")
}
}
}
return element
}
fun <R : JKTreeElement> applyRecursive(
element: R,
func: (JKTreeElement) -> JKTreeElement
): R = applyRecursive(element, null, { _, _ -> }) { it, _ -> func(it) }
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.util.getJavaClassDescriptor
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.JKSymbolProvider
import org.jetbrains.kotlin.j2k.ast.ArrayType
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.kotlinTypeByName
@@ -59,6 +60,7 @@ fun JKExpression.type(symbolProvider: JKSymbolProvider): JKType? =
}
JKClassTypeImpl(symbol, listOf(classType.type), Nullability.NotNull)
}
is JKKtAnnotationArrayInitializerExpression -> JKNoTypeImpl //TODO
else -> TODO(this::class.java.toString())
}
@@ -166,6 +168,26 @@ fun JKClassSymbol.toKtType(): KotlinType? {
return classDescriptor?.defaultType
}
fun JKType.applyRecursive(transform: (JKType) -> JKType?): JKType =
transform(this) ?: when (this) {
is JKTypeParameterTypeImpl -> this
is JKClassTypeImpl ->
JKClassTypeImpl(
classReference,
parameters.map { it.applyRecursive(transform) },
nullability
)
is JKNoType -> this
is JKJavaVoidType -> this
is JKJavaPrimitiveType -> this
is JKJavaArrayType -> JKJavaArrayTypeImpl(type.applyRecursive(transform), nullability)
is JKContextType -> JKContextType
is JKJavaDisjunctionType ->
JKJavaDisjunctionTypeImpl(disjunctions.map { it.applyRecursive(transform) }, nullability)
is JKStarProjectionType -> this
else -> TODO(this::class.toString())
}
inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability): T =
if (nullability == newNullability) this
else when (this) {
@@ -181,22 +203,18 @@ inline fun <reified T : JKType> T.updateNullability(newNullability: Nullability)
} as T
fun <T : JKType> T.updateNullabilityRecursively(newNullability: Nullability): T =
if (nullability == newNullability) this
else when (this) {
is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(name, newNullability)
is JKClassTypeImpl ->
JKClassTypeImpl(
classReference,
parameters.map { it.updateNullabilityRecursively(newNullability) },
newNullability
)
is JKNoType -> this
is JKJavaVoidType -> this
is JKJavaPrimitiveType -> this
is JKJavaArrayType -> JKJavaArrayTypeImpl(type.updateNullabilityRecursively(newNullability), newNullability)
is JKContextType -> JKContextType
is JKJavaDisjunctionType -> this
else -> TODO(this::class.toString())
applyRecursive {
when (it) {
is JKTypeParameterTypeImpl -> JKTypeParameterTypeImpl(it.name, newNullability)
is JKClassTypeImpl ->
JKClassTypeImpl(
it.classReference,
it.parameters.map { it.updateNullabilityRecursively(newNullability) },
newNullability
)
is JKJavaArrayType -> JKJavaArrayTypeImpl(it.type.updateNullabilityRecursively(newNullability), newNullability)
else -> null
}
} as T
fun JKJavaMethod.returnTypeNullability(context: ConversionContext): Nullability =
@@ -330,4 +348,15 @@ private fun JKMethod.findSuperMethodSymbol(symbolProvider: JKSymbolProvider): JK
?.firstOrNull()
?.let {
symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol
}
}
fun JKType.replaceJavaClassWithKotlinClassType(symbolProvider: JKSymbolProvider): JKType =
applyRecursive { type ->
if (type is JKClassType && type.classReference.fqName == "java.lang.Class") {
JKClassTypeImpl(
symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.kClass),
type.parameters.map { it.replaceJavaClassWithKotlinClassType(symbolProvider) },
Nullability.NotNull
)
} else null
}
@@ -10,7 +10,9 @@ interface JKVisitor<out R, in D> {
fun visitClass(klass: JKClass, data: D): R = visitDeclaration(klass, data)
fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo, data: D): R = visitTreeElement(inheritanceInfo, data)
fun visitAnnotationList(annotationList: JKAnnotationList, data: D): R = visitTreeElement(annotationList, data)
fun visitAnnotation(annotation: JKAnnotation, data: D): R = visitTreeElement(annotation, data)
fun visitAnnotation(annotation: JKAnnotation, data: D): R = visitAnnotationMemberValue(annotation, data)
fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter, data: D): R = visitTreeElement(annotationParameter, data)
fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter, data: D): R = visitAnnotationParameter(annotationNameParameter, data)
fun visitAnnotationListOwner(annotationListOwner: JKAnnotationListOwner, data: D): R = visitTreeElement(annotationListOwner, data)
fun visitMethod(method: JKMethod, data: D): R = visitDeclaration(method, data)
fun visitVariable(variable: JKVariable, data: D): R = visitDeclaration(variable, data)
@@ -76,6 +78,7 @@ interface JKVisitor<out R, in D> {
fun visitForInStatement(forInStatement: JKForInStatement, data: D): R = visitStatement(forInStatement, data)
fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration, data: D): R = visitDeclaration(packageDeclaration, data)
fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression, data: D): R = visitExpression(classLiteralExpression, data)
fun visitAnnotationMemberValue(annotationMemberValue: JKAnnotationMemberValue, data: D): R = visitTreeElement(annotationMemberValue, data)
fun visitField(field: JKField, data: D): R = visitVariable(field, data)
fun visitJavaField(javaField: JKJavaField, data: D): R = visitField(javaField, data)
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R = visitMethod(javaMethod, data)
@@ -101,6 +104,7 @@ interface JKVisitor<out R, in D> {
fun visitJavaLabelSwitchCase(javaLabelSwitchCase: JKJavaLabelSwitchCase, data: D): R = visitJavaSwitchCase(javaLabelSwitchCase, data)
fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement, data: D): R = visitStatement(javaContinueStatement, data)
fun visitJavaSynchronizedStatement(javaSynchronizedStatement: JKJavaSynchronizedStatement, data: D): R = visitStatement(javaSynchronizedStatement, data)
fun visitJavaAnnotationMethod(javaAnnotationMethod: JKJavaAnnotationMethod, data: D): R = visitMethod(javaAnnotationMethod, data)
fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter, data: D): R = visitTreeElement(ktGetterOrSetter, data)
fun visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter: JKKtEmptyGetterOrSetter, data: D): R = visitKtGetterOrSetter(ktEmptyGetterOrSetter, data)
fun visitKtProperty(ktProperty: JKKtProperty, data: D): R = visitField(ktProperty, data)
@@ -123,4 +127,5 @@ interface JKVisitor<out R, in D> {
fun visitKtThrowExpression(ktThrowExpression: JKKtThrowExpression, data: D): R = visitExpression(ktThrowExpression, data)
fun visitKtTryExpression(ktTryExpression: JKKtTryExpression, data: D): R = visitExpression(ktTryExpression, data)
fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection, data: D): R = visitTreeElement(ktTryCatchSection, data)
fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression, data: D): R = visitExpression(ktAnnotationArrayInitializerExpression, data)
}
@@ -17,8 +17,12 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitInheritanceInfo(inheritanceInfo: JKInheritanceInfo, data: Nothing?) = visitInheritanceInfo(inheritanceInfo)
fun visitAnnotationList(annotationList: JKAnnotationList) = visitTreeElement(annotationList, null)
override fun visitAnnotationList(annotationList: JKAnnotationList, data: Nothing?) = visitAnnotationList(annotationList)
fun visitAnnotation(annotation: JKAnnotation) = visitTreeElement(annotation, null)
fun visitAnnotation(annotation: JKAnnotation) = visitAnnotationMemberValue(annotation, null)
override fun visitAnnotation(annotation: JKAnnotation, data: Nothing?) = visitAnnotation(annotation)
fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter) = visitTreeElement(annotationParameter, null)
override fun visitAnnotationParameter(annotationParameter: JKAnnotationParameter, data: Nothing?) = visitAnnotationParameter(annotationParameter)
fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter) = visitAnnotationParameter(annotationNameParameter, null)
override fun visitAnnotationNameParameter(annotationNameParameter: JKAnnotationNameParameter, data: Nothing?) = visitAnnotationNameParameter(annotationNameParameter)
fun visitAnnotationListOwner(annotationListOwner: JKAnnotationListOwner) = visitTreeElement(annotationListOwner, null)
override fun visitAnnotationListOwner(annotationListOwner: JKAnnotationListOwner, data: Nothing?) = visitAnnotationListOwner(annotationListOwner)
fun visitMethod(method: JKMethod) = visitDeclaration(method, null)
@@ -149,6 +153,8 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitPackageDeclaration(packageDeclaration: JKPackageDeclaration, data: Nothing?) = visitPackageDeclaration(packageDeclaration)
fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression) = visitExpression(classLiteralExpression, null)
override fun visitClassLiteralExpression(classLiteralExpression: JKClassLiteralExpression, data: Nothing?) = visitClassLiteralExpression(classLiteralExpression)
fun visitAnnotationMemberValue(annotationMemberValue: JKAnnotationMemberValue) = visitTreeElement(annotationMemberValue, null)
override fun visitAnnotationMemberValue(annotationMemberValue: JKAnnotationMemberValue, data: Nothing?) = visitAnnotationMemberValue(annotationMemberValue)
fun visitField(field: JKField) = visitVariable(field, null)
override fun visitField(field: JKField, data: Nothing?) = visitField(field)
fun visitJavaField(javaField: JKJavaField) = visitField(javaField, null)
@@ -199,6 +205,8 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitJavaContinueStatement(javaContinueStatement: JKJavaContinueStatement, data: Nothing?) = visitJavaContinueStatement(javaContinueStatement)
fun visitJavaSynchronizedStatement(javaSynchronizedStatement: JKJavaSynchronizedStatement) = visitStatement(javaSynchronizedStatement, null)
override fun visitJavaSynchronizedStatement(javaSynchronizedStatement: JKJavaSynchronizedStatement, data: Nothing?) = visitJavaSynchronizedStatement(javaSynchronizedStatement)
fun visitJavaAnnotationMethod(javaAnnotationMethod: JKJavaAnnotationMethod) = visitMethod(javaAnnotationMethod, null)
override fun visitJavaAnnotationMethod(javaAnnotationMethod: JKJavaAnnotationMethod, data: Nothing?) = visitJavaAnnotationMethod(javaAnnotationMethod)
fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter) = visitTreeElement(ktGetterOrSetter, null)
override fun visitKtGetterOrSetter(ktGetterOrSetter: JKKtGetterOrSetter, data: Nothing?) = visitKtGetterOrSetter(ktGetterOrSetter)
fun visitKtEmptyGetterOrSetter(ktEmptyGetterOrSetter: JKKtEmptyGetterOrSetter) = visitKtGetterOrSetter(ktEmptyGetterOrSetter, null)
@@ -243,4 +251,6 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitKtTryExpression(ktTryExpression: JKKtTryExpression, data: Nothing?) = visitKtTryExpression(ktTryExpression)
fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection) = visitTreeElement(ktTryCatchSection, null)
override fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection, data: Nothing?) = visitKtTryCatchSection(ktTryCatchSection)
fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression) = visitExpression(ktAnnotationArrayInitializerExpression, null)
override fun visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression, data: Nothing?) = visitKtAnnotationArrayInitializerExpression(ktAnnotationArrayInitializerExpression)
}