Java to Kotlin converter: replacing equals call to ==/!= and no redundant parethesis generation
#KT-4426 Fixed
This commit is contained in:
@@ -449,12 +449,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) {
|
||||
return result
|
||||
}
|
||||
|
||||
public fun convertTypeElement(element: PsiTypeElement?): TypeElement {
|
||||
return TypeElement(if (element == null)
|
||||
Type.Empty
|
||||
else
|
||||
typeConverter.convertType(element.getType()))
|
||||
}
|
||||
public fun convertTypeElement(element: PsiTypeElement?): TypeElement
|
||||
= TypeElement(if (element == null) Type.Empty else typeConverter.convertType(element.getType()))
|
||||
|
||||
private fun convertToNotNullableTypes(types: Array<out PsiType?>): List<Type>
|
||||
= types.map { typeConverter.convertType(it, Nullability.NotNull) }
|
||||
|
||||
@@ -16,59 +16,78 @@
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
open class ArrayAccessExpression(val expression: Expression, val index: Expression, val lvalue: Boolean) : Expression() {
|
||||
override fun toKotlin() = expression.toKotlin() +
|
||||
(if (!lvalue && expression.isNullable) "!!" else "") +
|
||||
"[" + index.toKotlin() + "]"
|
||||
class ArrayAccessExpression(val expression: Expression, val index: Expression, val lvalue: Boolean) : Expression() {
|
||||
override fun toKotlin() = operandToKotlin(expression) +
|
||||
(if (!lvalue && expression.isNullable) "!!" else "") +
|
||||
"[" + index.toKotlin() + "]"
|
||||
}
|
||||
|
||||
open class AssignmentExpression(val left: Expression, val right: Expression, val op: String) : Expression() {
|
||||
override fun toKotlin() = left.toKotlin() + " " + op + " " + right.toKotlin()
|
||||
class AssignmentExpression(val left: Expression, val right: Expression, val op: String) : Expression() {
|
||||
override fun toKotlin() = operandToKotlin(left) + " " + op + " " + operandToKotlin(right)
|
||||
}
|
||||
|
||||
class BangBangExpression(val expr: Expression) : Expression() {
|
||||
override fun toKotlin() = expr.toKotlin() + "!!"
|
||||
override fun toKotlin() = operandToKotlin(expr) + "!!"
|
||||
}
|
||||
|
||||
open class BinaryExpression(val left: Expression, val right: Expression, val op: String) : Expression() {
|
||||
override fun toKotlin() = left.toKotlin() + " " + op + " " + right.toKotlin()
|
||||
class BinaryExpression(val left: Expression, val right: Expression, val op: String) : Expression() {
|
||||
override fun toKotlin() = operandToKotlin(left, false) + " " + op + " " + operandToKotlin(right, true)
|
||||
}
|
||||
|
||||
open class ClassObjectAccessExpression(val typeElement: TypeElement) : Expression() {
|
||||
override fun toKotlin() = "javaClass<" + typeElement.toKotlinNotNull() + ">()"
|
||||
class IsOperator(val expression: Expression, val typeElement: TypeElement) : Expression() {
|
||||
override fun toKotlin() = operandToKotlin(expression) + " is " + typeElement.toKotlinNotNull()
|
||||
}
|
||||
|
||||
open class IsOperator(val expression: Expression, val typeElement: TypeElement) : Expression() {
|
||||
override fun toKotlin() = expression.toKotlin() + " is " + typeElement.toKotlinNotNull()
|
||||
class TypeCastExpression(val `type`: Type, val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = operandToKotlin(expression) + " as " + `type`.toKotlin()
|
||||
}
|
||||
|
||||
open class TypeCastExpression(val `type`: Type, val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = "(" + expression.toKotlin() + " as " + `type`.toKotlin() + ")"
|
||||
}
|
||||
|
||||
open class LiteralExpression(val literalText: String) : Expression() {
|
||||
class LiteralExpression(val literalText: String) : Expression() {
|
||||
override fun toKotlin() = literalText
|
||||
}
|
||||
|
||||
open class ParenthesizedExpression(val expression: Expression) : Expression() {
|
||||
class ParenthesizedExpression(val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = "(" + expression.toKotlin() + ")"
|
||||
}
|
||||
|
||||
open class PrefixOperator(val op: String, val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = op + expression.toKotlin()
|
||||
class PrefixOperator(val op: String, val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = op + operandToKotlin(expression)
|
||||
|
||||
override val isNullable: Boolean
|
||||
get() = expression.isNullable
|
||||
}
|
||||
|
||||
open class PostfixOperator(val op: String, val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = expression.toKotlin() + op
|
||||
class PostfixOperator(val op: String, val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = operandToKotlin(expression) + op
|
||||
}
|
||||
|
||||
open class ThisExpression(val identifier: Identifier) : Expression() {
|
||||
class ThisExpression(val identifier: Identifier) : Expression() {
|
||||
override fun toKotlin() = "this" + identifier.withPrefix("@")
|
||||
}
|
||||
|
||||
open class SuperExpression(val identifier: Identifier) : Expression() {
|
||||
class SuperExpression(val identifier: Identifier) : Expression() {
|
||||
override fun toKotlin() = "super" + identifier.withPrefix("@")
|
||||
}
|
||||
|
||||
class QualifiedExpression(val expression: Expression, val identifier: Expression) : Expression() {
|
||||
override val isNullable: Boolean
|
||||
get() {
|
||||
if (!expression.isEmpty && expression.isNullable) return true
|
||||
return identifier.isNullable
|
||||
}
|
||||
|
||||
override fun toKotlin(): String {
|
||||
if (!expression.isEmpty) {
|
||||
return operandToKotlin(expression) + (if (expression.isNullable) "?." else ".") + identifier.toKotlin()
|
||||
}
|
||||
|
||||
return identifier.toKotlin()
|
||||
}
|
||||
}
|
||||
|
||||
class PolyadicExpression(val expressions: List<Expression>, val token: String) : Expression() {
|
||||
override fun toKotlin(): String {
|
||||
val expressionsWithConversions = expressions.map { it.toKotlin() }
|
||||
return expressionsWithConversions.makeString(" " + token + " ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ class LocalVariable(
|
||||
private val initializer: Expression,
|
||||
private val isVal: Boolean,
|
||||
private val settings: ConverterSettings
|
||||
) : Expression() {
|
||||
) : Element {
|
||||
|
||||
override fun toKotlin(): String {
|
||||
val varVal = if (isVal) "val" else "var"
|
||||
|
||||
@@ -19,19 +19,19 @@ package org.jetbrains.jet.j2k.ast
|
||||
import java.util.ArrayList
|
||||
|
||||
open class MethodCallExpression(
|
||||
val methodCall: Expression,
|
||||
val methodExpression: Expression,
|
||||
val arguments: List<Expression>,
|
||||
val typeParameters: List<Type>,
|
||||
val resultIsNullable: Boolean = false
|
||||
) : Expression() {
|
||||
|
||||
override val isNullable: Boolean
|
||||
get() = methodCall.isNullable || resultIsNullable
|
||||
get() = methodExpression.isNullable || resultIsNullable
|
||||
|
||||
override fun toKotlin(): String {
|
||||
val typeParamsToKotlin: String = typeParameters.toKotlin(", ", "<", ">")
|
||||
val argumentsMapped = arguments.map { it.toKotlin() }
|
||||
return methodCall.toKotlin() + typeParamsToKotlin + "(" + argumentsMapped.makeString(", ") + ")"
|
||||
return operandToKotlin(methodExpression) + typeParamsToKotlin + "(" + argumentsMapped.makeString(", ") + ")"
|
||||
}
|
||||
|
||||
class object {
|
||||
|
||||
@@ -22,19 +22,14 @@ open class NewClassExpression(
|
||||
val qualifier: Expression = Expression.Empty,
|
||||
val anonymousClass: AnonymousClass? = null
|
||||
) : Expression() {
|
||||
|
||||
override fun toKotlin(): String {
|
||||
val callOperator: String? = (if (qualifier.isNullable)
|
||||
"?."
|
||||
else
|
||||
".")
|
||||
val qualifier: String? = (if (qualifier.isEmpty)
|
||||
""
|
||||
else
|
||||
qualifier.toKotlin() + callOperator)
|
||||
val appliedArguments: String = arguments.toKotlin(", ")
|
||||
return (if (anonymousClass != null)
|
||||
val callOperator = if (qualifier.isNullable) "?." else "."
|
||||
val qualifier = if (qualifier.isEmpty) "" else qualifier.toKotlin() + callOperator
|
||||
val appliedArguments = arguments.toKotlin(", ")
|
||||
return if (anonymousClass != null)
|
||||
"object : " + qualifier + name.toKotlin() + "(" + appliedArguments + ")" + anonymousClass.toKotlin()
|
||||
else
|
||||
qualifier + name.toKotlin() + "(" + appliedArguments + ")")
|
||||
qualifier + name.toKotlin() + "(" + appliedArguments + ")"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,9 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
class Parameter(val identifier: Identifier, val `type`: Type, val varVal: Parameter.VarValModifier, val modifiers: Collection<Modifier>) : Expression() {
|
||||
//TODO: merge with modifiers?
|
||||
//TODO: maybe vararg is modifier too?
|
||||
class Parameter(val identifier: Identifier, val `type`: Type, val varVal: Parameter.VarValModifier, val modifiers: Collection<Modifier>) : Element {
|
||||
public enum class VarValModifier {
|
||||
None
|
||||
Val
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
|
||||
open class ParameterList(val parameters: List<Parameter>) : Expression() {
|
||||
open class ParameterList(val parameters: List<Parameter>) : Element {
|
||||
override fun toKotlin() = parameters.map { it.toKotlin() }.makeString(", ")
|
||||
}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
|
||||
open class PolyadicExpression(val expressions: List<Expression>, val token: String) : Expression() {
|
||||
override fun toKotlin(): String {
|
||||
val expressionsWithConversions = expressions.map { it.toKotlin() }
|
||||
return expressionsWithConversions.makeString(" " + token + " ")
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2013 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
class QualifiedExpression(val expression: Expression, val identifier: Expression) : Expression() {
|
||||
override val isNullable: Boolean
|
||||
get() {
|
||||
if (!expression.isEmpty && expression.isNullable) return true
|
||||
return identifier.isNullable
|
||||
}
|
||||
|
||||
override fun toKotlin(): String {
|
||||
if (!expression.isEmpty) {
|
||||
return expression.toKotlin() + (if (expression.isNullable) "?." else ".") + identifier.toKotlin()
|
||||
}
|
||||
|
||||
return identifier.toKotlin()
|
||||
}
|
||||
}
|
||||
@@ -26,24 +26,24 @@ abstract class Statement() : Element {
|
||||
}
|
||||
}
|
||||
|
||||
open class DeclarationStatement(val elements: List<Element>) : Statement() {
|
||||
class DeclarationStatement(val elements: List<Element>) : Statement() {
|
||||
override fun toKotlin(): String
|
||||
= elements.filterIsInstance(javaClass<LocalVariable>()).map { it.toKotlin() }.makeString("\n")
|
||||
}
|
||||
|
||||
open class ExpressionListStatement(val expressions: List<Expression>) : Expression() {
|
||||
class ExpressionListStatement(val expressions: List<Expression>) : Expression() {
|
||||
override fun toKotlin() = expressions.toKotlin("\n")
|
||||
}
|
||||
|
||||
open 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()
|
||||
}
|
||||
|
||||
open class ReturnStatement(val expression: Expression) : Statement() {
|
||||
class ReturnStatement(val expression: Expression) : Statement() {
|
||||
override fun toKotlin() = "return " + expression.toKotlin()
|
||||
}
|
||||
|
||||
open class IfStatement(
|
||||
class IfStatement(
|
||||
val condition: Expression,
|
||||
val thenStatement: Element,
|
||||
val elseStatement: Element
|
||||
@@ -64,25 +64,23 @@ open class WhileStatement(val condition: Expression, val body: Element) : Statem
|
||||
override fun toKotlin() = "while (" + condition.toKotlin() + ")\n" + body.toKotlin()
|
||||
}
|
||||
|
||||
open class DoWhileStatement(condition: Expression, body: Element) : WhileStatement(condition, body) {
|
||||
class DoWhileStatement(condition: Expression, body: Element) : WhileStatement(condition, body) {
|
||||
override fun toKotlin() = "do\n" + body.toKotlin() + "\nwhile (" + condition.toKotlin() + ")"
|
||||
}
|
||||
|
||||
open class ForeachStatement(
|
||||
class ForeachStatement(
|
||||
val variable: Parameter,
|
||||
val expression: Expression,
|
||||
val body: Element
|
||||
) : Statement() {
|
||||
override fun toKotlin() = "for (" + variable.identifier.toKotlin() + " in " +
|
||||
expression.toKotlin() + ")\n" + body.toKotlin()
|
||||
override fun toKotlin() = "for (" + variable.identifier.toKotlin() + " in " + expression.toKotlin() + ")\n" + body.toKotlin()
|
||||
}
|
||||
|
||||
open class ForeachWithRangeStatement(val identifier: Identifier,
|
||||
class ForeachWithRangeStatement(val identifier: Identifier,
|
||||
val start: Expression,
|
||||
val end: Expression,
|
||||
val body: Element) : Statement() {
|
||||
override fun toKotlin() = "for (" + identifier.toKotlin() + " in " +
|
||||
start.toKotlin() + ".." + end.toKotlin() + ") " + body.toKotlin()
|
||||
override fun toKotlin() = "for (" + identifier.toKotlin() + " in " + start.toKotlin() + ".." + end.toKotlin() + ") " + body.toKotlin()
|
||||
}
|
||||
|
||||
open class BreakStatement(val label: Identifier = Identifier.Empty) : Statement() {
|
||||
@@ -95,7 +93,7 @@ open class ContinueStatement(val label: Identifier = Identifier.Empty) : Stateme
|
||||
|
||||
// Exceptions ----------------------------------------------------------------------------------------------
|
||||
|
||||
open 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 {
|
||||
val builder = StringBuilder()
|
||||
.append("try\n")
|
||||
@@ -110,37 +108,37 @@ open class TryStatement(val block: Block, val catches: List<CatchStatement>, val
|
||||
}
|
||||
}
|
||||
|
||||
open class ThrowStatement(val expression: Expression) : Expression() {
|
||||
class ThrowStatement(val expression: Expression) : Expression() {
|
||||
override fun toKotlin() = "throw " + expression.toKotlin()
|
||||
}
|
||||
|
||||
open 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()
|
||||
}
|
||||
|
||||
// Switch --------------------------------------------------------------------------------------------------
|
||||
|
||||
open 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}"
|
||||
}
|
||||
|
||||
open 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)
|
||||
|
||||
override fun toKotlin() = caseStatement.toKotlin(", ") + " -> " + block.toKotlin()
|
||||
}
|
||||
|
||||
open class SwitchLabelStatement(val expression: Expression) : Statement() {
|
||||
class SwitchLabelStatement(val expression: Expression) : Statement() {
|
||||
override fun toKotlin() = expression.toKotlin()
|
||||
}
|
||||
|
||||
open class DefaultSwitchLabelStatement() : Statement() {
|
||||
class DefaultSwitchLabelStatement() : Statement() {
|
||||
override fun toKotlin() = "else"
|
||||
}
|
||||
|
||||
// Other ------------------------------------------------------------------------------------------------------
|
||||
|
||||
open 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()
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.jet.j2k.ast
|
||||
|
||||
open class TypeElement(val `type`: Type) : Element {
|
||||
class TypeElement(val `type`: Type) : Element {
|
||||
override fun toKotlin() = `type`.toKotlin()
|
||||
|
||||
fun toKotlinNotNull(): String = `type`.toNotNullType().toKotlin()
|
||||
|
||||
@@ -69,4 +69,41 @@ open class WhiteSpaceSeparatedElementList(
|
||||
}
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
fun Expression.operandToKotlin(operand: Expression, parenthesisForSamePrecedence: Boolean = false): String {
|
||||
val parentPrecedence = precedence() ?: throw IllegalArgumentException("Unknown precendence for $this")
|
||||
val kotlinCode = operand.toKotlin()
|
||||
val operandPrecedence = operand.precedence() ?: return kotlinCode
|
||||
val needParenthesis = parentPrecedence < operandPrecedence || parentPrecedence == operandPrecedence && parenthesisForSamePrecedence
|
||||
return if (needParenthesis) "($kotlinCode)" else kotlinCode
|
||||
}
|
||||
|
||||
private fun Expression.precedence(): Int? {
|
||||
return when(this) {
|
||||
is QualifiedExpression, is MethodCallExpression, is ArrayAccessExpression, is PostfixOperator, is BangBangExpression -> 0
|
||||
|
||||
is PrefixOperator -> 1
|
||||
|
||||
is TypeCastExpression -> 2
|
||||
|
||||
is BinaryExpression -> when(op) {
|
||||
"*", "/", "%" -> 3
|
||||
"+", "-" -> 4
|
||||
"?:" -> 6
|
||||
">", "<", ">=", "<=" -> 8
|
||||
"==", "!=", "===", "!===" -> 9
|
||||
"&&" -> 10
|
||||
"||" -> 11
|
||||
else -> 5 /* simple name */
|
||||
}
|
||||
|
||||
is IsOperator -> 7
|
||||
|
||||
is IfStatement -> 12
|
||||
|
||||
is AssignmentExpression -> 13
|
||||
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
@@ -89,19 +89,20 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
}
|
||||
|
||||
override fun visitClassObjectAccessExpression(expression: PsiClassObjectAccessExpression) {
|
||||
result = ClassObjectAccessExpression(converter.convertTypeElement(expression.getOperand()))
|
||||
val typeElement = converter.convertTypeElement(expression.getOperand())
|
||||
result = MethodCallExpression(Identifier("javaClass"), listOf(), listOf(typeElement.`type`.toNotNullType()), true)
|
||||
}
|
||||
|
||||
override fun visitConditionalExpression(expression: PsiConditionalExpression) {
|
||||
val condition = expression.getCondition()
|
||||
val `type` = condition.getType()
|
||||
val e = if (`type` != null)
|
||||
val expr = if (`type` != null)
|
||||
converter.convertExpression(condition, `type`)
|
||||
else
|
||||
converter.convertExpression(condition)
|
||||
result = ParenthesizedExpression(IfStatement(e,
|
||||
converter.convertExpression(expression.getThenExpression()),
|
||||
converter.convertExpression(expression.getElseExpression())))
|
||||
result = IfStatement(expr,
|
||||
converter.convertExpression(expression.getThenExpression()),
|
||||
converter.convertExpression(expression.getElseExpression()))
|
||||
}
|
||||
|
||||
override fun visitExpressionList(list: PsiExpressionList) {
|
||||
@@ -148,6 +149,7 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
if (expression.isSuperConstructorCall() && expression.isInsidePrimaryConstructor()) return // skip it
|
||||
|
||||
val methodExpr = expression.getMethodExpression()
|
||||
val arguments = expression.getArgumentList().getExpressions()
|
||||
val target = methodExpr.resolve()
|
||||
if (target is KotlinLightMethod) {
|
||||
val origin = target.origin
|
||||
@@ -155,7 +157,6 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
if (origin is JetProperty || origin is JetPropertyAccessor) {
|
||||
val property = if (origin is JetProperty) origin else origin.getParent() as JetProperty
|
||||
val parameterCount = target.getParameterList().getParameters().size
|
||||
val arguments = expression.getArgumentList().getExpressions()
|
||||
if (parameterCount == arguments.size) {
|
||||
val propertyName = Identifier(property.getName()!!, false)
|
||||
var isExtension = false
|
||||
@@ -189,7 +190,6 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
else if (origin is JetFunction) {
|
||||
if (isTopLevel) {
|
||||
result = if (origin.isExtensionDeclaration()) {
|
||||
val arguments = expression.getArgumentList().getExpressions()
|
||||
val qualifier = converter.convertExpression(arguments.firstOrNull())
|
||||
MethodCallExpression(QualifiedExpression(qualifier, Identifier(origin.getName()!!, false)),
|
||||
convertArguments(expression, isExtension = true),
|
||||
@@ -208,12 +208,26 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
}
|
||||
}
|
||||
|
||||
if (target is PsiMethod && isObjectEquals(target) && arguments.size == 1) {
|
||||
val qualifier = methodExpr.getQualifierExpression()
|
||||
if (qualifier != null && qualifier !is PsiSuperExpression) {
|
||||
result = BinaryExpression(converter.convertExpression(qualifier), converter.convertExpression(arguments.single()), "==")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
result = MethodCallExpression(converter.convertExpression(methodExpr),
|
||||
convertArguments(expression),
|
||||
typeConverter.convertTypes(expression.getTypeArguments()),
|
||||
typeConverter.convertType(expression.getType()).isNullable)
|
||||
}
|
||||
|
||||
private fun isObjectEquals(method: PsiMethod): Boolean {
|
||||
return method.getName() == "equals" &&
|
||||
method.getParameterList().getParameters().size == 1 &&
|
||||
method.getParameterList().getParameters().single().getType().getCanonicalText() == JAVA_LANG_OBJECT
|
||||
}
|
||||
|
||||
override fun visitNewExpression(expression: PsiNewExpression) {
|
||||
if (expression.getArrayInitializer() != null) {
|
||||
result = createNewEmptyArray(expression)
|
||||
@@ -269,7 +283,10 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
val operand = converter.convertExpression(expression.getOperand(), expression.getOperand()!!.getType())
|
||||
val token = expression.getOperationTokenType()
|
||||
if (token == JavaTokenType.TILDE) {
|
||||
result = MethodCallExpression.build(ParenthesizedExpression(operand), "inv", ArrayList())
|
||||
result = MethodCallExpression.build(operand, "inv", ArrayList())
|
||||
}
|
||||
else if (token == JavaTokenType.EXCL && operand is BinaryExpression && operand.op == "==") { // happens when equals is converted to ==
|
||||
result = BinaryExpression(operand.left, operand.right, "!=")
|
||||
}
|
||||
else {
|
||||
result = PrefixOperator(getOperatorString(token), operand)
|
||||
@@ -375,11 +392,8 @@ class ExpressionVisitor(private val converter: Converter,
|
||||
}
|
||||
|
||||
override fun visitPolyadicExpression(expression: PsiPolyadicExpression) {
|
||||
var parameters = ArrayList<Expression>()
|
||||
for (operand : PsiExpression in expression.getOperands()) {
|
||||
parameters.add(converter.convertExpression(operand, expression.getType()))
|
||||
}
|
||||
result = PolyadicExpression(parameters, getOperatorString(expression.getOperationTokenType()))
|
||||
val args = expression.getOperands().map { converter.convertExpression(it, expression.getType()) }
|
||||
result = PolyadicExpression(args, getOperatorString(expression.getOperationTokenType()))
|
||||
}
|
||||
|
||||
private fun convertArguments(expression: PsiCallExpression, isExtension: Boolean = false): List<Expression> {
|
||||
|
||||
@@ -109,7 +109,7 @@ abstract class AbstractJavaToKotlinConverterTest() : LightIdeaTestCase() {
|
||||
val reformattedText = convertedFile.getText()!!
|
||||
|
||||
return if (inFunContext)
|
||||
reformattedText.removeFirstLine().removeLastLine().trimIndent()
|
||||
reformattedText.removeFirstLine().removeLastLine().trimIndent().trim()
|
||||
else
|
||||
reformattedText
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.jetbrains.jet.j2k.test.AbstractJavaToKotlinConverterTest;
|
||||
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("j2k/tests/testData/ast")
|
||||
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.KotlinExclusion.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
|
||||
@InnerTestClasses({JavaToKotlinConverterTestGenerated.Annotations.class, JavaToKotlinConverterTestGenerated.AnonymousBlock.class, JavaToKotlinConverterTestGenerated.ArrayAccessExpression.class, JavaToKotlinConverterTestGenerated.ArrayInitializerExpression.class, JavaToKotlinConverterTestGenerated.ArrayType.class, JavaToKotlinConverterTestGenerated.AssertStatement.class, JavaToKotlinConverterTestGenerated.AssignmentExpression.class, JavaToKotlinConverterTestGenerated.BinaryExpression.class, JavaToKotlinConverterTestGenerated.BoxedType.class, JavaToKotlinConverterTestGenerated.BreakStatement.class, JavaToKotlinConverterTestGenerated.CallChainExpression.class, JavaToKotlinConverterTestGenerated.Class.class, JavaToKotlinConverterTestGenerated.ClassExpression.class, JavaToKotlinConverterTestGenerated.ConditionalExpression.class, JavaToKotlinConverterTestGenerated.Constructors.class, JavaToKotlinConverterTestGenerated.ContinueStatement.class, JavaToKotlinConverterTestGenerated.DeclarationStatement.class, JavaToKotlinConverterTestGenerated.DoWhileStatement.class, JavaToKotlinConverterTestGenerated.Enum.class, JavaToKotlinConverterTestGenerated.Equals.class, JavaToKotlinConverterTestGenerated.Field.class, JavaToKotlinConverterTestGenerated.For.class, JavaToKotlinConverterTestGenerated.ForeachStatement.class, JavaToKotlinConverterTestGenerated.Formatting.class, JavaToKotlinConverterTestGenerated.Function.class, JavaToKotlinConverterTestGenerated.Identifier.class, JavaToKotlinConverterTestGenerated.IfStatement.class, JavaToKotlinConverterTestGenerated.ImportStatement.class, JavaToKotlinConverterTestGenerated.InProjectionType.class, JavaToKotlinConverterTestGenerated.Inheritance.class, JavaToKotlinConverterTestGenerated.IsOperator.class, JavaToKotlinConverterTestGenerated.Issues.class, JavaToKotlinConverterTestGenerated.KotlinApiAccess.class, JavaToKotlinConverterTestGenerated.KotlinExclusion.class, JavaToKotlinConverterTestGenerated.LabelStatement.class, JavaToKotlinConverterTestGenerated.List.class, JavaToKotlinConverterTestGenerated.LiteralExpression.class, JavaToKotlinConverterTestGenerated.LocalVariable.class, JavaToKotlinConverterTestGenerated.MethodCallExpression.class, JavaToKotlinConverterTestGenerated.Misc.class, JavaToKotlinConverterTestGenerated.NewClassExpression.class, JavaToKotlinConverterTestGenerated.Nullability.class, JavaToKotlinConverterTestGenerated.ObjectLiteral.class, JavaToKotlinConverterTestGenerated.OutProjectionType.class, JavaToKotlinConverterTestGenerated.PackageStatement.class, JavaToKotlinConverterTestGenerated.ParenthesizedExpression.class, JavaToKotlinConverterTestGenerated.PolyadicExpression.class, JavaToKotlinConverterTestGenerated.PostfixOperator.class, JavaToKotlinConverterTestGenerated.PrefixOperator.class, JavaToKotlinConverterTestGenerated.RawGenerics.class, JavaToKotlinConverterTestGenerated.ReturnStatement.class, JavaToKotlinConverterTestGenerated.Settings.class, JavaToKotlinConverterTestGenerated.StarProjectionType.class, JavaToKotlinConverterTestGenerated.SuperExpression.class, JavaToKotlinConverterTestGenerated.Switch.class, JavaToKotlinConverterTestGenerated.SynchronizedStatement.class, JavaToKotlinConverterTestGenerated.ThisExpression.class, JavaToKotlinConverterTestGenerated.ThrowStatement.class, JavaToKotlinConverterTestGenerated.Trait.class, JavaToKotlinConverterTestGenerated.TryStatement.class, JavaToKotlinConverterTestGenerated.TypeCastExpression.class, JavaToKotlinConverterTestGenerated.TypeParameters.class, JavaToKotlinConverterTestGenerated.VarArg.class, JavaToKotlinConverterTestGenerated.WhileStatement.class})
|
||||
public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInAst() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast"), Pattern.compile("^(.+)\\.java$"), true);
|
||||
@@ -384,6 +384,11 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
doTest("j2k/tests/testData/ast/binaryExpression/minus.java");
|
||||
}
|
||||
|
||||
@TestMetadata("multiplePlusMinus.java")
|
||||
public void testMultiplePlusMinus() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/binaryExpression/multiplePlusMinus.java");
|
||||
}
|
||||
|
||||
@TestMetadata("multiply.java")
|
||||
public void testMultiply() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/binaryExpression/multiply.java");
|
||||
@@ -959,6 +964,34 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("j2k/tests/testData/ast/equals")
|
||||
public static class Equals extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInEquals() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("j2k/tests/testData/ast/equals"), Pattern.compile("^(.+)\\.java$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("Equals1.java")
|
||||
public void testEquals1() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/equals/Equals1.java");
|
||||
}
|
||||
|
||||
@TestMetadata("Equals2.java")
|
||||
public void testEquals2() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/equals/Equals2.java");
|
||||
}
|
||||
|
||||
@TestMetadata("Equals3.java")
|
||||
public void testEquals3() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/equals/Equals3.java");
|
||||
}
|
||||
|
||||
@TestMetadata("Equals4.java")
|
||||
public void testEquals4() throws Exception {
|
||||
doTest("j2k/tests/testData/ast/equals/Equals4.java");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@TestMetadata("j2k/tests/testData/ast/field")
|
||||
public static class Field extends AbstractJavaToKotlinConverterTest {
|
||||
public void testAllFilesPresentInField() throws Exception {
|
||||
@@ -2543,6 +2576,7 @@ public class JavaToKotlinConverterTestGenerated extends AbstractJavaToKotlinConv
|
||||
suite.addTestSuite(DeclarationStatement.class);
|
||||
suite.addTestSuite(DoWhileStatement.class);
|
||||
suite.addTestSuite(Enum.class);
|
||||
suite.addTestSuite(Equals.class);
|
||||
suite.addTestSuite(Field.class);
|
||||
suite.addTestSuite(For.class);
|
||||
suite.addTestSuite(ForeachStatement.class);
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
//expression
|
||||
1 + 2 + 3 - 4 + 5
|
||||
@@ -0,0 +1 @@
|
||||
1 + 2 + 3 - 4 + 5
|
||||
@@ -1,4 +1,4 @@
|
||||
(if (a.isEmpty())
|
||||
if (a.isEmpty())
|
||||
0
|
||||
else
|
||||
1)
|
||||
1
|
||||
@@ -0,0 +1,13 @@
|
||||
//file
|
||||
interface I {
|
||||
}
|
||||
|
||||
class C{
|
||||
boolean foo1(I i1, I i2) {
|
||||
return i1.equals(i2)
|
||||
}
|
||||
|
||||
boolean foo2(I i1, I i2) {
|
||||
return !i1.equals(i2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
trait I
|
||||
|
||||
class C() {
|
||||
fun foo1(i1: I, i2: I): Boolean {
|
||||
return i1 == i2
|
||||
}
|
||||
|
||||
fun foo2(i1: I, i2: I): Boolean {
|
||||
return i1 != i2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
//file
|
||||
class C{
|
||||
boolean foo1(String s1, String s2) {
|
||||
return s1.equals(s2)
|
||||
}
|
||||
|
||||
boolean foo2(String s1, String s2) {
|
||||
return !s1.equals(s2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class C() {
|
||||
fun foo1(s1: String, s2: String): Boolean {
|
||||
return s1 == s2
|
||||
}
|
||||
|
||||
fun foo2(s1: String, s2: String): Boolean {
|
||||
return s1 != s2
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
//file
|
||||
class C{
|
||||
public boolean equals(C c) {
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean foo(C c1, C c2) {
|
||||
return c1.equals(c2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
class C() {
|
||||
public fun equals(c: C): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun foo(c1: C, c2: C): Boolean {
|
||||
return c1.equals(c2)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
//file
|
||||
class C{
|
||||
boolean foo(String s1, String s2, String s3, String s4) {
|
||||
return s1.equals(s2) == !s3.equals(s4)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
class C() {
|
||||
fun foo(s1: String, s2: String, s3: String, s4: String): Boolean {
|
||||
return s1 == s2 == (s3 != s4)
|
||||
}
|
||||
}
|
||||
@@ -15,10 +15,10 @@ class Test() {
|
||||
if (One.myContainer.myBoolean)
|
||||
System.out.println("Ok")
|
||||
|
||||
val s = (if (One.myContainer.myBoolean)
|
||||
val s = if (One.myContainer.myBoolean)
|
||||
"YES"
|
||||
else
|
||||
"NO")
|
||||
"NO"
|
||||
|
||||
while (One.myContainer.myBoolean)
|
||||
System.out.println("Ok")
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.io.Serializable
|
||||
public class Language(protected var code: String) : Serializable {
|
||||
|
||||
public fun equals(other: Language): Boolean {
|
||||
return other.toString().equals(this.toString())
|
||||
return other.toString() == this.toString()
|
||||
}
|
||||
|
||||
class object {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
foundIt = true
|
||||
break@test
|
||||
}
|
||||
System.out.println((if (foundIt)
|
||||
System.out.println(if (foundIt)
|
||||
"Found it"
|
||||
else
|
||||
"Didn't find it"))
|
||||
"Didn't find it")
|
||||
@@ -3,9 +3,9 @@ class C() {
|
||||
}
|
||||
|
||||
fun bar(b: Boolean) {
|
||||
foo((if (b)
|
||||
foo(if (b)
|
||||
"a"
|
||||
else
|
||||
null))
|
||||
null)
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
class C() {
|
||||
fun foo(b: Boolean): String? {
|
||||
return (if (b)
|
||||
return if (b)
|
||||
"abc"
|
||||
else
|
||||
null)
|
||||
null
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
// !specifyLocalVariableTypeByDefault: true
|
||||
fun foo(b: Boolean) {
|
||||
val s: String? = ((if (b)
|
||||
val s: String? = (if (b)
|
||||
"abc"
|
||||
else
|
||||
null))
|
||||
null)
|
||||
}
|
||||
@@ -1,2 +1,2 @@
|
||||
val i = (10).inv()
|
||||
val j = ((i * 100)).inv()
|
||||
val i = 10.inv()
|
||||
val j = (i * 100).inv()
|
||||
@@ -1,2 +1,2 @@
|
||||
val i = 10
|
||||
val j = (10).inv()
|
||||
val j = 10.inv()
|
||||
@@ -1 +1 @@
|
||||
(list as List<out String>)
|
||||
list as List<out String>
|
||||
@@ -1 +1 @@
|
||||
(t as Foo)
|
||||
t as Foo
|
||||
@@ -1 +1 @@
|
||||
(t as Int)
|
||||
t as Int
|
||||
@@ -1 +1 @@
|
||||
(list as List<Expression>)
|
||||
list as List<Expression>
|
||||
@@ -1 +1 @@
|
||||
(t as String)
|
||||
t as String
|
||||
@@ -1 +1 @@
|
||||
(list as List<in String>)
|
||||
list as List<in String>
|
||||
@@ -1 +1 @@
|
||||
(list as List<*>)
|
||||
list as List<*>
|
||||
Reference in New Issue
Block a user