New J2K: Implement Array init conversions
This commit is contained in:
@@ -23,6 +23,7 @@ object ConversionsRunner {
|
|||||||
|
|
||||||
private fun createRootConversion(context: ConversionContext) =
|
private fun createRootConversion(context: ConversionContext) =
|
||||||
batchPipe {
|
batchPipe {
|
||||||
|
+ArrayInitializerConversion(context)
|
||||||
+ModalityConversion(context)
|
+ModalityConversion(context)
|
||||||
+ImplicitInitializerConversion()
|
+ImplicitInitializerConversion()
|
||||||
+DefaultArgumentsConversion(context)
|
+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.*
|
||||||
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
|
import org.jetbrains.kotlin.j2k.tree.JKLiteralExpression.LiteralType.*
|
||||||
import org.jetbrains.kotlin.j2k.tree.impl.*
|
import org.jetbrains.kotlin.j2k.tree.impl.*
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
|
|
||||||
class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
|
class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
|
||||||
@@ -161,27 +162,33 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun PsiArrayInitializerExpression.toJK(): JKExpression {
|
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 {
|
fun PsiNewExpression.toJK(): JKExpression {
|
||||||
assert(this is PsiNewExpressionImpl)
|
require(this is PsiNewExpressionImpl)
|
||||||
if ((this as PsiNewExpressionImpl).findChildByRole(ChildRole.LBRACKET) != null) {
|
if (findChildByRole(ChildRole.LBRACKET) != null) {
|
||||||
return arrayInitializer?.toJK() ?: run {
|
return arrayInitializer?.toJK() ?: run {
|
||||||
val dimensions = mutableListOf<PsiLiteralExpression?>()
|
val dimensions = mutableListOf<PsiExpression?>()
|
||||||
var child = firstChild
|
var child = firstChild
|
||||||
while (child != null) {
|
while (child != null) {
|
||||||
if (child.node.elementType == JavaTokenType.LBRACKET) {
|
if (child.node.elementType == JavaTokenType.LBRACKET) {
|
||||||
child = child.nextSibling
|
child = child.nextSibling
|
||||||
if (child.node.elementType == JavaTokenType.RBRACKET) {
|
dimensions += if (child.node.elementType == JavaTokenType.RBRACKET) {
|
||||||
dimensions.add(null)
|
null
|
||||||
} else {
|
} else {
|
||||||
dimensions.add(child as PsiLiteralExpression?)
|
child as PsiExpression? //TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
child = child.nextSibling
|
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()
|
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.j2k.tree.visitors.JKVisitorVoid
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.utils.Printer
|
import org.jetbrains.kotlin.utils.Printer
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
|
||||||
|
|
||||||
class NewCodeBuilder {
|
class NewCodeBuilder {
|
||||||
|
|
||||||
@@ -274,6 +273,15 @@ class NewCodeBuilder {
|
|||||||
|
|
||||||
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
|
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
|
||||||
printer.printWithNoIndent(FqName(methodCallExpression.identifier.fqName).shortName().asString())
|
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 {
|
printer.par {
|
||||||
methodCallExpression.arguments.accept(this)
|
methodCallExpression.arguments.accept(this)
|
||||||
}
|
}
|
||||||
@@ -312,7 +320,7 @@ class NewCodeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
printer.printWithNoIndent(" ", localVariable.name.value)
|
printer.printWithNoIndent(" ", localVariable.name.value)
|
||||||
if(localVariable.type.type != JKContextType) {
|
if (localVariable.type.type != JKContextType) {
|
||||||
printer.printWithNoIndent(": ")
|
printer.printWithNoIndent(": ")
|
||||||
localVariable.type.accept(this)
|
localVariable.type.accept(this)
|
||||||
}
|
}
|
||||||
@@ -347,9 +355,7 @@ class NewCodeBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun visitTypeElement(typeElement: JKTypeElement) {
|
override fun visitTypeElement(typeElement: JKTypeElement) {
|
||||||
val type = typeElement.type
|
renderType(typeElement.type)
|
||||||
|
|
||||||
renderType(type)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun visitBlock(block: JKBlock) {
|
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(
|
class JKJavaMethodCallExpressionImpl(
|
||||||
override var identifier: JKMethodSymbol,
|
override var identifier: JKMethodSymbol,
|
||||||
arguments: JKExpressionList
|
arguments: JKExpressionList,
|
||||||
|
typeArguments: List<JKTypeElement> = emptyList()
|
||||||
) : JKJavaMethodCallExpression, JKBranchElementBase() {
|
) : JKJavaMethodCallExpression, JKBranchElementBase() {
|
||||||
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaMethodCallExpression(this, data)
|
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitJavaMethodCallExpression(this, data)
|
||||||
|
|
||||||
override val arguments: JKExpressionList by child(arguments)
|
override val arguments: JKExpressionList by child(arguments)
|
||||||
|
override var typeArguments: List<JKTypeElement> by children(typeArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
class JKJavaNewExpressionImpl(
|
class JKJavaNewExpressionImpl(
|
||||||
@@ -114,11 +116,15 @@ class JKJavaDefaultNewExpressionImpl(
|
|||||||
override val classSymbol: JKClassSymbol
|
override val classSymbol: JKClassSymbol
|
||||||
) : JKJavaDefaultNewExpression, JKElementBase()
|
) : 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)
|
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)
|
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() {
|
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 fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitExpressionList(this, data)
|
||||||
|
|
||||||
override var expressions by children(expressions)
|
override var expressions by children(expressions)
|
||||||
@@ -181,7 +183,7 @@ class JKTypeElementImpl(override val type: JKType) : JKTypeElement, JKElementBas
|
|||||||
|
|
||||||
class JKClassTypeImpl(
|
class JKClassTypeImpl(
|
||||||
override val classReference: JKClassSymbol,
|
override val classReference: JKClassSymbol,
|
||||||
override var parameters: List<JKType>,
|
override var parameters: List<JKType> = emptyList(),
|
||||||
override val nullability: Nullability = Nullability.Default
|
override val nullability: Nullability = Nullability.Default
|
||||||
) : JKClassType
|
) : JKClassType
|
||||||
|
|
||||||
@@ -331,7 +333,9 @@ class JKMutabilityModifierImpl(override val mutability: Mutability) : JKMutabili
|
|||||||
}
|
}
|
||||||
|
|
||||||
class JKLambdaExpressionImpl(
|
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() {
|
) : JKLambdaExpression, JKBranchElementBase() {
|
||||||
override var statement by child(statement)
|
override var statement by child(statement)
|
||||||
override val returnType by child(returnType)
|
override val returnType by child(returnType)
|
||||||
|
|||||||
@@ -65,11 +65,13 @@ sealed class JKKtQualifierImpl : JKQualifier, JKElementBase() {
|
|||||||
|
|
||||||
class JKKtCallExpressionImpl(
|
class JKKtCallExpressionImpl(
|
||||||
override val identifier: JKMethodSymbol,
|
override val identifier: JKMethodSymbol,
|
||||||
arguments: JKExpressionList
|
arguments: JKExpressionList,
|
||||||
|
typeArguments: List<JKTypeElement> = emptyList()
|
||||||
) : JKKtMethodCallExpression, JKBranchElementBase() {
|
) : JKKtMethodCallExpression, JKBranchElementBase() {
|
||||||
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtMethodCallExpression(this, data)
|
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 arguments: JKExpressionList by child(arguments)
|
||||||
|
override var typeArguments: List<JKTypeElement> by children(typeArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
class JKKtLiteralExpressionImpl(
|
class JKKtLiteralExpressionImpl(
|
||||||
@@ -167,6 +169,7 @@ class JKKtAlsoCallExpressionImpl(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
override var typeArguments: List<JKTypeElement> by children(emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
class JKKtAssignmentStatementImpl(
|
class JKKtAssignmentStatementImpl(
|
||||||
|
|||||||
@@ -44,11 +44,13 @@ interface JKJavaModifier : JKModifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface JKJavaNewEmptyArray : JKExpression {
|
interface JKJavaNewEmptyArray : JKExpression {
|
||||||
val initializer: List<JKLiteralExpression?>
|
val type: JKTypeElement
|
||||||
|
var initializer: List<JKExpression>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JKJavaNewArray : JKExpression {
|
interface JKJavaNewArray : JKExpression {
|
||||||
val initializer: List<JKExpression>
|
val type: JKTypeElement
|
||||||
|
var initializer: List<JKExpression>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JKJavaLiteralExpression : JKLiteralExpression
|
interface JKJavaLiteralExpression : JKLiteralExpression
|
||||||
|
|||||||
@@ -146,6 +146,7 @@ interface JKQualifiedExpression : JKExpression, JKAssignableExpression {
|
|||||||
interface JKMethodCallExpression : JKExpression, JKBranchElement {
|
interface JKMethodCallExpression : JKExpression, JKBranchElement {
|
||||||
val identifier: JKMethodSymbol
|
val identifier: JKMethodSymbol
|
||||||
val arguments: JKExpressionList
|
val arguments: JKExpressionList
|
||||||
|
var typeArguments: List<JKTypeElement>
|
||||||
}
|
}
|
||||||
|
|
||||||
interface JKFieldAccessExpression : JKAssignableExpression {
|
interface JKFieldAccessExpression : JKAssignableExpression {
|
||||||
|
|||||||
Reference in New Issue
Block a user