New J2K: Add labeled statement
This commit is contained in:
committed by
Ilya Kirillov
parent
0a08467b45
commit
27526cf866
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user