New J2K: Implement Array init conversions

This commit is contained in:
Dimach
2018-07-30 03:00:12 +03:00
committed by Ilya Kirillov
parent f3ffb2acfd
commit abc4104ba7
9 changed files with 134 additions and 21 deletions
@@ -23,6 +23,7 @@ object ConversionsRunner {
private fun createRootConversion(context: ConversionContext) =
batchPipe {
+ArrayInitializerConversion(context)
+ModalityConversion(context)
+ImplicitInitializerConversion()
+DefaultArgumentsConversion(context)
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
@@ -161,27 +162,33 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
}
fun PsiArrayInitializerExpression.toJK(): JKExpression {
return JKJavaNewArrayImpl(initializers.map { it.toJK() })
return JKJavaNewArrayImpl(
initializers.map { it.toJK() },
JKTypeElementImpl(type?.toJK().safeAs<JKJavaArrayType>()?.type ?: JKContextType)
)
}
fun PsiNewExpression.toJK(): JKExpression {
assert(this is PsiNewExpressionImpl)
if ((this as PsiNewExpressionImpl).findChildByRole(ChildRole.LBRACKET) != null) {
require(this is PsiNewExpressionImpl)
if (findChildByRole(ChildRole.LBRACKET) != null) {
return arrayInitializer?.toJK() ?: run {
val dimensions = mutableListOf<PsiLiteralExpression?>()
val dimensions = mutableListOf<PsiExpression?>()
var child = firstChild
while (child != null) {
if (child.node.elementType == JavaTokenType.LBRACKET) {
child = child.nextSibling
if (child.node.elementType == JavaTokenType.RBRACKET) {
dimensions.add(null)
dimensions += if (child.node.elementType == JavaTokenType.RBRACKET) {
null
} else {
dimensions.add(child as PsiLiteralExpression?)
child as PsiExpression? //TODO
}
}
child = child.nextSibling
}
JKJavaNewEmptyArrayImpl(dimensions.map { it?.toJK() })
JKJavaNewEmptyArrayImpl(
dimensions.map { it?.toJK() ?: JKStubExpressionImpl() },
JKTypeElementImpl(generateSequence(type?.toJK()) { it.safeAs<JKJavaArrayType>()?.type }.last())
)
}
}
val constructedClass = classOrAnonymousClassReference?.resolve()
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class NewCodeBuilder {
@@ -274,6 +273,15 @@ class NewCodeBuilder {
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
printer.printWithNoIndent(FqName(methodCallExpression.identifier.fqName).shortName().asString())
if (methodCallExpression.typeArguments.isNotEmpty()) {
printer.printWithNoIndent("<")
methodCallExpression.typeArguments.firstOrNull()?.accept(this)
for (i in 1..methodCallExpression.typeArguments.lastIndex) {
printer.printWithNoIndent(", ")
methodCallExpression.typeArguments[i].accept(this)
}
printer.printWithNoIndent(">")
}
printer.par {
methodCallExpression.arguments.accept(this)
}
@@ -312,7 +320,7 @@ class NewCodeBuilder {
}
printer.printWithNoIndent(" ", localVariable.name.value)
if(localVariable.type.type != JKContextType) {
if (localVariable.type.type != JKContextType) {
printer.printWithNoIndent(": ")
localVariable.type.accept(this)
}
@@ -347,9 +355,7 @@ class NewCodeBuilder {
}
override fun visitTypeElement(typeElement: JKTypeElement) {
val type = typeElement.type
renderType(type)
renderType(typeElement.type)
}
override fun visitBlock(block: JKBlock) {
@@ -0,0 +1,83 @@
/*
* Copyright 2010-2018 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.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.resolve.CollectionLiteralResolver
class ArrayInitializerConversion(private val context: ConversionContext) : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
var newElement = element
if (element is JKJavaNewArray) {
val arrayType = element.type.type
newElement = JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName(
if (arrayType is JKJavaPrimitiveType)
CollectionLiteralResolver.PRIMITIVE_TYPE_TO_ARRAY[PrimitiveType.valueOf(arrayType.jvmPrimitiveType.name)]!!.asString()
else
CollectionLiteralResolver.ARRAY_OF_FUNCTION.asString()
),
JKExpressionListImpl(element.initializer.also { element.initializer = emptyList() })
)
} else if (element is JKJavaNewEmptyArray) {
newElement = buildArrayInitializer(element.initializer.also { element.initializer = emptyList() }, element.type.type)
}
return recurse(newElement)
}
private fun buildArrayInitializer(dimensions: List<JKExpression>, type: JKType): JKExpression {
if (dimensions.size == 1) {
val methodOrConstructorReference = if (type !is JKJavaPrimitiveType)
context.symbolProvider.provideByFqName("kotlin/arrayOfNulls")
else
JKUnresolvedMethod(arrayFqName(type).replace('/', '.')/*TODO resolve real reference*/)
return JKJavaMethodCallExpressionImpl(
methodOrConstructorReference,
JKExpressionListImpl(dimensions[0]),
if (type is JKJavaPrimitiveType) emptyList() else listOf(JKTypeElementImpl(type))
)
}
if (dimensions[1] !is JKStubExpression) {
return JKJavaMethodCallExpressionImpl(
JKUnresolvedMethod("kotlin.Array"),//TODO resolve real reference
JKExpressionListImpl(
dimensions[0],
JKLambdaExpressionImpl(
statement = JKExpressionStatementImpl(buildArrayInitializer(dimensions.subList(1, dimensions.size), type))
)
)
)
}
var resultType = JKClassTypeImpl(
context.symbolProvider.provideByFqName(arrayFqName(type)),
if (type is JKJavaPrimitiveType) emptyList() else listOf(type),
Nullability.NotNull
)
for (i in 0 until dimensions.size - 2) {
resultType = JKClassTypeImpl(
context.symbolProvider.provideByFqName(KotlinBuiltIns.FQ_NAMES.array.asString()),
listOf(resultType),
Nullability.NotNull
)
}
return JKJavaMethodCallExpressionImpl(
context.symbolProvider.provideByFqName("kotlin/arrayOfNulls"),
JKExpressionListImpl(dimensions[0]),
listOf(JKTypeElementImpl(resultType))
)
}
private fun arrayFqName(type: JKType): String = if (type is JKJavaPrimitiveType)
PrimitiveType.valueOf(type.jvmPrimitiveType.name).arrayTypeFqName.asString()
else KotlinBuiltIns.FQ_NAMES.array.asString()
}
@@ -94,11 +94,13 @@ sealed class JKJavaQualifierImpl : JKQualifier {
class JKJavaMethodCallExpressionImpl(
override var identifier: JKMethodSymbol,
arguments: JKExpressionList
arguments: JKExpressionList,
typeArguments: List<JKTypeElement> = emptyList()
) : JKJavaMethodCallExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaMethodCallExpression(this, data)
override val arguments: JKExpressionList by child(arguments)
override var typeArguments: List<JKTypeElement> by children(typeArguments)
}
class JKJavaNewExpressionImpl(
@@ -114,11 +116,15 @@ class JKJavaDefaultNewExpressionImpl(
override val classSymbol: JKClassSymbol
) : JKJavaDefaultNewExpression, JKElementBase()
class JKJavaNewEmptyArrayImpl(override var initializer: List<JKLiteralExpression?>) : JKJavaNewEmptyArray, JKElementBase() {
class JKJavaNewEmptyArrayImpl(initializer: List<JKExpression>, type: JKTypeElement) : JKJavaNewEmptyArray, JKBranchElementBase() {
override val type by child(type)
override var initializer by children(initializer)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaNewEmptyArray(this, data)
}
class JKJavaNewArrayImpl(override var initializer: List<JKExpression>) : JKJavaNewArray, JKElementBase() {
class JKJavaNewArrayImpl(initializer: List<JKExpression>, type: JKTypeElement) : JKJavaNewArray, JKBranchElementBase() {
override val type by child(type)
override var initializer by children(initializer)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaNewArray(this, data)
}
@@ -125,6 +125,8 @@ class JKPostfixExpressionImpl(expression: JKExpression, override var operator: J
}
class JKExpressionListImpl(expressions: List<JKExpression> = emptyList()) : JKExpressionList, JKBranchElementBase() {
constructor(vararg expresions: JKExpression) : this(expresions.asList())
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitExpressionList(this, data)
override var expressions by children(expressions)
@@ -181,7 +183,7 @@ class JKTypeElementImpl(override val type: JKType) : JKTypeElement, JKElementBas
class JKClassTypeImpl(
override val classReference: JKClassSymbol,
override var parameters: List<JKType>,
override var parameters: List<JKType> = emptyList(),
override val nullability: Nullability = Nullability.Default
) : JKClassType
@@ -331,7 +333,9 @@ class JKMutabilityModifierImpl(override val mutability: Mutability) : JKMutabili
}
class JKLambdaExpressionImpl(
parameters: List<JKParameter>, statement: JKStatement, returnType: JKTypeElement = JKTypeElementImpl(JKContextType)
parameters: List<JKParameter> = listOf(
JKParameterImpl(JKTypeElementImpl(JKJavaVoidType), JKNameIdentifierImpl("it"), JKModifierListImpl())
), statement: JKStatement, returnType: JKTypeElement = JKTypeElementImpl(JKContextType)
) : JKLambdaExpression, JKBranchElementBase() {
override var statement by child(statement)
override val returnType by child(returnType)
@@ -65,11 +65,13 @@ sealed class JKKtQualifierImpl : JKQualifier, JKElementBase() {
class JKKtCallExpressionImpl(
override val identifier: JKMethodSymbol,
arguments: JKExpressionList
arguments: JKExpressionList,
typeArguments: List<JKTypeElement> = emptyList()
) : JKKtMethodCallExpression, JKBranchElementBase() {
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtMethodCallExpression(this, data)
override var arguments: JKExpressionList by child(arguments)
override var typeArguments: List<JKTypeElement> by children(typeArguments)
}
class JKKtLiteralExpressionImpl(
@@ -167,6 +169,7 @@ class JKKtAlsoCallExpressionImpl(
)
)
)
override var typeArguments: List<JKTypeElement> by children(emptyList())
}
class JKKtAssignmentStatementImpl(
@@ -44,11 +44,13 @@ interface JKJavaModifier : JKModifier {
}
interface JKJavaNewEmptyArray : JKExpression {
val initializer: List<JKLiteralExpression?>
val type: JKTypeElement
var initializer: List<JKExpression>
}
interface JKJavaNewArray : JKExpression {
val initializer: List<JKExpression>
val type: JKTypeElement
var initializer: List<JKExpression>
}
interface JKJavaLiteralExpression : JKLiteralExpression
@@ -146,6 +146,7 @@ interface JKQualifiedExpression : JKExpression, JKAssignableExpression {
interface JKMethodCallExpression : JKExpression, JKBranchElement {
val identifier: JKMethodSymbol
val arguments: JKExpressionList
var typeArguments: List<JKTypeElement>
}
interface JKFieldAccessExpression : JKAssignableExpression {