Java to Kotlin converter: working on not loosing comments - CommentConverter is passed when converting to Kotlin

This commit is contained in:
Valentin Kipyatkov
2014-06-17 14:11:08 +04:00
parent c4bac83cc9
commit d01a2237b5
37 changed files with 308 additions and 254 deletions
@@ -20,7 +20,7 @@ import com.intellij.psi.*
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.ast.Element import org.jetbrains.jet.j2k.ast.Element
class CommentConverter(private val topElement: PsiElement) { class CommentConverter(private val topElement: PsiElement?) {
private enum class CommentPlacement { private enum class CommentPlacement {
Before Before
SameLineBefore SameLineBefore
@@ -42,7 +42,7 @@ class CommentConverter(private val topElement: PsiElement) {
private val allComments: List<CommentInfo> = run { private val allComments: List<CommentInfo> = run {
val list = ArrayList<CommentInfo>() val list = ArrayList<CommentInfo>()
topElement.accept(object : JavaRecursiveElementVisitor(){ topElement?.accept(object : JavaRecursiveElementVisitor(){
override fun visitComment(comment: PsiComment) { override fun visitComment(comment: PsiComment) {
list.add(CommentInfo(comment)) list.add(CommentInfo(comment))
} }
@@ -55,4 +55,8 @@ class CommentConverter(private val topElement: PsiElement) {
} }
*/ */
class object {
val Dummy: CommentConverter = CommentConverter(null)
}
} }
+1 -1
View File
@@ -60,7 +60,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
= Converter(project, settings, conversionScope, State(typeConverter, state.methodReturnType, state.expressionVisitorFactory, factory)) = Converter(project, settings, conversionScope, State(typeConverter, state.methodReturnType, state.expressionVisitorFactory, factory))
public fun elementToKotlin(element: PsiElement): String public fun elementToKotlin(element: PsiElement): String
= convertTopElement(element)?.toKotlin(/*CommentConverter(element)*/) ?: "" = convertTopElement(element)?.toKotlin(CommentConverter(element)) ?: ""
private fun convertTopElement(element: PsiElement?): Element? = when(element) { private fun convertTopElement(element: PsiElement?): Element? = when(element) {
is PsiJavaFile -> convertFile(element) is PsiJavaFile -> convertFile(element)
+1 -1
View File
@@ -23,7 +23,7 @@ import com.intellij.psi.search.LocalSearchScope
import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.search.searches.ReferencesSearch
import org.jetbrains.jet.j2k.ast.* import org.jetbrains.jet.j2k.ast.*
fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".") fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier.toKotlin(it) }.makeString(".")
fun findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection<PsiReferenceExpression> { fun findVariableUsages(variable: PsiVariable, scope: PsiElement): Collection<PsiReferenceExpression> {
return ReferencesSearch.search(variable, LocalSearchScope(scope)).findAll().filterIsInstance(javaClass<PsiReferenceExpression>()) return ReferencesSearch.search(variable, LocalSearchScope(scope)).findAll().filterIsInstance(javaClass<PsiReferenceExpression>())
@@ -16,30 +16,32 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import java.util.HashSet import org.jetbrains.jet.j2k.CommentConverter
class Annotation(val name: Identifier, val arguments: List<Pair<Identifier?, Expression>>, val brackets: Boolean) : Element() { class Annotation(val name: Identifier, val arguments: List<Pair<Identifier?, Expression>>, val brackets: Boolean) : Element() {
private fun surroundWithBrackets(text: String) = if (brackets) "[$text]" else text private fun surroundWithBrackets(text: String) = if (brackets) "[$text]" else text
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
if (arguments.isEmpty()) { if (arguments.isEmpty()) {
return surroundWithBrackets(name.toKotlin()) return surroundWithBrackets(name.toKotlin(commentConverter))
} }
val argsText = arguments.map { val argsText = arguments.map {
if (it.first != null) if (it.first != null)
it.first!!.toKotlin() + " = " + it.second.toKotlin() it.first!!.toKotlin(commentConverter) + " = " + it.second.toKotlin(commentConverter)
else else
it.second.toKotlin() it.second.toKotlin(commentConverter)
}.makeString(", ") }.makeString(", ")
return surroundWithBrackets(name.toKotlin() + "(" + argsText + ")") return surroundWithBrackets(name.toKotlin(commentConverter) + "(" + argsText + ")")
} }
} }
class Annotations(val annotations: List<Annotation>, val newLines: Boolean) { class Annotations(val annotations: List<Annotation>, val newLines: Boolean) : Element() {
private val br = if (newLines) "\n" else " " private val br = if (newLines) "\n" else " "
fun toKotlin(): String = if (annotations.isNotEmpty()) annotations.map { it.toKotlin() }.makeString(br) + br else "" override fun toKotlinImpl(commentConverter: CommentConverter): String {
return if (annotations.isNotEmpty()) annotations.map { it.toKotlin(commentConverter) }.makeString(br) + br else ""
}
fun plus(other: Annotations) = Annotations(annotations + other.annotations, newLines || other.newLines) fun plus(other: Annotations) = Annotations(annotations + other.annotations, newLines || other.newLines)
@@ -16,10 +16,9 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter import org.jetbrains.jet.j2k.CommentConverter
import java.util.Collections
class AnonymousClassBody(body: ClassBody, val extendsTrait: Boolean) class AnonymousClassBody(body: ClassBody, val extendsTrait: Boolean)
: Class(Identifier(""), MemberComments.Empty, Annotations.Empty, setOf(), TypeParameterList.Empty, listOf(), listOf(), listOf(), body) { : Class(Identifier(""), MemberComments.Empty, Annotations.Empty, setOf(), TypeParameterList.Empty, listOf(), listOf(), listOf(), body) {
override fun toKotlin() = body.toKotlin(null) override fun toKotlinImpl(commentConverter: CommentConverter) = body.toKotlin(null, commentConverter)
} }
@@ -16,38 +16,41 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
open class ArrayWithoutInitializationExpression(val `type`: ArrayType, val expressions: List<Expression>) : Expression() { open class ArrayWithoutInitializationExpression(val `type`: ArrayType, val expressions: List<Expression>) : Expression() {
override fun toKotlin(): String override fun toKotlinImpl(commentConverter: CommentConverter): String {
= constructInnerType(`type`, expressions) fun getConstructorName(`type`: ArrayType, hasInit: Boolean): String {
return when (`type`.elementType) {
private fun constructInnerType(hostType: ArrayType, expressions: List<Expression>): String { is PrimitiveType ->
if (expressions.size() == 1) { `type`.toNotNullType().toKotlin(commentConverter)
return oneDim(hostType, expressions[0]) is ArrayType ->
if (hasInit)
`type`.toNotNullType().toKotlin(commentConverter)
else
"arrayOfNulls<" + `type`.elementType.toKotlin(commentConverter) + ">"
else ->
"arrayOfNulls<" + `type`.elementType.toKotlin(commentConverter) + ">"
}
} }
val innerType = hostType.elementType fun oneDim(`type`: ArrayType, size: Expression, init: String = ""): String {
if (expressions.size() > 1 && innerType is ArrayType) { return getConstructorName(`type`, !init.isEmpty()) + "(" + size.toKotlin(commentConverter) + init.withPrefix(", ") + ")"
return oneDim(hostType, expressions[0], "{" + constructInnerType(innerType, expressions.subList(1, expressions.size())) + "}")
} }
return getConstructorName(hostType, expressions.size() != 0) fun constructInnerType(hostType: ArrayType, expressions: List<Expression>): String {
} if (expressions.size() == 1) {
return oneDim(hostType, expressions[0])
}
private fun oneDim(`type`: ArrayType, size: Expression, init: String = ""): String { val innerType = hostType.elementType
return getConstructorName(`type`, !init.isEmpty()) + "(" + size.toKotlin() + init.withPrefix(", ") + ")" if (expressions.size() > 1 && innerType is ArrayType) {
} return oneDim(hostType, expressions[0], "{" + constructInnerType(innerType, expressions.subList(1, expressions.size())) + "}")
}
private fun getConstructorName(`type`: ArrayType, hasInit: Boolean): String { return getConstructorName(hostType, expressions.size() != 0)
return when (`type`.elementType) {
is PrimitiveType ->
`type`.toNotNullType().toKotlin()
is ArrayType ->
if (hasInit)
`type`.toNotNullType().toKotlin()
else
"arrayOfNulls<" + `type`.elementType.toKotlin() + ">"
else ->
"arrayOfNulls<" + `type`.elementType.toKotlin() + ">"
} }
return constructInnerType(`type`, expressions)
} }
} }
+3 -2
View File
@@ -17,6 +17,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.CommentConverter
fun Block(statements: List<Statement>, notEmpty: Boolean = false): Block { fun Block(statements: List<Statement>, notEmpty: Boolean = false): Block {
val elements = ArrayList<Element>() val elements = ArrayList<Element>()
@@ -33,9 +34,9 @@ class Block(val statementList: StatementList, val notEmpty: Boolean = false) : S
override val isEmpty: Boolean override val isEmpty: Boolean
get() = !notEmpty && statements.all { it.isEmpty } get() = !notEmpty && statements.all { it.isEmpty }
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
if (!isEmpty) { if (!isEmpty) {
return "{${statementList.toKotlin()}}" return "{${statementList.toKotlin(commentConverter)}}"
} }
return "" return ""
+19 -18
View File
@@ -17,6 +17,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.CommentConverter
open class Class( open class Class(
val name: Identifier, val name: Identifier,
@@ -30,35 +31,35 @@ open class Class(
val body: ClassBody val body: ClassBody
) : Member(comments, annotations, modifiers) { ) : Member(comments, annotations, modifiers) {
override fun toKotlin(): String = override fun toKotlinImpl(commentConverter: CommentConverter): String =
commentsToKotlin() + commentsToKotlin(commentConverter) +
annotations.toKotlin() + annotations.toKotlin(commentConverter) +
modifiersToKotlin() + modifiersToKotlin() +
keyword + " " + name.toKotlin() + keyword + " " + name.toKotlin(commentConverter) +
typeParameterList.toKotlin() + typeParameterList.toKotlin(commentConverter) +
primaryConstructorSignatureToKotlin() + primaryConstructorSignatureToKotlin(commentConverter) +
implementTypesToKotlin() + implementTypesToKotlin(commentConverter) +
typeParameterList.whereToKotlin().withPrefix(" ") + typeParameterList.whereToKotlin(commentConverter).withPrefix(" ") +
body.toKotlin(this) body.toKotlin(this, commentConverter)
protected open val keyword: String protected open val keyword: String
get() = "class" get() = "class"
protected open fun primaryConstructorSignatureToKotlin(): String protected open fun primaryConstructorSignatureToKotlin(commentConverter: CommentConverter): String
= body.primaryConstructor?.signatureToKotlin() ?: "()" = body.primaryConstructor?.signatureToKotlin(commentConverter) ?: "()"
private fun baseClassSignatureWithParams(): List<String> { private fun baseClassSignatureWithParams(commentConverter: CommentConverter): List<String> {
if (keyword.equals("class") && extendsTypes.size() == 1) { if (keyword.equals("class") && extendsTypes.size() == 1) {
val baseParams = baseClassParams.toKotlin(", ") val baseParams = baseClassParams.toKotlin(commentConverter, ", ")
return arrayListOf(extendsTypes[0].toKotlin() + "(" + baseParams + ")") return arrayListOf(extendsTypes[0].toKotlin(commentConverter) + "(" + baseParams + ")")
} }
return extendsTypes.map { it.toKotlin() } return extendsTypes.map { it.toKotlin(commentConverter) }
} }
protected fun implementTypesToKotlin(): String { protected fun implementTypesToKotlin(commentConverter: CommentConverter): String {
val allTypes = ArrayList<String>() val allTypes = ArrayList<String>()
allTypes.addAll(baseClassSignatureWithParams()) allTypes.addAll(baseClassSignatureWithParams(commentConverter))
allTypes.addAll(implementsTypes.map { it.toKotlin() }) allTypes.addAll(implementsTypes.map { it.toKotlin(commentConverter) })
return if (allTypes.size() == 0) return if (allTypes.size() == 0)
"" ""
else else
@@ -19,6 +19,7 @@ package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter import org.jetbrains.jet.j2k.Converter
import java.util.HashSet import java.util.HashSet
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.CommentConverter
abstract class Constructor( abstract class Constructor(
converter: Converter, converter: Converter,
@@ -37,13 +38,13 @@ class PrimaryConstructor(converter: Converter,
block: Block) block: Block)
: Constructor(converter, comments, annotations, modifiers, parameterList, block) { : Constructor(converter, comments, annotations, modifiers, parameterList, block) {
public fun signatureToKotlin(): String { public fun signatureToKotlin(commentConverter: CommentConverter): String {
val accessModifier = modifiers.accessModifier() val accessModifier = modifiers.accessModifier()
val modifiersString = if (accessModifier != null && accessModifier != Modifier.PUBLIC) " " + accessModifier.toKotlin() else "" val modifiersString = if (accessModifier != null && accessModifier != Modifier.PUBLIC) " " + accessModifier.toKotlin() else ""
return modifiersString + "(" + parameterList.toKotlin() + ")" return modifiersString + "(" + parameterList.toKotlin(commentConverter) + ")"
} }
public fun bodyToKotlin(): String = block!!.toKotlin() public fun bodyToKotlin(commentConverter: CommentConverter): String = block!!.toKotlin(commentConverter)
} }
class SecondaryConstructor(converter: Converter, class SecondaryConstructor(converter: Converter,
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class DummyStringExpression(val string: String) : Expression() { class DummyStringExpression(val string: String) : Expression() {
override fun toKotlin(): String = string override fun toKotlinImpl(commentConverter: CommentConverter): String = string
} }
+7 -3
View File
@@ -16,17 +16,21 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
abstract class Element { abstract class Element {
public abstract fun toKotlin(): String public fun toKotlin(commentConverter: CommentConverter): String = toKotlinImpl(commentConverter)
protected abstract fun toKotlinImpl(commentConverter: CommentConverter): String
public open val isEmpty: Boolean get() = false public open val isEmpty: Boolean get() = false
object Empty : Element() { object Empty : Element() {
override fun toKotlin() = "" override fun toKotlinImpl(commentConverter: CommentConverter) = ""
override val isEmpty: Boolean get() = true override val isEmpty: Boolean get() = true
} }
} }
class Comment(val text: String) : Element() { class Comment(val text: String) : Element() {
override fun toKotlin() = text override fun toKotlinImpl(commentConverter: CommentConverter) = text
} }
+12 -10
View File
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class Enum( class Enum(
name: Identifier, name: Identifier,
comments: MemberComments, comments: MemberComments,
@@ -29,17 +31,17 @@ class Enum(
) : Class(name, comments, annotations, modifiers, typeParameterList, ) : Class(name, comments, annotations, modifiers, typeParameterList,
extendsTypes, baseClassParams, implementsTypes, body) { extendsTypes, baseClassParams, implementsTypes, body) {
override fun primaryConstructorSignatureToKotlin(): String override fun primaryConstructorSignatureToKotlin(commentConverter: CommentConverter): String
= body.primaryConstructor?.signatureToKotlin() ?: "" = body.primaryConstructor?.signatureToKotlin(commentConverter) ?: ""
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
return commentsToKotlin() + return commentsToKotlin(commentConverter) +
annotations.toKotlin() + annotations.toKotlin(commentConverter) +
modifiersToKotlin() + modifiersToKotlin() +
"enum class " + name.toKotlin() + "enum class " + name.toKotlin(commentConverter) +
primaryConstructorSignatureToKotlin() + primaryConstructorSignatureToKotlin(commentConverter) +
typeParameterList.toKotlin() + typeParameterList.toKotlin(commentConverter) +
implementTypesToKotlin() + implementTypesToKotlin(commentConverter) +
body.toKotlin(this) body.toKotlin(this, commentConverter)
} }
} }
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class EnumConstant( class EnumConstant(
identifier: Identifier, identifier: Identifier,
members: MemberComments, members: MemberComments,
@@ -25,12 +27,12 @@ class EnumConstant(
params: Element params: Element
) : Field(identifier, members, annotations, modifiers, `type`.toNotNullType(), params, true, false) { ) : Field(identifier, members, annotations, modifiers, `type`.toNotNullType(), params, true, false) {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
if (initializer.toKotlin().isEmpty()) { if (initializer.toKotlin(commentConverter).isEmpty()) {
return annotations.toKotlin() + identifier.toKotlin() return annotations.toKotlin(commentConverter) + identifier.toKotlin(commentConverter)
} }
return annotations.toKotlin() + identifier.toKotlin() + " : " + `type`.toKotlin() + "(" + initializer.toKotlin() + ")" return annotations.toKotlin(commentConverter) + identifier.toKotlin(commentConverter) + " : " + `type`.toKotlin(commentConverter) + "(" + initializer.toKotlin(commentConverter) + ")"
} }
@@ -16,12 +16,14 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
abstract class Expression() : Statement() { abstract class Expression() : Statement() {
open val isNullable: Boolean get() = false open val isNullable: Boolean get() = false
object Empty : Expression() { object Empty : Expression() {
override fun toKotlin() = "" override fun toKotlinImpl(commentConverter: CommentConverter) = ""
override val isEmpty: Boolean get() = true override val isEmpty: Boolean get() = true
} }
@@ -16,8 +16,10 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
open class ExpressionList(val expressions: List<Expression>) : Expression() { open class ExpressionList(val expressions: List<Expression>) : Expression() {
override fun toKotlin(): String = expressions.map { it.toKotlin() }.makeString(", ") override fun toKotlinImpl(commentConverter: CommentConverter): String = expressions.map { it.toKotlin(commentConverter) }.makeString(", ")
override val isEmpty: Boolean override val isEmpty: Boolean
get() = expressions.isEmpty() get() = expressions.isEmpty()
@@ -17,83 +17,84 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.lang.types.expressions.OperatorConventions import org.jetbrains.jet.lang.types.expressions.OperatorConventions
import org.jetbrains.jet.j2k.CommentConverter
class ArrayAccessExpression(val expression: Expression, val index: Expression, val lvalue: Boolean) : Expression() { class ArrayAccessExpression(val expression: Expression, val index: Expression, val lvalue: Boolean) : Expression() {
override fun toKotlin() = operandToKotlin(expression) + override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(expression, commentConverter) +
(if (!lvalue && expression.isNullable) "!!" else "") + (if (!lvalue && expression.isNullable) "!!" else "") +
"[" + index.toKotlin() + "]" "[" + index.toKotlin(commentConverter) + "]"
} }
class AssignmentExpression(val left: Expression, val right: Expression, val op: String) : Expression() { class AssignmentExpression(val left: Expression, val right: Expression, val op: String) : Expression() {
override fun toKotlin() = operandToKotlin(left) + " " + op + " " + operandToKotlin(right) override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(left, commentConverter) + " " + op + " " + operandToKotlin(right, commentConverter)
} }
class BangBangExpression(val expr: Expression) : Expression() { class BangBangExpression(val expr: Expression) : Expression() {
override fun toKotlin() = operandToKotlin(expr) + "!!" override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(expr, commentConverter) + "!!"
} }
class BinaryExpression(val left: Expression, val right: Expression, val op: String) : Expression() { class BinaryExpression(val left: Expression, val right: Expression, val op: String) : Expression() {
override fun toKotlin() = operandToKotlin(left, false) + " " + op + " " + operandToKotlin(right, true) override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(left, commentConverter, false) + " " + op + " " + operandToKotlin(right, commentConverter, true)
} }
class IsOperator(val expression: Expression, val typeElement: TypeElement) : Expression() { class IsOperator(val expression: Expression, val typeElement: TypeElement) : Expression() {
override fun toKotlin() = operandToKotlin(expression) + " is " + typeElement.toKotlinNotNull() override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(expression, commentConverter) + " is " + typeElement.`type`.toNotNullType().toKotlin(commentConverter)
} }
class TypeCastExpression(val `type`: Type, val expression: Expression) : Expression() { class TypeCastExpression(val `type`: Type, val expression: Expression) : Expression() {
override fun toKotlin() = operandToKotlin(expression) + " as " + `type`.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(expression, commentConverter) + " as " + `type`.toKotlin(commentConverter)
} }
class LiteralExpression(val literalText: String) : Expression() { class LiteralExpression(val literalText: String) : Expression() {
override fun toKotlin() = literalText override fun toKotlinImpl(commentConverter: CommentConverter) = literalText
} }
class ParenthesizedExpression(val expression: Expression) : Expression() { class ParenthesizedExpression(val expression: Expression) : Expression() {
override fun toKotlin() = "(" + expression.toKotlin() + ")" override fun toKotlinImpl(commentConverter: CommentConverter) = "(" + expression.toKotlin(commentConverter) + ")"
} }
class PrefixOperator(val op: String, val expression: Expression) : Expression() { class PrefixOperator(val op: String, val expression: Expression) : Expression() {
override fun toKotlin() = op + operandToKotlin(expression) override fun toKotlinImpl(commentConverter: CommentConverter) = op + operandToKotlin(expression, commentConverter)
override val isNullable: Boolean override val isNullable: Boolean
get() = expression.isNullable get() = expression.isNullable
} }
class PostfixOperator(val op: String, val expression: Expression) : Expression() { class PostfixOperator(val op: String, val expression: Expression) : Expression() {
override fun toKotlin() = operandToKotlin(expression) + op override fun toKotlinImpl(commentConverter: CommentConverter) = operandToKotlin(expression, commentConverter) + op
} }
class ThisExpression(val identifier: Identifier) : Expression() { class ThisExpression(val identifier: Identifier) : Expression() {
override fun toKotlin() = "this" + identifier.withPrefix("@") override fun toKotlinImpl(commentConverter: CommentConverter) = "this" + identifier.withPrefix("@", commentConverter)
} }
class SuperExpression(val identifier: Identifier) : Expression() { class SuperExpression(val identifier: Identifier) : Expression() {
override fun toKotlin() = "super" + identifier.withPrefix("@") override fun toKotlinImpl(commentConverter: CommentConverter) = "super" + identifier.withPrefix("@", commentConverter)
} }
class QualifiedExpression(val qualifier: Expression, val identifier: Expression) : Expression() { class QualifiedExpression(val qualifier: Expression, val identifier: Expression) : Expression() {
override val isNullable: Boolean override val isNullable: Boolean
get() = identifier.isNullable get() = identifier.isNullable
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
if (!qualifier.isEmpty) { if (!qualifier.isEmpty) {
return operandToKotlin(qualifier) + (if (qualifier.isNullable) "!!." else ".") + identifier.toKotlin() return operandToKotlin(qualifier, commentConverter) + (if (qualifier.isNullable) "!!." else ".") + identifier.toKotlin(commentConverter)
} }
return identifier.toKotlin() return identifier.toKotlin(commentConverter)
} }
} }
class PolyadicExpression(val expressions: List<Expression>, val token: String) : Expression() { class PolyadicExpression(val expressions: List<Expression>, val token: String) : Expression() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val expressionsWithConversions = expressions.map { it.toKotlin() } val expressionsWithConversions = expressions.map { it.toKotlin(commentConverter) }
return expressionsWithConversions.makeString(" " + token + " ") return expressionsWithConversions.makeString(" " + token + " ")
} }
} }
class LambdaExpression(val arguments: String?, val statementList: StatementList) : Expression() { class LambdaExpression(val arguments: String?, val statementList: StatementList) : Expression() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val statementsText = statementList.toKotlin().trim() val statementsText = statementList.toKotlin(commentConverter).trim()
if (arguments != null) { if (arguments != null) {
val br = if (statementsText.indexOf('\n') < 0 && statementsText.indexOf('\r') < 0) " " else "\n" val br = if (statementsText.indexOf('\n') < 0 && statementsText.indexOf('\r') < 0) " " else "\n"
return "{ $arguments ->$br$statementsText }" return "{ $arguments ->$br$statementsText }"
@@ -105,25 +106,25 @@ class LambdaExpression(val arguments: String?, val statementList: StatementList)
} }
class StarExpression(val methodCall: MethodCallExpression) : Expression() { class StarExpression(val methodCall: MethodCallExpression) : Expression() {
override fun toKotlin() = "*" + methodCall.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "*" + methodCall.toKotlin(commentConverter)
} }
fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Expression>, needExplicitType: Boolean) : MethodCallExpression { fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Expression>, needExplicitType: Boolean) : MethodCallExpression {
val elementType = arrayType.elementType val elementType = arrayType.elementType
val createArrayFunction = if (elementType.isPrimitive()) val createArrayFunction = if (elementType is PrimitiveType)
(elementType.toNotNullType().toKotlin() + "Array").decapitalize() (elementType.toNotNullType().toKotlin(CommentConverter.Dummy) + "Array").decapitalize()
else if (needExplicitType) else if (needExplicitType)
arrayType.toNotNullType().toKotlin().decapitalize() arrayType.toNotNullType().toKotlin(CommentConverter.Dummy).decapitalize()
else else
"array" "array"
val doubleOrFloatTypes = setOf("double", "float", "java.lang.double", "java.lang.float") val doubleOrFloatTypes = setOf("double", "float", "java.lang.double", "java.lang.float")
val afterReplace = arrayType.toNotNullType().toKotlin().replace("Array", "").toLowerCase().replace(">", "").replace("<", "").replace("?", "") val afterReplace = arrayType.toNotNullType().toKotlin(CommentConverter.Dummy).replace("Array", "").toLowerCase().replace(">", "").replace("<", "").replace("?", "")
fun explicitConvertIfNeeded(initializer: Expression): Expression { fun explicitConvertIfNeeded(initializer: Expression): Expression {
if (doubleOrFloatTypes.contains(afterReplace)) { if (doubleOrFloatTypes.contains(afterReplace)) {
if (initializer is LiteralExpression) { if (initializer is LiteralExpression) {
if (!initializer.toKotlin().contains(".")) { if (!initializer.toKotlin(CommentConverter.Dummy).contains(".")) {
return LiteralExpression(initializer.literalText + ".0") return LiteralExpression(initializer.literalText + ".0")
} }
} }
+10 -4
View File
@@ -30,12 +30,18 @@ open class Field(
private val hasWriteAccesses: Boolean private val hasWriteAccesses: Boolean
) : Member(comments, annotations, modifiers) { ) : Member(comments, annotations, modifiers) {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val declaration = commentsToKotlin() + annotations.toKotlin() + modifiersToKotlin() + (if (isVal) "val " else "var ") + identifier.toKotlin() + " : " + `type`.toKotlin() val declaration = commentsToKotlin(commentConverter) +
annotations.toKotlin(commentConverter) +
modifiersToKotlin() +
(if (isVal) "val " else "var ") +
identifier.toKotlin(commentConverter) +
" : " +
`type`.toKotlin(commentConverter)
return if (initializer.isEmpty) return if (initializer.isEmpty)
declaration + (if (isVal && hasWriteAccesses) "" else " = " + getDefaultInitializer(this).toKotlin()) declaration + (if (isVal && hasWriteAccesses) "" else " = " + getDefaultInitializer(this).toKotlin(commentConverter))
else else
declaration + " = " + initializer.toKotlin() declaration + " = " + initializer.toKotlin(commentConverter)
} }
private fun modifiersToKotlin(): String { private fun modifiersToKotlin(): String {
+5 -3
View File
@@ -16,10 +16,12 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class FileMemberList(elements: List<Element>) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NewLine, false) class FileMemberList(elements: List<Element>) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NewLine, false)
class PackageStatement(val packageName: String) : Element() { class PackageStatement(val packageName: String) : Element() {
override fun toKotlin(): String = "package " + packageName override fun toKotlinImpl(commentConverter: CommentConverter): String = "package " + packageName
} }
class File( class File(
@@ -27,7 +29,7 @@ class File(
val mainFunction: String val mainFunction: String
) : Element() { ) : Element() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
return body.toKotlin() + mainFunction return body.toKotlin(commentConverter) + mainFunction
} }
} }
+9 -10
View File
@@ -18,6 +18,7 @@ package org.jetbrains.jet.j2k.ast
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.Converter import org.jetbrains.jet.j2k.Converter
import org.jetbrains.jet.j2k.CommentConverter
open class Function( open class Function(
val converter: Converter, val converter: Converter,
@@ -55,16 +56,14 @@ open class Function(
return resultingModifiers.toKotlin() return resultingModifiers.toKotlin()
} }
private fun returnTypeToKotlin() = if (!`type`.isUnit()) " : " + `type`.toKotlin() + " " else " " override fun toKotlinImpl(commentConverter: CommentConverter): String {
return commentsToKotlin(commentConverter) +
override fun toKotlin(): String { annotations.toKotlin(commentConverter) +
return commentsToKotlin() +
annotations.toKotlin() +
modifiersToKotlin() + modifiersToKotlin() +
"fun ${typeParameterList.toKotlin().withSuffix(" ")}${name.toKotlin()}" + "fun ${typeParameterList.toKotlin(commentConverter).withSuffix(" ")}${name.toKotlin(commentConverter)}" +
"(${parameterList.toKotlin()})" + "(${parameterList.toKotlin(commentConverter)})" +
returnTypeToKotlin() + (if (!`type`.isUnit()) " : " + `type`.toKotlin(commentConverter) + " " else " ") +
typeParameterList.whereToKotlin() + typeParameterList.whereToKotlin(commentConverter) +
block?.toKotlin() block?.toKotlin(commentConverter)
} }
} }
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class Identifier( class Identifier(
val name: String, val name: String,
@@ -26,7 +28,7 @@ class Identifier(
override val isEmpty: Boolean override val isEmpty: Boolean
get() = name.isEmpty() get() = name.isEmpty()
private fun identifierToKotlin(): String { private fun toKotlin(): String {
if (quotingNeeded && ONLY_KOTLIN_KEYWORDS.contains(name) || name.contains("$")) { if (quotingNeeded && ONLY_KOTLIN_KEYWORDS.contains(name) || name.contains("$")) {
return quote(name) return quote(name)
} }
@@ -34,7 +36,7 @@ class Identifier(
return name return name
} }
override fun toKotlin(): String = identifierToKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = toKotlin()
private fun quote(str: String): String = "`" + str + "`" private fun quote(str: String): String = "`" + str + "`"
@@ -47,6 +49,6 @@ class Identifier(
"package", "as", "type", "val", "var", "fun", "is", "in", "object", "when", "trait", "This" "package", "as", "type", "val", "var", "fun", "is", "in", "object", "when", "trait", "This"
) )
fun toKotlin(name: String): String = Identifier(name).identifierToKotlin() fun toKotlin(name: String): String = Identifier(name).toKotlin()
} }
} }
+2 -2
View File
@@ -25,14 +25,14 @@ import com.intellij.psi.PsiJavaCodeReferenceElement
import org.jetbrains.jet.asJava.KotlinLightClassForPackage import org.jetbrains.jet.asJava.KotlinLightClassForPackage
class Import(val name: String) : Element() { class Import(val name: String) : Element() {
override fun toKotlin() = "import " + name override fun toKotlinImpl(commentConverter: CommentConverter) = "import " + name
} }
class ImportList(public val imports: List<Import>) : Element() { class ImportList(public val imports: List<Import>) : Element() {
override val isEmpty: Boolean override val isEmpty: Boolean
get() = imports.isEmpty() get() = imports.isEmpty()
override fun toKotlin() = imports.toKotlin("\n") override fun toKotlinImpl(commentConverter: CommentConverter) = imports.toKotlin(commentConverter, "\n")
} }
public fun Converter.convertImportList(importList: PsiImportList): ImportList = public fun Converter.convertImportList(importList: PsiImportList): ImportList =
@@ -16,8 +16,10 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class Initializer(val block: Block, modifiers: Set<Modifier>) : Member(MemberComments.Empty, Annotations.Empty, modifiers) { class Initializer(val block: Block, modifiers: Set<Modifier>) : Member(MemberComments.Empty, Annotations.Empty, modifiers) {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
return block.toKotlin() return block.toKotlin(commentConverter)
} }
} }
@@ -17,6 +17,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.ConverterSettings import org.jetbrains.jet.j2k.ConverterSettings
import org.jetbrains.jet.j2k.CommentConverter
class LocalVariable( class LocalVariable(
private val identifier: Identifier, private val identifier: Identifier,
@@ -28,17 +29,17 @@ class LocalVariable(
private val settings: ConverterSettings private val settings: ConverterSettings
) : Element() { ) : Element() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val start = annotations.toKotlin() + if (isVal) "val" else "var" val start = annotations.toKotlin(commentConverter) + if (isVal) "val" else "var"
return if (initializer.isEmpty) { return if (initializer.isEmpty) {
"$start ${identifier.toKotlin()} : ${typeCalculator().toKotlin()}" "$start ${identifier.toKotlin(commentConverter)} : ${typeCalculator().toKotlin(commentConverter)}"
} }
else { else {
val shouldSpecifyType = settings.specifyLocalVariableTypeByDefault val shouldSpecifyType = settings.specifyLocalVariableTypeByDefault
if (shouldSpecifyType) if (shouldSpecifyType)
"$start ${identifier.toKotlin()} : ${typeCalculator().toKotlin()} = ${initializer.toKotlin()}" "$start ${identifier.toKotlin(commentConverter)} : ${typeCalculator().toKotlin(commentConverter)} = ${initializer.toKotlin(commentConverter)}"
else else
"$start ${identifier.toKotlin()} = ${initializer.toKotlin()}" "$start ${identifier.toKotlin(commentConverter)} = ${initializer.toKotlin(commentConverter)}"
} }
} }
} }
+10 -13
View File
@@ -17,12 +17,7 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import java.util.ArrayList import java.util.ArrayList
import com.intellij.psi.PsiClass import org.jetbrains.jet.j2k.CommentConverter
import org.jetbrains.jet.j2k.Converter
import java.util.HashSet
import com.intellij.psi.PsiMember
import java.util.LinkedHashMap
import com.intellij.psi.PsiElement
class MemberComments(elements: List<Element>) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NoSpace) { class MemberComments(elements: List<Element>) : WhiteSpaceSeparatedElementList(elements, WhiteSpace.NoSpace) {
class object { class object {
@@ -31,7 +26,7 @@ class MemberComments(elements: List<Element>) : WhiteSpaceSeparatedElementList(e
} }
abstract class Member(val comments: MemberComments, val annotations: Annotations, val modifiers: Set<Modifier>) : Element() { abstract class Member(val comments: MemberComments, val annotations: Annotations, val modifiers: Set<Modifier>) : Element() {
fun commentsToKotlin(): String = comments.toKotlin() fun commentsToKotlin(commentConverter: CommentConverter): String = comments.toKotlin(commentConverter)
} }
//member itself and all the elements before it in the code (comments, whitespaces) //member itself and all the elements before it in the code (comments, whitespaces)
@@ -48,23 +43,25 @@ class ClassBody (
val normalMembers: MemberList, val normalMembers: MemberList,
val classObjectMembers: MemberList) { val classObjectMembers: MemberList) {
fun toKotlin(containingClass: Class?): String { fun toKotlin(containingClass: Class?, commentConverter: CommentConverter): String {
val innerBody = normalMembers.toKotlin() + primaryConstructorBodyToKotlin() + classObjectToKotlin(containingClass) val innerBody = normalMembers.toKotlin(commentConverter) +
primaryConstructorBodyToKotlin(commentConverter) +
classObjectToKotlin(containingClass, commentConverter)
return if (innerBody.trim().isNotEmpty()) " {" + innerBody + "}" else "" return if (innerBody.trim().isNotEmpty()) " {" + innerBody + "}" else ""
} }
private fun primaryConstructorBodyToKotlin(): String { private fun primaryConstructorBodyToKotlin(commentConverter: CommentConverter): String {
val constructor = primaryConstructor val constructor = primaryConstructor
if (constructor != null && !(constructor.block?.isEmpty ?: true)) { if (constructor != null && !(constructor.block?.isEmpty ?: true)) {
return "\n" + constructor.bodyToKotlin() + "\n" return "\n" + constructor.bodyToKotlin(commentConverter) + "\n"
} }
return "" return ""
} }
private fun classObjectToKotlin(containingClass: Class?): String { private fun classObjectToKotlin(containingClass: Class?, commentConverter: CommentConverter): String {
val secondaryConstructorsAsStaticInitFunctions = secondaryConstructorsAsStaticInitFunctions(containingClass) val secondaryConstructorsAsStaticInitFunctions = secondaryConstructorsAsStaticInitFunctions(containingClass)
if (secondaryConstructorsAsStaticInitFunctions.isEmpty() && classObjectMembers.isEmpty()) return "" if (secondaryConstructorsAsStaticInitFunctions.isEmpty() && classObjectMembers.isEmpty()) return ""
return "\nclass object {${secondaryConstructorsAsStaticInitFunctions.toKotlin()}${classObjectMembers.toKotlin()}}" return "\nclass object {${secondaryConstructorsAsStaticInitFunctions.toKotlin(commentConverter)}${classObjectMembers.toKotlin(commentConverter)}}"
} }
private fun secondaryConstructorsAsStaticInitFunctions(containingClass: Class?): MemberList { private fun secondaryConstructorsAsStaticInitFunctions(containingClass: Class?): MemberList {
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class MethodCallExpression( class MethodCallExpression(
val methodExpression: Expression, val methodExpression: Expression,
val arguments: List<Expression>, val arguments: List<Expression>,
@@ -24,15 +26,15 @@ class MethodCallExpression(
val lambdaArgument: LambdaExpression? = null val lambdaArgument: LambdaExpression? = null
) : Expression() { ) : Expression() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val builder = StringBuilder() val builder = StringBuilder()
builder.append(operandToKotlin(methodExpression)) builder.append(operandToKotlin(methodExpression, commentConverter))
builder.append(typeArguments.toKotlin(", ", "<", ">")) builder.append(typeArguments.toKotlin(commentConverter, ", ", "<", ">"))
if (arguments.isNotEmpty() || lambdaArgument == null) { if (arguments.isNotEmpty() || lambdaArgument == null) {
builder.append("(").append(arguments.map { it.toKotlin() }.makeString(", ")).append(")") builder.append("(").append(arguments.map { it.toKotlin(commentConverter) }.makeString(", ")).append(")")
} }
if (lambdaArgument != null) { if (lambdaArgument != null) {
builder.append(lambdaArgument.toKotlin()) builder.append(lambdaArgument.toKotlin(commentConverter))
} }
return builder.toString() return builder.toString()
} }
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
enum class Modifier(val name: String) { enum class Modifier(val name: String) {
PUBLIC: Modifier("public") PUBLIC: Modifier("public")
PROTECTED: Modifier("protected") PROTECTED: Modifier("protected")
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class NewClassExpression( class NewClassExpression(
val name: Element, val name: Element,
val arguments: List<Expression>, val arguments: List<Expression>,
@@ -23,18 +25,18 @@ class NewClassExpression(
val anonymousClass: AnonymousClassBody? = null val anonymousClass: AnonymousClassBody? = null
) : Expression() { ) : Expression() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val callOperator = if (qualifier.isNullable) "!!." else "." val callOperator = if (qualifier.isNullable) "!!." else "."
val qualifier = if (qualifier.isEmpty) "" else qualifier.toKotlin() + callOperator val qualifier = if (qualifier.isEmpty) "" else qualifier.toKotlin(commentConverter) + callOperator
val appliedArguments = arguments.toKotlin(", ") val appliedArguments = arguments.toKotlin(commentConverter, ", ")
return if (anonymousClass != null) { return if (anonymousClass != null) {
if (anonymousClass.extendsTrait) if (anonymousClass.extendsTrait)
"object : " + qualifier + name.toKotlin() + anonymousClass.toKotlin() "object : " + qualifier + name.toKotlin(commentConverter) + anonymousClass.toKotlin(commentConverter)
else else
"object : " + qualifier + name.toKotlin() + "(" + appliedArguments + ")" + anonymousClass.toKotlin() "object : " + qualifier + name.toKotlin(commentConverter) + "(" + appliedArguments + ")" + anonymousClass.toKotlin(commentConverter)
} }
else{ else{
qualifier + name.toKotlin() + "(" + appliedArguments + ")" qualifier + name.toKotlin(commentConverter) + "(" + appliedArguments + ")"
} }
} }
} }
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class Parameter(val identifier: Identifier, class Parameter(val identifier: Identifier,
val `type`: Type, val `type`: Type,
val varVal: Parameter.VarValModifier, val varVal: Parameter.VarValModifier,
@@ -27,10 +29,10 @@ class Parameter(val identifier: Identifier,
Var Var
} }
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val builder = StringBuilder() val builder = StringBuilder()
builder.append(annotations.toKotlin()) builder.append(annotations.toKotlin(commentConverter))
builder.append(modifiers.toKotlin()) builder.append(modifiers.toKotlin())
if (`type` is VarArgType) { if (`type` is VarArgType) {
@@ -43,7 +45,7 @@ class Parameter(val identifier: Identifier,
VarValModifier.Val -> builder.append("val ") VarValModifier.Val -> builder.append("val ")
} }
builder.append(identifier.toKotlin()).append(": ").append(`type`.toKotlin()) builder.append(identifier.toKotlin(commentConverter)).append(": ").append(`type`.toKotlin(commentConverter))
return builder.toString() return builder.toString()
} }
} }
@@ -16,8 +16,10 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
open class ParameterList(val parameters: List<Parameter>) : Element() { open class ParameterList(val parameters: List<Parameter>) : Element() {
override fun toKotlin() = parameters.map { it.toKotlin() }.makeString(", ") override fun toKotlinImpl(commentConverter: CommentConverter) = parameters.map { it.toKotlin(commentConverter) }.makeString(", ")
} }
@@ -16,6 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class ReferenceElement(val reference: Identifier, val types: List<Type>) : Element() { class ReferenceElement(val reference: Identifier, val types: List<Type>) : Element() {
override fun toKotlin() = reference.toKotlin() + types.toKotlin(", ", "<", ">") override fun toKotlinImpl(commentConverter: CommentConverter) = reference.toKotlin(commentConverter) + types.toKotlin(commentConverter, ", ", "<", ">")
} }
+28 -26
View File
@@ -16,10 +16,12 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
abstract class Statement() : Element() { abstract class Statement() : Element() {
object Empty : Statement() { object Empty : Statement() {
override fun toKotlin() = "" override fun toKotlinImpl(commentConverter: CommentConverter) = ""
override val isEmpty: Boolean override val isEmpty: Boolean
get() = true get() = true
@@ -27,20 +29,20 @@ abstract class Statement() : Element() {
} }
class DeclarationStatement(val elements: List<Element>) : Statement() { class DeclarationStatement(val elements: List<Element>) : Statement() {
override fun toKotlin(): String override fun toKotlinImpl(commentConverter: CommentConverter): String
= elements.filterIsInstance(javaClass<LocalVariable>()).map { it.toKotlin() }.makeString("\n") = elements.filterIsInstance(javaClass<LocalVariable>()).map { it.toKotlin(commentConverter) }.makeString("\n")
} }
class ExpressionListStatement(val expressions: List<Expression>) : Expression() { class ExpressionListStatement(val expressions: List<Expression>) : Expression() {
override fun toKotlin() = expressions.toKotlin("\n") override fun toKotlinImpl(commentConverter: CommentConverter) = expressions.toKotlin(commentConverter, "\n")
} }
class LabelStatement(val name: Identifier, val statement: Element) : Statement() { class LabelStatement(val name: Identifier, val statement: Element) : Statement() {
override fun toKotlin(): String = "@" + name.toKotlin() + " " + statement.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = "@" + name.toKotlin(commentConverter) + " " + statement.toKotlin(commentConverter)
} }
class ReturnStatement(val expression: Expression) : Statement() { class ReturnStatement(val expression: Expression) : Statement() {
override fun toKotlin() = "return " + expression.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "return " + expression.toKotlin(commentConverter)
} }
class IfStatement( class IfStatement(
@@ -51,10 +53,10 @@ class IfStatement(
) : Expression() { ) : Expression() {
private val br = if (singleLine) " " else "\n" private val br = if (singleLine) " " else "\n"
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val result = "if (" + condition.toKotlin() + ")$br" + thenStatement.toKotlin() val result = "if (" + condition.toKotlin(commentConverter) + ")$br" + thenStatement.toKotlin(commentConverter)
if (!elseStatement.isEmpty) { if (!elseStatement.isEmpty) {
return "$result${br}else$br${elseStatement.toKotlin()}" return "$result${br}else$br${elseStatement.toKotlin(commentConverter)}"
} }
return result return result
} }
@@ -65,13 +67,13 @@ class IfStatement(
class WhileStatement(val condition: Expression, val body: Element, singleLine: Boolean) : Statement() { class WhileStatement(val condition: Expression, val body: Element, singleLine: Boolean) : Statement() {
private val br = if (singleLine) " " else "\n" private val br = if (singleLine) " " else "\n"
override fun toKotlin() = "while (" + condition.toKotlin() + ")$br" + body.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "while (" + condition.toKotlin(commentConverter) + ")$br" + body.toKotlin(commentConverter)
} }
class DoWhileStatement(val condition: Expression, val body: Element, singleLine: Boolean) : Statement() { class DoWhileStatement(val condition: Expression, val body: Element, singleLine: Boolean) : Statement() {
private val br = if (singleLine) " " else "\n" private val br = if (singleLine) " " else "\n"
override fun toKotlin() = "do$br" + body.toKotlin() + "${br}while (" + condition.toKotlin() + ")" override fun toKotlinImpl(commentConverter: CommentConverter) = "do$br" + body.toKotlin(commentConverter) + "${br}while (" + condition.toKotlin(commentConverter) + ")"
} }
class ForeachStatement( class ForeachStatement(
@@ -83,7 +85,7 @@ class ForeachStatement(
private val br = if (singleLine) " " else "\n" private val br = if (singleLine) " " else "\n"
override fun toKotlin() = "for (" + variable.identifier.toKotlin() + " in " + expression.toKotlin() + ")$br" + body.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "for (" + variable.identifier.toKotlin(commentConverter) + " in " + expression.toKotlin(commentConverter) + ")$br" + body.toKotlin(commentConverter)
} }
class ForeachWithRangeStatement(val identifier: Identifier, class ForeachWithRangeStatement(val identifier: Identifier,
@@ -93,66 +95,66 @@ class ForeachWithRangeStatement(val identifier: Identifier,
singleLine: Boolean) : Statement() { singleLine: Boolean) : Statement() {
private val br = if (singleLine) " " else "\n" private val br = if (singleLine) " " else "\n"
override fun toKotlin() = "for (" + identifier.toKotlin() + " in " + start.toKotlin() + ".." + end.toKotlin() + ")$br" + body.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "for (" + identifier.toKotlin(commentConverter) + " in " + start.toKotlin(commentConverter) + ".." + end.toKotlin(commentConverter) + ")$br" + body.toKotlin(commentConverter)
} }
class BreakStatement(val label: Identifier = Identifier.Empty) : Statement() { class BreakStatement(val label: Identifier = Identifier.Empty) : Statement() {
override fun toKotlin() = "break" + label.withPrefix("@") override fun toKotlinImpl(commentConverter: CommentConverter) = "break" + label.withPrefix("@", commentConverter)
} }
class ContinueStatement(val label: Identifier = Identifier.Empty) : Statement() { class ContinueStatement(val label: Identifier = Identifier.Empty) : Statement() {
override fun toKotlin() = "continue" + label.withPrefix("@") override fun toKotlinImpl(commentConverter: CommentConverter) = "continue" + label.withPrefix("@", commentConverter)
} }
// Exceptions ---------------------------------------------------------------------------------------------- // Exceptions ----------------------------------------------------------------------------------------------
class TryStatement(val block: Block, val catches: List<CatchStatement>, val finallyBlock: Block) : Statement() { class TryStatement(val block: Block, val catches: List<CatchStatement>, val finallyBlock: Block) : Statement() {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
val builder = StringBuilder() val builder = StringBuilder()
.append("try\n") .append("try\n")
.append(block.toKotlin()) .append(block.toKotlin(commentConverter))
.append("\n") .append("\n")
.append(catches.toKotlin("\n")) .append(catches.toKotlin(commentConverter, "\n"))
.append("\n") .append("\n")
if (!finallyBlock.isEmpty) { if (!finallyBlock.isEmpty) {
builder.append("finally\n").append(finallyBlock.toKotlin()) builder.append("finally\n").append(finallyBlock.toKotlin(commentConverter))
} }
return builder.toString() return builder.toString()
} }
} }
class ThrowStatement(val expression: Expression) : Expression() { class ThrowStatement(val expression: Expression) : Expression() {
override fun toKotlin() = "throw " + expression.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "throw " + expression.toKotlin(commentConverter)
} }
class CatchStatement(val variable: Parameter, val block: Block) : Statement() { class CatchStatement(val variable: Parameter, val block: Block) : Statement() {
override fun toKotlin(): String = "catch (" + variable.toKotlin() + ") " + block.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = "catch (" + variable.toKotlin(commentConverter) + ") " + block.toKotlin(commentConverter)
} }
// Switch -------------------------------------------------------------------------------------------------- // Switch --------------------------------------------------------------------------------------------------
class SwitchContainer(val expression: Expression, val caseContainers: List<CaseContainer>) : Statement() { class SwitchContainer(val expression: Expression, val caseContainers: List<CaseContainer>) : Statement() {
override fun toKotlin() = "when (" + expression.toKotlin() + ") {\n" + caseContainers.toKotlin("\n") + "\n}" override fun toKotlinImpl(commentConverter: CommentConverter) = "when (" + expression.toKotlin(commentConverter) + ") {\n" + caseContainers.toKotlin(commentConverter, "\n") + "\n}"
} }
class CaseContainer(val caseStatement: List<Element>, statements: List<Statement>) : Statement() { class CaseContainer(val caseStatement: List<Element>, statements: List<Statement>) : Statement() {
private val block = Block(statements.filterNot { it is BreakStatement || it is ContinueStatement }, true) private val block = Block(statements.filterNot { it is BreakStatement || it is ContinueStatement }, true)
override fun toKotlin() = caseStatement.toKotlin(", ") + " -> " + block.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = caseStatement.toKotlin(commentConverter, ", ") + " -> " + block.toKotlin(commentConverter)
} }
class SwitchLabelStatement(val expression: Expression) : Statement() { class SwitchLabelStatement(val expression: Expression) : Statement() {
override fun toKotlin() = expression.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = expression.toKotlin(commentConverter)
} }
class DefaultSwitchLabelStatement() : Statement() { class DefaultSwitchLabelStatement() : Statement() {
override fun toKotlin() = "else" override fun toKotlinImpl(commentConverter: CommentConverter) = "else"
} }
// Other ------------------------------------------------------------------------------------------------------ // Other ------------------------------------------------------------------------------------------------------
class SynchronizedStatement(val expression: Expression, val block: Block) : Statement() { class SynchronizedStatement(val expression: Expression, val block: Block) : Statement() {
override fun toKotlin() = "synchronized (" + expression.toKotlin() + ") " + block.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter) = "synchronized (" + expression.toKotlin(commentConverter) + ") " + block.toKotlin(commentConverter)
} }
class StatementList(elements: List<Element>) class StatementList(elements: List<Element>)
+2 -2
View File
@@ -16,8 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.Converter
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.CommentConverter
class Trait(name: Identifier, class Trait(name: Identifier,
comments: MemberComments, comments: MemberComments,
@@ -33,7 +33,7 @@ class Trait(name: Identifier,
override val keyword: String override val keyword: String
get() = "trait" get() = "trait"
override fun primaryConstructorSignatureToKotlin() = "" override fun primaryConstructorSignatureToKotlin(commentConverter: CommentConverter) = ""
override fun modifiersToKotlin(): String { override fun modifiersToKotlin(): String {
val modifierList = ArrayList<Modifier>() val modifierList = ArrayList<Modifier>()
@@ -16,8 +16,8 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
class TypeElement(val `type`: Type) : Element() { import org.jetbrains.jet.j2k.CommentConverter
override fun toKotlin() = `type`.toKotlin()
fun toKotlinNotNull(): String = `type`.toNotNullType().toKotlin() class TypeElement(val `type`: Type) : Element() {
override fun toKotlinImpl(commentConverter: CommentConverter) = `type`.toKotlin(commentConverter)
} }
@@ -20,37 +20,39 @@ import com.intellij.psi.PsiTypeParameter
import org.jetbrains.jet.j2k.Converter import org.jetbrains.jet.j2k.Converter
import com.intellij.psi.PsiTypeParameterList import com.intellij.psi.PsiTypeParameterList
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.CommentConverter
class TypeParameter(val name: Identifier, val extendsTypes: List<Type>) : Element() { class TypeParameter(val name: Identifier, val extendsTypes: List<Type>) : Element() {
fun hasWhere(): Boolean = extendsTypes.size() > 1 fun hasWhere(): Boolean = extendsTypes.size() > 1
fun getWhereToKotlin(): String { fun whereToKotlin(commentConverter: CommentConverter): String {
if (hasWhere()) { if (hasWhere()) {
return name.toKotlin() + " : " + extendsTypes[1].toKotlin() return name.toKotlin(commentConverter) + " : " + extendsTypes[1].toKotlin(commentConverter)
} }
return "" return ""
} }
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
if (extendsTypes.size() > 0) { if (extendsTypes.size() > 0) {
return name.toKotlin() + " : " + extendsTypes[0].toKotlin() return name.toKotlin(commentConverter) + " : " + extendsTypes[0].toKotlin(commentConverter)
} }
return name.toKotlin() return name.toKotlin(commentConverter)
} }
} }
class TypeParameterList(val parameters: List<TypeParameter>) : Element() { class TypeParameterList(val parameters: List<TypeParameter>) : Element() {
override fun toKotlin(): String = if (!parameters.isEmpty()) override fun toKotlinImpl(commentConverter: CommentConverter): String {
parameters.map { return if (parameters.isNotEmpty())
it.toKotlin() parameters.map { it.toKotlin(commentConverter) }.makeString(", ", "<", ">")
}.makeString(", ", "<", ">") else
else "" ""
}
fun whereToKotlin(): String { fun whereToKotlin(commentConverter: CommentConverter): String {
if (hasWhere()) { if (hasWhere()) {
val wheres = parameters.map { it.getWhereToKotlin() } val wheres = parameters.map { it.whereToKotlin(commentConverter) }
return "where " + wheres.makeString(", ") return "where " + wheres.makeString(", ")
} }
return "" return ""
@@ -71,7 +73,9 @@ fun Converter.convertTypeParameter(psiTypeParameter: PsiTypeParameter): TypePara
return convertElement(psiTypeParameter) as TypeParameter return convertElement(psiTypeParameter) as TypeParameter
} }
fun Converter.convertTypeParameterList(psiTypeParameterlist: PsiTypeParameterList?): TypeParameterList { fun Converter.convertTypeParameterList(typeParameterList: PsiTypeParameterList?): TypeParameterList {
return if (psiTypeParameterlist == null) TypeParameterList.Empty return if (typeParameterList != null)
else TypeParameterList(psiTypeParameterlist.getTypeParameters()!!.toList().map { convertTypeParameter(it) }) TypeParameterList(typeParameterList.getTypeParameters()!!.toList().map { convertTypeParameter(it) })
else
TypeParameterList.Empty
} }
+31 -33
View File
@@ -16,10 +16,9 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import java.util.ArrayList
import org.jetbrains.jet.j2k.ConverterSettings import org.jetbrains.jet.j2k.ConverterSettings
import org.jetbrains.jet.j2k.CommentConverter
fun Type.isPrimitive(): Boolean = this is PrimitiveType
fun Type.isUnit(): Boolean = this == Type.Unit fun Type.isUnit(): Boolean = this == Type.Unit
enum class Nullability { enum class Nullability {
@@ -34,17 +33,20 @@ fun Nullability.isNullable(settings: ConverterSettings) = when(this) {
Nullability.Default -> !settings.forceNotNullTypes Nullability.Default -> !settings.forceNotNullTypes
} }
abstract class MayBeNullableType(nullability: Nullability, val settings: ConverterSettings) : Type { abstract class MayBeNullableType(nullability: Nullability, val settings: ConverterSettings) : Type() {
override val isNullable: Boolean = nullability.isNullable(settings) override val isNullable: Boolean = nullability.isNullable(settings)
protected val isNullableStr: String
get() = if (isNullable) "?" else ""
} }
trait NotNullType : Type { abstract class NotNullType() : Type() {
override val isNullable: Boolean override val isNullable: Boolean
get() = false get() = false
} }
trait Type : Element { abstract class Type() : Element() {
val isNullable: Boolean abstract val isNullable: Boolean
open fun toNotNullType(): Type { open fun toNotNullType(): Type {
if (isNullable) throw UnsupportedOperationException("toNotNullType must be defined") if (isNullable) throw UnsupportedOperationException("toNotNullType must be defined")
@@ -56,31 +58,27 @@ trait Type : Element {
return this return this
} }
protected fun isNullableStr(): String? { object Empty : NotNullType() {
return if (isNullable) "?" else "" override fun toKotlinImpl(commentConverter: CommentConverter): String = "UNRESOLVED_TYPE"
} }
object Empty : NotNullType { object Unit: NotNullType() {
override fun toKotlin(): String = "UNRESOLVED_TYPE" override fun toKotlinImpl(commentConverter: CommentConverter) = "Unit"
} }
object Unit: NotNullType { override fun equals(other: Any?): Boolean = other is Type && other.toKotlin(CommentConverter.Dummy) == this.toKotlin(CommentConverter.Dummy)
override fun toKotlin() = "Unit"
}
override fun equals(other: Any?): Boolean = other is Type && other.toKotlin() == this.toKotlin() override fun hashCode(): Int = toKotlin(CommentConverter.Dummy).hashCode()
override fun hashCode(): Int = toKotlin().hashCode() override fun toString(): String = toKotlin(CommentConverter.Dummy)
override fun toString(): String = toKotlin()
} }
class ClassType(val `type`: Identifier, val typeArgs: List<Element>, nullability: Nullability, settings: ConverterSettings) class ClassType(val `type`: Identifier, val typeArgs: List<Element>, nullability: Nullability, settings: ConverterSettings)
: MayBeNullableType(nullability, settings) { : MayBeNullableType(nullability, settings) {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
var params = if (typeArgs.isEmpty()) "" else typeArgs.map { it.toKotlin() }.makeString(", ", "<", ">") var params = if (typeArgs.isEmpty()) "" else typeArgs.map { it.toKotlin(commentConverter) }.makeString(", ", "<", ">")
return `type`.toKotlin() + params + isNullableStr() return `type`.toKotlin(commentConverter) + params + isNullableStr
} }
@@ -91,34 +89,34 @@ class ClassType(val `type`: Identifier, val typeArgs: List<Element>, nullability
class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings) class ArrayType(val elementType: Type, nullability: Nullability, settings: ConverterSettings)
: MayBeNullableType(nullability, settings) { : MayBeNullableType(nullability, settings) {
override fun toKotlin(): String { override fun toKotlinImpl(commentConverter: CommentConverter): String {
if (elementType is PrimitiveType) { if (elementType is PrimitiveType) {
return elementType.toKotlin() + "Array" + isNullableStr() return elementType.toKotlin(commentConverter) + "Array" + isNullableStr
} }
return "Array<" + elementType.toKotlin() + ">" + isNullableStr() return "Array<" + elementType.toKotlin(commentConverter) + ">" + isNullableStr
} }
override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, settings) override fun toNotNullType(): Type = ArrayType(elementType, Nullability.NotNull, settings)
override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings) override fun toNullableType(): Type = ArrayType(elementType, Nullability.Nullable, settings)
} }
class InProjectionType(val bound: Type) : NotNullType { class InProjectionType(val bound: Type) : NotNullType() {
override fun toKotlin(): String = "in " + bound.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = "in " + bound.toKotlin(commentConverter)
} }
class OutProjectionType(val bound: Type) : NotNullType { class OutProjectionType(val bound: Type) : NotNullType() {
override fun toKotlin(): String = "out " + bound.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = "out " + bound.toKotlin(commentConverter)
} }
class StarProjectionType() : NotNullType { class StarProjectionType() : NotNullType() {
override fun toKotlin(): String = "*" override fun toKotlinImpl(commentConverter: CommentConverter): String = "*"
} }
class PrimitiveType(val `type`: Identifier) : NotNullType { class PrimitiveType(val `type`: Identifier) : NotNullType() {
override fun toKotlin(): String = `type`.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = `type`.toKotlin(commentConverter)
} }
class VarArgType(val `type`: Type) : NotNullType { class VarArgType(val `type`: Type) : NotNullType() {
override fun toKotlin(): String = `type`.toKotlin() override fun toKotlinImpl(commentConverter: CommentConverter): String = `type`.toKotlin(commentConverter)
} }
+8 -7
View File
@@ -17,13 +17,14 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import java.util.ArrayList import java.util.ArrayList
import org.jetbrains.jet.j2k.CommentConverter
fun List<Element>.toKotlin(separator: String, prefix: String = "", postfix: String = ""): String fun List<Element>.toKotlin(commentConverter: CommentConverter, separator: String, prefix: String = "", postfix: String = ""): String
= if (isNotEmpty()) map { it.toKotlin() }.makeString(separator, prefix, postfix) else "" = if (isNotEmpty()) map { it.toKotlin(commentConverter) }.makeString(separator, prefix, postfix) else ""
fun String.withSuffix(suffix: String): String = if (isEmpty()) "" else this + suffix fun String.withSuffix(suffix: String): String = if (isEmpty()) "" else this + suffix
fun String.withPrefix(prefix: String): String = if (isEmpty()) "" else prefix + this fun String.withPrefix(prefix: String): String = if (isEmpty()) "" else prefix + this
fun Expression.withPrefix(prefix: String): String = if (isEmpty) "" else prefix + toKotlin() fun Expression.withPrefix(prefix: String, commentConverter: CommentConverter): String = if (isEmpty) "" else prefix + toKotlin(commentConverter)
open class WhiteSpaceSeparatedElementList( open class WhiteSpaceSeparatedElementList(
val elements: List<Element>, val elements: List<Element>,
@@ -34,9 +35,9 @@ open class WhiteSpaceSeparatedElementList(
fun isEmpty() = nonEmptyElements.all { it is WhiteSpace } fun isEmpty() = nonEmptyElements.all { it is WhiteSpace }
fun toKotlin(): String { fun toKotlin(commentConverter: CommentConverter): String {
if (isEmpty()) return "" if (isEmpty()) return ""
return nonEmptyElements.surroundWithWhiteSpaces().insertAndMergeWhiteSpaces().map { it.toKotlin() }.makeString("") return nonEmptyElements.surroundWithWhiteSpaces().insertAndMergeWhiteSpaces().map { it.toKotlin(commentConverter) }.makeString("")
} }
private fun List<Element>.surroundWithWhiteSpaces(): List<Element> private fun List<Element>.surroundWithWhiteSpaces(): List<Element>
@@ -71,9 +72,9 @@ open class WhiteSpaceSeparatedElementList(
} }
} }
fun Expression.operandToKotlin(operand: Expression, parenthesisForSamePrecedence: Boolean = false): String { fun Expression.operandToKotlin(operand: Expression, commentConverter: CommentConverter, parenthesisForSamePrecedence: Boolean = false): String {
val parentPrecedence = precedence() ?: throw IllegalArgumentException("Unknown precendence for $this") val parentPrecedence = precedence() ?: throw IllegalArgumentException("Unknown precendence for $this")
val kotlinCode = operand.toKotlin() val kotlinCode = operand.toKotlin(commentConverter)
val operandPrecedence = operand.precedence() ?: return kotlinCode val operandPrecedence = operand.precedence() ?: return kotlinCode
val needParenthesis = parentPrecedence < operandPrecedence || parentPrecedence == operandPrecedence && parenthesisForSamePrecedence val needParenthesis = parentPrecedence < operandPrecedence || parentPrecedence == operandPrecedence && parenthesisForSamePrecedence
return if (needParenthesis) "($kotlinCode)" else kotlinCode return if (needParenthesis) "($kotlinCode)" else kotlinCode
@@ -16,9 +16,11 @@
package org.jetbrains.jet.j2k.ast package org.jetbrains.jet.j2k.ast
import org.jetbrains.jet.j2k.CommentConverter
class WhiteSpace(val text: String) : Element() { class WhiteSpace(val text: String) : Element() {
override fun toKotlin() = text override fun toKotlinImpl(commentConverter: CommentConverter) = text
override val isEmpty: Boolean override val isEmpty: Boolean
get() = text.isEmpty() get() = text.isEmpty()