From abc4104ba7efe2fb36bd9974b418bf6410619533 Mon Sep 17 00:00:00 2001 From: Dimach Date: Mon, 30 Jul 2018 03:00:12 +0300 Subject: [PATCH] New J2K: Implement Array init conversions --- .../jetbrains/kotlin/j2k/ConversionsRunner.kt | 1 + .../kotlin/j2k/JavaToJKTreeBuilder.kt | 23 +++-- .../jetbrains/kotlin/j2k/NewCodeBuilder.kt | 16 ++-- .../conversions/ArrayInitializerConversion.kt | 83 +++++++++++++++++++ .../org/jetbrains/kotlin/j2k/tree/impl/j.kt | 12 ++- .../org/jetbrains/kotlin/j2k/tree/impl/jk.kt | 8 +- .../org/jetbrains/kotlin/j2k/tree/impl/k.kt | 5 +- j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt | 6 +- .../org/jetbrains/kotlin/j2k/tree/jk.kt | 1 + 9 files changed, 134 insertions(+), 21 deletions(-) create mode 100644 j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ArrayInitializerConversion.kt diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt index ada7eccc115..1ffe83ba75d 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/ConversionsRunner.kt @@ -23,6 +23,7 @@ object ConversionsRunner { private fun createRootConversion(context: ConversionContext) = batchPipe { + +ArrayInitializerConversion(context) +ModalityConversion(context) +ImplicitInitializerConversion() +DefaultArgumentsConversion(context) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt index de1116e72a4..bf8a708c86a 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/JavaToJKTreeBuilder.kt @@ -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()?.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() + val dimensions = mutableListOf() 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()?.type }.last()) + ) } } val constructedClass = classOrAnonymousClassReference?.resolve() diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt index 3e8add69606..830407ad3d5 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt @@ -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) { diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ArrayInitializerConversion.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ArrayInitializerConversion.kt new file mode 100644 index 00000000000..faa95923974 --- /dev/null +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/conversions/ArrayInitializerConversion.kt @@ -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, 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() +} \ No newline at end of file diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt index f0d1e2e2ac5..a783cb01e99 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/j.kt @@ -94,11 +94,13 @@ sealed class JKJavaQualifierImpl : JKQualifier { class JKJavaMethodCallExpressionImpl( override var identifier: JKMethodSymbol, - arguments: JKExpressionList + arguments: JKExpressionList, + typeArguments: List = emptyList() ) : JKJavaMethodCallExpression, JKBranchElementBase() { override fun accept(visitor: JKVisitor, data: D): R = visitor.visitJavaMethodCallExpression(this, data) override val arguments: JKExpressionList by child(arguments) + override var typeArguments: List by children(typeArguments) } class JKJavaNewExpressionImpl( @@ -114,11 +116,15 @@ class JKJavaDefaultNewExpressionImpl( override val classSymbol: JKClassSymbol ) : JKJavaDefaultNewExpression, JKElementBase() -class JKJavaNewEmptyArrayImpl(override var initializer: List) : JKJavaNewEmptyArray, JKElementBase() { +class JKJavaNewEmptyArrayImpl(initializer: List, type: JKTypeElement) : JKJavaNewEmptyArray, JKBranchElementBase() { + override val type by child(type) + override var initializer by children(initializer) override fun accept(visitor: JKVisitor, data: D): R = visitor.visitJavaNewEmptyArray(this, data) } -class JKJavaNewArrayImpl(override var initializer: List) : JKJavaNewArray, JKElementBase() { +class JKJavaNewArrayImpl(initializer: List, type: JKTypeElement) : JKJavaNewArray, JKBranchElementBase() { + override val type by child(type) + override var initializer by children(initializer) override fun accept(visitor: JKVisitor, data: D): R = visitor.visitJavaNewArray(this, data) } diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt index 64da1f7d5c6..6401b824f5d 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/jk.kt @@ -125,6 +125,8 @@ class JKPostfixExpressionImpl(expression: JKExpression, override var operator: J } class JKExpressionListImpl(expressions: List = emptyList()) : JKExpressionList, JKBranchElementBase() { + constructor(vararg expresions: JKExpression) : this(expresions.asList()) + override fun accept(visitor: JKVisitor, 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, + override var parameters: List = emptyList(), override val nullability: Nullability = Nullability.Default ) : JKClassType @@ -331,7 +333,9 @@ class JKMutabilityModifierImpl(override val mutability: Mutability) : JKMutabili } class JKLambdaExpressionImpl( - parameters: List, statement: JKStatement, returnType: JKTypeElement = JKTypeElementImpl(JKContextType) + parameters: List = 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) diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt index 4f258c6cbc4..1db146357a3 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/impl/k.kt @@ -65,11 +65,13 @@ sealed class JKKtQualifierImpl : JKQualifier, JKElementBase() { class JKKtCallExpressionImpl( override val identifier: JKMethodSymbol, - arguments: JKExpressionList + arguments: JKExpressionList, + typeArguments: List = emptyList() ) : JKKtMethodCallExpression, JKBranchElementBase() { override fun accept(visitor: JKVisitor, data: D): R = visitor.visitKtMethodCallExpression(this, data) override var arguments: JKExpressionList by child(arguments) + override var typeArguments: List by children(typeArguments) } class JKKtLiteralExpressionImpl( @@ -167,6 +169,7 @@ class JKKtAlsoCallExpressionImpl( ) ) ) + override var typeArguments: List by children(emptyList()) } class JKKtAssignmentStatementImpl( diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt index 5a8bd875821..ec8e342713e 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/j.kt @@ -44,11 +44,13 @@ interface JKJavaModifier : JKModifier { } interface JKJavaNewEmptyArray : JKExpression { - val initializer: List + val type: JKTypeElement + var initializer: List } interface JKJavaNewArray : JKExpression { - val initializer: List + val type: JKTypeElement + var initializer: List } interface JKJavaLiteralExpression : JKLiteralExpression diff --git a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt index 0319c1382ea..cf2156fcbbd 100644 --- a/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt +++ b/j2k/newSrc/org/jetbrains/kotlin/j2k/tree/jk.kt @@ -146,6 +146,7 @@ interface JKQualifiedExpression : JKExpression, JKAssignableExpression { interface JKMethodCallExpression : JKExpression, JKBranchElement { val identifier: JKMethodSymbol val arguments: JKExpressionList + var typeArguments: List } interface JKFieldAccessExpression : JKAssignableExpression {