New J2K: Add labeled statement

This commit is contained in:
Ilya Kirillov
2018-10-17 13:11:33 +03:00
committed by Ilya Kirillov
parent 0a08467b45
commit 27526cf866
12 changed files with 209 additions and 11 deletions
@@ -51,6 +51,7 @@ object ConversionsRunner {
+SwitchStatementConversion(context)
+InstanceofConversion()
+ForConversion(context)
+LabeledStatementConversion()
}
fun doApply(trees: List<JKTreeElement>, context: ConversionContext) {
@@ -21,6 +21,7 @@ import com.intellij.psi.*
import com.intellij.psi.JavaTokenType.SUPER_KEYWORD
import com.intellij.psi.JavaTokenType.THIS_KEYWORD
import com.intellij.psi.impl.source.tree.ChildRole
import com.intellij.psi.impl.source.tree.java.PsiLabeledStatementImpl
import com.intellij.psi.impl.source.tree.java.PsiLiteralExpressionImpl
import com.intellij.psi.impl.source.tree.java.PsiNewExpressionImpl
import com.intellij.psi.impl.source.tree.java.PsiReferenceExpressionImpl
@@ -397,6 +398,10 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
} ?: JKLabelEmptyImpl()
JKContinueStatementImpl(label)
}
is PsiLabeledStatement -> {
val (labels, statement) = collectLabels()
JKLabeledStatementImpl(statement.toJK(), labels.map { JKNameIdentifierImpl(it.text) })
}
else -> TODO("for ${this::class}")
}.also {
if (this != null) backAnnotation[it] = this
@@ -404,6 +409,14 @@ class JavaToJKTreeBuilder(var symbolProvider: JKSymbolProvider) {
}
}
//TODO better way than generateSequence.last??
fun PsiLabeledStatement.collectLabels(): Pair<List<PsiIdentifier>, PsiStatement> =
generateSequence(emptyList<PsiIdentifier>() to this as PsiStatement) { (labels, statement) ->
if (statement !is PsiLabeledStatementImpl) return@generateSequence null
(labels + statement.labelIdentifier) to statement.statement!!
}.last()
private inner class ModifierMapper {
fun PsiModifierList?.toJK(finalAsMutability: Boolean = false): JKModifierList {
@@ -315,6 +315,18 @@ class NewCodeBuilder {
printer.printWithNoIndent(" ")
}
override fun visitLabeledStatement(labeledStatement: JKLabeledStatement) {
for (label in labeledStatement.labels) {
label.accept(this)
printer.printWithNoIndent("@")
}
labeledStatement.statement.accept(this)
}
override fun visitNameIdentifier(nameIdentifier: JKNameIdentifier) {
printer.printWithNoIndent(nameIdentifier.value)
}
override fun visitPostfixExpression(postfixExpression: JKPostfixExpression) {
postfixExpression.expression.accept(this)
printer.printWithNoIndent(postfixExpression.operator.operatorText)
@@ -392,6 +404,13 @@ class NewCodeBuilder {
printer.printlnWithNoIndent()
}
override fun visitKtConvertedFromForLoopSyntheticWhileStatement(
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
) {
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclaration.accept(this)
printer.printlnWithNoIndent()
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
}
private fun renderType(type: JKType) {
when (type) {
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.j2k.conversions
import com.intellij.psi.*
import org.jetbrains.kotlin.j2k.ConversionContext
import org.jetbrains.kotlin.j2k.ReferenceSearcher
import org.jetbrains.kotlin.j2k.hasWriteAccesses
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
@@ -30,18 +28,18 @@ class ForConversion(private val context: ConversionContext) : RecursiveApplicabl
private fun convertToWhile(loopStatement: JKJavaForLoopStatement): JKStatement? {
val whileBody = createWhileBody(loopStatement)
val whileStatement =
JKWhileStatementImpl(
if (loopStatement.condition !is JKStubExpression) loopStatement.condition.detached()
else JKKtLiteralExpressionImpl("true", JKLiteralExpression.LiteralType.BOOLEAN),
whileBody
)
val condition =
if (loopStatement.condition !is JKStubExpression) loopStatement.condition.detached()
else JKKtLiteralExpressionImpl("true", JKLiteralExpression.LiteralType.BOOLEAN)
val whileStatement = JKWhileStatementImpl(condition, whileBody)
if (loopStatement.initializer is JKEmptyStatement) return whileStatement
//TODO check for error conflict
return JKBlockStatementImpl(JKBlockImpl(listOf(loopStatement.initializer.detached(), whileStatement)))
return JKKtConvertedFromForLoopSyntheticWhileStatementImpl(
loopStatement.initializer.detached(),
JKWhileStatementImpl(condition, whileBody)
)
}
private fun createWhileBody(loopStatement: JKJavaForLoopStatement): JKStatement {
@@ -0,0 +1,27 @@
/*
* 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.j2k.blockStatement
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
class LabeledStatementConversion : RecursiveApplicableConversionBase() {
override fun applyToElement(element: JKTreeElement): JKTreeElement {
if (element !is JKLabeledStatement) return recurse(element)
val statement = element.statement as? JKKtConvertedFromForLoopSyntheticWhileStatementImpl ?: return recurse(element)
return recurse(
JKBlockStatementWithoutBracketsImpl(
JKBlockImpl(
statement::variableDeclaration.detached(),
JKLabeledStatementImpl(statement::whileStatement.detached(), element::labels.detached())
)
)
)
}
}
@@ -0,0 +1,108 @@
/*
* 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
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.j2k.conversions.multiResolveFqName
import org.jetbrains.kotlin.j2k.conversions.resolveFqName
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.psi.KtNamedFunction
fun kotlinTypeByName(name: String, symbolProvider: JKSymbolProvider): JKClassType {
val symbol =
symbolProvider.provideDirectSymbol(
resolveFqName(ClassId.fromString(name), symbolProvider.symbolsByPsi.keys.first())!!
) as JKClassSymbol
return JKClassTypeImpl(symbol, emptyList())
}
private fun JKKtOperatorToken.methodSymbol(
leftType: JKType,
rightType: JKType,
symbolProvider: JKSymbolProvider
): JKMethodSymbol {
val classSymbol =
when (leftType) {
is JKClassType -> leftType.classReference as JKMultiverseKtClassSymbol
is JKJavaPrimitiveType -> {
val psiClass = resolveFqName(
ClassId.fromString(leftType.jvmPrimitiveType.primitiveType.typeFqName.asString()),
symbolProvider.symbolsByPsi.keys.first()
)!!
symbolProvider.provideDirectSymbol(psiClass) as JKMultiverseKtClassSymbol
}
else ->
TODO(leftType::class.java.toString())
}
val operatorNames =
if (operatorName == "equals") listOf("equals", "compareTo")
else listOf(operatorName)
return classSymbol.target.declarations// todo look for extensions
.asSequence()
.filterIsInstance<KtNamedFunction>()
.filter { it.name in operatorNames }
.mapNotNull { symbolProvider.provideDirectSymbol(it) as? JKMethodSymbol }
.firstOrNull { it.parameterTypes.singleOrNull()?.takeIf { it.isSubtypeOf(rightType, symbolProvider) } != null }!!
}
fun kotlinBinaryExpression(
left: JKExpression,
right: JKExpression,
token: JKKtOperatorToken,
context: ConversionContext
): JKBinaryExpression? {
val leftType = left.type(context)
val rightType = right.type(context)
val methodSymbol = token.methodSymbol(leftType, rightType, context.symbolProvider)
return JKBinaryExpressionImpl(left, right, JKKtOperatorImpl(token, methodSymbol))
}
fun untilToExpression(
from: JKExpression,
to: JKExpression,
conversionContext: ConversionContext,
psiContext: PsiElement
): JKKtOperatorExpression =
rangeExpression(
from,
to,
"until",
conversionContext,
psiContext
)
fun downToExpression(
from: JKExpression,
to: JKExpression,
conversionContext: ConversionContext,
psiContext: PsiElement
): JKKtOperatorExpression =
rangeExpression(
from,
to,
"downTo",
conversionContext,
psiContext
)
fun rangeExpression(
from: JKExpression,
to: JKExpression,
operatorName: String,
conversionContext: ConversionContext,
psiContext: PsiElement
): JKKtOperatorExpressionImpl {
val symbol = conversionContext.symbolProvider.provideDirectSymbol(
multiResolveFqName(ClassId.fromString("kotlin/ranges/$operatorName"), psiContext).first()
) as JKMethodSymbol
return JKKtOperatorExpressionImpl(from, symbol, to)
}
fun blockStatement(vararg statements: JKStatement) =
JKBlockStatementImpl(JKBlockImpl(statements.toList()))
@@ -394,4 +394,10 @@ class JKLabelTextImpl(label: JKNameIdentifier) : JKLabelText, JKBranchElementBas
class JKContinueStatementImpl(label: JKLabel) : JKContinueStatement, JKBranchElementBase() {
override var label: JKLabel by child(label)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitContinueStatement(this, data)
}
class JKLabeledStatementImpl(statement: JKStatement, labels: List<JKNameIdentifier>) : JKLabeledStatement, JKBranchElementBase() {
override var statement: JKStatement by child(statement)
override val labels: List<JKNameIdentifier> by children(labels)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitLabeledStatement(this, data)
}
@@ -286,3 +286,13 @@ class JKKtOperatorExpressionImpl(
override var argument: JKExpression by child(argument)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R = visitor.visitKtOperatorExpression(this, data)
}
class JKKtConvertedFromForLoopSyntheticWhileStatementImpl(
variableDeclaration: JKStatement,
whileStatement: JKWhileStatement
) : JKKtConvertedFromForLoopSyntheticWhileStatement, JKBranchElementBase(), PsiOwner by PsiOwnerImpl() {
override var variableDeclaration: JKStatement by child(variableDeclaration)
override var whileStatement: JKWhileStatement by child(whileStatement)
override fun <R, D> accept(visitor: JKVisitor<R, D>, data: D): R =
visitor.visitKtConvertedFromForLoopSyntheticWhileStatement(this, data)
}
@@ -261,4 +261,9 @@ interface JKLabelText : JKLabel {
interface JKContinueStatement : JKStatement {
var label: JKLabel
}
interface JKLabeledStatement : JKStatement {
var statement: JKStatement
val labels: List<JKNameIdentifier>
}
@@ -97,4 +97,9 @@ interface JKKtOperatorExpression : JKExpression {
var receiver: JKExpression
var identifier: JKMethodSymbol
var argument: JKExpression
}
interface JKKtConvertedFromForLoopSyntheticWhileStatement : JKStatement {
var variableDeclaration: JKStatement
var whileStatement: JKWhileStatement
}
@@ -58,6 +58,7 @@ interface JKVisitor<out R, in D> {
fun visitLabelEmpty(labelEmpty: JKLabelEmpty, data: D): R = visitLabel(labelEmpty, data)
fun visitLabelText(labelText: JKLabelText, data: D): R = visitLabel(labelText, data)
fun visitContinueStatement(continueStatement: JKContinueStatement, data: D): R = visitStatement(continueStatement, data)
fun visitLabeledStatement(labeledStatement: JKLabeledStatement, data: D): R = visitStatement(labeledStatement, data)
fun visitJavaField(javaField: JKJavaField, data: D): R = visitField(javaField, data)
fun visitJavaMethod(javaMethod: JKJavaMethod, data: D): R = visitMethod(javaMethod, data)
fun visitJavaMethodCallExpression(javaMethodCallExpression: JKJavaMethodCallExpression, data: D): R = visitMethodCallExpression(javaMethodCallExpression, data)
@@ -97,4 +98,5 @@ interface JKVisitor<out R, in D> {
fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration, data: D): R = visitDeclaration(ktInitDeclaration, data)
fun visitKtForInStatement(ktForInStatement: JKKtForInStatement, data: D): R = visitStatement(ktForInStatement, data)
fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression, data: D): R = visitExpression(ktOperatorExpression, data)
fun visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement, data: D): R = visitStatement(ktConvertedFromForLoopSyntheticWhileStatement, data)
}
@@ -113,6 +113,8 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitLabelText(labelText: JKLabelText, data: Nothing?) = visitLabelText(labelText)
fun visitContinueStatement(continueStatement: JKContinueStatement) = visitStatement(continueStatement, null)
override fun visitContinueStatement(continueStatement: JKContinueStatement, data: Nothing?) = visitContinueStatement(continueStatement)
fun visitLabeledStatement(labeledStatement: JKLabeledStatement) = visitStatement(labeledStatement, null)
override fun visitLabeledStatement(labeledStatement: JKLabeledStatement, data: Nothing?) = visitLabeledStatement(labeledStatement)
fun visitJavaField(javaField: JKJavaField) = visitField(javaField, null)
override fun visitJavaField(javaField: JKJavaField, data: Nothing?) = visitJavaField(javaField)
fun visitJavaMethod(javaMethod: JKJavaMethod) = visitMethod(javaMethod, null)
@@ -191,4 +193,6 @@ interface JKVisitorVoid : JKVisitor<Unit, Nothing?> {
override fun visitKtForInStatement(ktForInStatement: JKKtForInStatement, data: Nothing?) = visitKtForInStatement(ktForInStatement)
fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression) = visitExpression(ktOperatorExpression, null)
override fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression, data: Nothing?) = visitKtOperatorExpression(ktOperatorExpression)
fun visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement) = visitStatement(ktConvertedFromForLoopSyntheticWhileStatement, null)
override fun visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement, data: Nothing?) = visitKtConvertedFromForLoopSyntheticWhileStatement(ktConvertedFromForLoopSyntheticWhileStatement)
}