Preserve formatting of parenthesis in calls too

This commit is contained in:
Valentin Kipyatkov
2016-08-19 22:13:58 +03:00
parent 87294207f9
commit 38edb58e60
15 changed files with 173 additions and 111 deletions
@@ -14,7 +14,8 @@ class A {
return JetBundle.message(
"x.in.y",
DescriptorRenderer.COMPACT.render(declarationDescriptor),
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(containingDescriptor))
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(containingDescriptor)
)
}
}
}
@@ -63,6 +63,16 @@ class CodeConverter(
fun convertExpressions(expressions: List<PsiExpression>): List<Expression>
= expressions.map { convertExpression(it) }
fun convertArgumentList(list: PsiExpressionList): ArgumentList {
val lPar = list.node.findChildByType(JavaTokenType.LPARENTH)?.psi
val rPar = list.node.findChildByType(JavaTokenType.RPARENTH)?.psi
return ArgumentList(
convertExpressions(list.expressions),
LPar().assignPrototype(lPar, CommentsAndSpacesInheritance.LINE_BREAKS),
RPar().assignPrototype(rPar, CommentsAndSpacesInheritance.LINE_BREAKS)
).assignPrototype(list)
}
fun convertExpression(expression: PsiExpression?, shouldParenthesize: Boolean = false): Expression {
if (expression == null) return Expression.Empty
@@ -127,7 +137,7 @@ class CodeConverter(
convertedExpression = LiteralExpression(text)
}
else if (expectedTypeStr == "char") {
convertedExpression = MethodCallExpression.build(convertedExpression, "toChar", emptyList(), emptyList(), false)
convertedExpression = MethodCallExpression.buildNonNull(convertedExpression, "toChar")
}
}
else if (expression is PsiPrefixExpression && expression.isLiteralWithSign()) {
@@ -137,7 +147,7 @@ class CodeConverter(
else {
val conversion = PRIMITIVE_TYPE_CONVERSIONS[expectedTypeStr]
if (conversion != null) {
convertedExpression = MethodCallExpression.buildNotNull(convertedExpression, conversion)
convertedExpression = MethodCallExpression.buildNonNull(convertedExpression, conversion)
}
}
}
@@ -146,7 +156,7 @@ class CodeConverter(
}
fun convertedExpressionType(expression: PsiExpression, expectedType: PsiType): Type {
var convertedExpression = convertExpression(expression)
val convertedExpression = convertExpression(expression)
val actualType = expression.type ?: return ErrorType()
var resultType = typeConverter.convertType(actualType, if (convertedExpression.isNullable) Nullability.Nullable else Nullability.NotNull)
@@ -317,8 +317,11 @@ class Converter private constructor(
if (field is PsiEnumConstant) {
assert(getMethod == null && setMethod == null)
val argumentList = field.argumentList
val params = deferredElement { codeConverter ->
ExpressionList(codeConverter.convertExpressions(argumentList?.expressions ?: arrayOf<PsiExpression>())).assignPrototype(argumentList)
val params = if (argumentList != null && argumentList.expressions.isNotEmpty()) {
deferredElement { codeConverter -> codeConverter.convertArgumentList(argumentList) }
}
else {
null
}
val body = field.initializingClass?.let { convertAnonymousClassBody(it) }
return EnumConstant(name, annotations, modifiers, params, body)
@@ -118,8 +118,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val expectedNullability = if (operationTokenType in NON_NULL_OPERAND_OPS) Nullability.NotNull else null
val leftOperandExpectedType = getOperandExpectedType(left, right, operationTokenType)
var leftConverted = codeConverter.convertExpression(left, leftOperandExpectedType, expectedNullability)
var rightConverted = codeConverter.convertExpression(
val leftConverted = codeConverter.convertExpression(left, leftOperandExpectedType, expectedNullability)
val rightConverted = codeConverter.convertExpression(
right,
if (leftOperandExpectedType == null)
getOperandExpectedType(right, left, operationTokenType)
@@ -129,7 +129,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
)
if (operationTokenType == JavaTokenType.GTGTGT) {
result = MethodCallExpression.buildNotNull(leftConverted, "ushr", listOf(rightConverted))
result = MethodCallExpression.buildNonNull(leftConverted, "ushr", ArgumentList.withNoPrototype(rightConverted))
}
else {
var operator = Operator(operationTokenType)
@@ -509,7 +509,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val operand = codeConverter.convertExpression(expression.operand, expression.operand!!.type)
val token = expression.operationTokenType
if (token == JavaTokenType.TILDE) {
result = MethodCallExpression.buildNotNull(operand, "inv")
result = MethodCallExpression.buildNonNull(operand, "inv")
}
else if (token == JavaTokenType.EXCL && operand is BinaryExpression && operand.op.asString() == "==") { // happens when equals is converted to ==
result = BinaryExpression(operand.left, operand.right, Operator(JavaTokenType.NE).assignPrototype(expression.operand))
@@ -623,7 +623,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText]
val operandConverted = codeConverter.convertExpression(operand)
if (operandType is PsiPrimitiveType && typeConversion != null) {
result = MethodCallExpression.buildNotNull(operandConverted, typeConversion)
result = MethodCallExpression.buildNonNull(operandConverted, typeConversion)
}
else {
val nullability = if (operandConverted.isNullable && !expression.isQualifier())
@@ -659,8 +659,9 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
result = PolyadicExpression(args, operators).assignPrototype(expression)
}
private fun convertArguments(expression: PsiCallExpression, isExtension: Boolean = false): List<Expression> {
var arguments = expression.argumentList?.expressions?.toList() ?: listOf()
private fun convertArguments(expression: PsiCallExpression, isExtension: Boolean = false): ArgumentList {
val argumentList = expression.argumentList
var arguments = argumentList?.expressions?.toList() ?: listOf()
if (isExtension && arguments.isNotEmpty()) {
arguments = arguments.drop(1)
}
@@ -670,7 +671,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val commentsAndSpacesInheritance = CommentsAndSpacesInheritance.LINE_BREAKS
return if (arguments.size == parameters.size) {
val convertedArguments = if (arguments.size == parameters.size) {
arguments.mapIndexed { i, argument ->
val expectedNullability = typeConverter.variableNullability(parameters[i])
val converted = codeConverter.convertExpression(argument, parameters[i].type, expectedNullability)
@@ -685,6 +686,15 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
else {
arguments.map { codeConverter.convertExpression(it).assignPrototype(it, commentsAndSpacesInheritance) }
}
val lPar = argumentList?.node?.findChildByType(JavaTokenType.LPARENTH)?.psi
val rPar = argumentList?.node?.findChildByType(JavaTokenType.RPARENTH)?.psi
return ArgumentList(
convertedArguments,
LPar().assignPrototype(lPar, CommentsAndSpacesInheritance.LINE_BREAKS),
RPar().assignPrototype(rPar, CommentsAndSpacesInheritance.LINE_BREAKS)
).assignPrototype(argumentList)
}
override fun visitLambdaExpression(expression: PsiLambdaExpression) {
@@ -772,7 +782,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
val specialMethod = method?.let { SpecialMethod.match(it, callParams.size, converter.services) }
val statement: Statement = if (expression.isConstructor) {
MethodCallExpression.build(null, convertMethodReferenceQualifier(qualifier), callParams.map { it.first }, emptyList(), false)
val argumentList = ArgumentList.withNoPrototype(callParams.map { it.first })
MethodCallExpression.buildNonNull(null, convertMethodReferenceQualifier(qualifier), argumentList)
}
else if (specialMethod != null) {
val factory = PsiElementFactory.SERVICE.getInstance(converter.project)
@@ -800,7 +811,8 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
}
else {
val referenceName = expression.referenceName!!
MethodCallExpression.build(receiver?.first, referenceName, callParams.map { it.first }, emptyList(), false)
val argumentList = ArgumentList.withNoPrototype(callParams.map { it.first })
MethodCallExpression.buildNonNull(receiver?.first, referenceName, argumentList)
}
statement.assignNoPrototype()
@@ -822,12 +834,10 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
}
else {
val convertedFunctionalType = converter.typeConverter.convertType(functionalType)
result = MethodCallExpression.build(
result = MethodCallExpression.buildNonNull(
null,
convertedFunctionalType.canonicalCode(),
listOf(lambdaExpression),
emptyList(),
false
ArgumentList.withNoPrototype(lambdaExpression)
)
}
}
@@ -138,7 +138,8 @@ class ForConverter(
block.generateCode(builder)
}
else {
val call = MethodCallExpression.build(null, "run", listOf(LambdaExpression(null, block)), listOf(), false)
val argumentList = ArgumentList.withNoPrototype(LambdaExpression(null, block))
val call = MethodCallExpression.buildNonNull(null, "run", argumentList)
call.generateCode(builder)
}
}
@@ -256,7 +257,7 @@ class ForConverter(
if (indices == null) return null
return if (reversed)
MethodCallExpression.build(indices.assignNoPrototype(), "reversed", listOf(), listOf(), false)
MethodCallExpression.buildNonNull(indices.assignNoPrototype(), "reversed")
else
indices
}
@@ -208,68 +208,80 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
COLLECTIONS_EMPTY_LIST(Collections::class.java.name, "emptyList", 0) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(null, "emptyList", listOf(), typeArgumentsConverted, false)
= MethodCallExpression.buildNonNull(null, "emptyList", ArgumentList.withNoPrototype(), typeArgumentsConverted)
},
COLLECTIONS_EMPTY_SET(Collections::class.java.name, "emptySet", 0) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(null, "emptySet", listOf(), typeArgumentsConverted, false)
= MethodCallExpression.buildNonNull(null, "emptySet", ArgumentList.withNoPrototype(), typeArgumentsConverted)
},
COLLECTIONS_EMPTY_MAP(Collections::class.java.name, "emptyMap", 0) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(null, "emptyMap", listOf(), typeArgumentsConverted, false)
= MethodCallExpression.buildNonNull(null, "emptyMap", ArgumentList.withNoPrototype(), typeArgumentsConverted)
},
COLLECTIONS_SINGLETON_LIST(Collections::class.java.name, "singletonList", 1) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(null, "listOf", listOf(codeConverter.convertExpression(arguments.single())), typeArgumentsConverted, false)
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
val argumentList = ArgumentList.withNoPrototype(codeConverter.convertExpression(arguments.single()))
return MethodCallExpression.buildNonNull(null, "listOf", argumentList, typeArgumentsConverted)
}
},
COLLECTIONS_SINGLETON(Collections::class.java.name, "singleton", 1) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(null, "setOf", listOf(codeConverter.convertExpression(arguments.single())), typeArgumentsConverted, false)
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
val argumentList = ArgumentList.withNoPrototype(codeConverter.convertExpression(arguments.single()))
return MethodCallExpression.buildNonNull(null, "setOf", argumentList, typeArgumentsConverted)
}
},
STRING_TRIM(JAVA_LANG_STRING, "trim", 0) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
val comparison = BinaryExpression(Identifier.withNoPrototype("it", isNullable = false), LiteralExpression("' '").assignNoPrototype(), Operator(JavaTokenType.LE).assignNoPrototype()).assignNoPrototype()
return MethodCallExpression.buildNotNull(
codeConverter.convertExpression(qualifier), "trim",
listOf(LambdaExpression(null, Block.of(comparison).assignNoPrototype())), emptyList())
val argumentList = ArgumentList.withNoPrototype(LambdaExpression(null, Block.of(comparison).assignNoPrototype()))
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "trim", argumentList)
}
},
STRING_REPLACE_ALL(JAVA_LANG_STRING, "replaceAll", 2) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(codeConverter.convertExpression(qualifier), "replace",
listOf(
codeConverter.convertToRegex(arguments[0]),
codeConverter.convertExpression(arguments[1])
), emptyList(), false)
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
val argumentList = ArgumentList.withNoPrototype(
codeConverter.convertToRegex(arguments[0]),
codeConverter.convertExpression(arguments[1])
)
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "replace", argumentList)
}
},
STRING_REPLACE_FIRST(JAVA_LANG_STRING, "replaceFirst", 2) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(codeConverter.convertExpression(qualifier), "replaceFirst",
listOf(
codeConverter.convertToRegex(arguments[0]),
codeConverter.convertExpression(arguments[1])
), emptyList(), false)
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
return MethodCallExpression.buildNonNull(
codeConverter.convertExpression(qualifier), "replaceFirst",
ArgumentList.withNoPrototype(
codeConverter.convertToRegex(arguments[0]),
codeConverter.convertExpression(arguments[1])
)
)
}
},
STRING_MATCHES(JAVA_LANG_STRING, "matches", 1) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(codeConverter.convertExpression(qualifier), "matches", listOf(codeConverter.convertToRegex(arguments.single())), emptyList(), false)
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
val argumentList = ArgumentList.withNoPrototype(codeConverter.convertToRegex(arguments.single()))
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "matches", argumentList)
}
},
STRING_SPLIT(JAVA_LANG_STRING, "split", 1) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
val splitCall = MethodCallExpression.buildNotNull(codeConverter.convertExpression(qualifier), "split", listOf(codeConverter.convertToRegex(arguments.single())), emptyList()).assignNoPrototype()
val isEmptyCall = MethodCallExpression.buildNotNull(Identifier.withNoPrototype("it", isNullable = false), "isEmpty", emptyList(), emptyList()).assignNoPrototype()
val splitCall = MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "split",
ArgumentList.withNoPrototype(codeConverter.convertToRegex(arguments.single()))
).assignNoPrototype()
val isEmptyCall = MethodCallExpression.buildNonNull(Identifier.withNoPrototype("it", isNullable = false), "isEmpty").assignNoPrototype()
val isEmptyCallBlock = Block.of(isEmptyCall).assignNoPrototype()
val dropLastCall = MethodCallExpression.buildNotNull(splitCall, "dropLastWhile", listOf(LambdaExpression(null, isEmptyCallBlock).assignNoPrototype())).assignNoPrototype()
return MethodCallExpression.buildNotNull(dropLastCall, "toTypedArray", emptyList(), emptyList())
val dropLastCall = MethodCallExpression.buildNonNull(splitCall, "dropLastWhile",
ArgumentList.withNoPrototype(LambdaExpression(null, isEmptyCallBlock).assignNoPrototype())).assignNoPrototype()
return MethodCallExpression.buildNonNull(dropLastCall, "toTypedArray")
}
},
@@ -281,7 +293,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
val limit = evaluator.computeConstantExpression(arguments[1], /* throwExceptionOnOverflow = */ false) as? Int
val splitArguments = when {
limit == null -> // not a constant
listOf(patternArgument, MethodCallExpression.buildNotNull(limitArgument, "coerceAtLeast", listOf(LiteralExpression("0").assignNoPrototype()), emptyList()).assignNoPrototype())
listOf(patternArgument, MethodCallExpression.buildNonNull(limitArgument, "coerceAtLeast", ArgumentList.withNoPrototype(LiteralExpression("0").assignNoPrototype())).assignNoPrototype())
limit < 0 -> // negative, same behavior as split(regex) in kotlin
listOf(patternArgument)
limit == 0 -> // zero, same replacement as for split without limit
@@ -290,8 +302,8 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
listOf(patternArgument, limitArgument)
}
val splitCall = MethodCallExpression.buildNotNull(codeConverter.convertExpression(qualifier), "split", splitArguments, emptyList()).assignNoPrototype()
return MethodCallExpression.buildNotNull(splitCall, "toTypedArray", emptyList(), emptyList())
val splitCall = MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "split", ArgumentList.withNoPrototype(splitArguments)).assignNoPrototype()
return MethodCallExpression.buildNonNull(splitCall, "toTypedArray")
}
},
@@ -299,8 +311,10 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
override fun matches(method: PsiMethod, superMethodsSearcher: SuperMethodsSearcher): Boolean
= super.matches(method, superMethodsSearcher) && method.parameterList.parameters.last().type.canonicalText == "java.lang.Iterable<? extends java.lang.CharSequence>"
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression?
= MethodCallExpression.buildNotNull(codeConverter.convertExpression(arguments[1]), "joinToString", codeConverter.convertExpressions(arguments.take(1)), emptyList())
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): Expression? {
val argumentList = ArgumentList.withNoPrototype(codeConverter.convertExpressions(arguments.take(1)))
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(arguments[1]), "joinToString", argumentList)
}
},
STRING_JOIN_VARARG(JAVA_LANG_STRING, "join", null) {
@@ -312,10 +326,10 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
return STRING_JOIN.convertCall(qualifier, arguments, typeArgumentsConverted, codeConverter)
}
else {
return MethodCallExpression.buildNotNull(
MethodCallExpression.buildNotNull(null, "arrayOf", codeConverter.convertExpressions(arguments.drop(1))).assignNoPrototype(),
return MethodCallExpression.buildNonNull(
MethodCallExpression.buildNonNull(null, "arrayOf", ArgumentList.withNoPrototype(codeConverter.convertExpressions(arguments.drop(1)))).assignNoPrototype(),
"joinToString",
codeConverter.convertExpressions(arguments.take(1))
ArgumentList.withNoPrototype(codeConverter.convertExpressions (arguments.take(1)))
)
}
}
@@ -351,18 +365,20 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
val charsetArg = arguments.lastOrNull()?.check { it.type?.canonicalText == JAVA_LANG_STRING }
val convertedArguments = codeConverter.convertExpressions(arguments).map {
if (charsetArg != null && it.prototypes?.singleOrNull()?.element == charsetArg)
MethodCallExpression.buildNotNull(null, "charset", listOf(it)).assignNoPrototype()
MethodCallExpression.buildNonNull(null, "charset", ArgumentList.withNoPrototype(it)).assignNoPrototype()
else
it
}
return MethodCallExpression.build(codeConverter.convertExpression(qualifier), "toByteArray", convertedArguments, emptyList(), false)
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "toByteArray", ArgumentList.withNoPrototype(convertedArguments))
}
},
STRING_GET_CHARS(JAVA_LANG_STRING, "getChars", 4) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
// reorder parameters: srcBegin(0), srcEnd(1), dst(2), dstOffset(3) -> destination(2), destinationOffset(3), startIndex(0), endIndex(1)
= MethodCallExpression.buildNotNull(codeConverter.convertExpression(qualifier), "toCharArray", codeConverter.convertExpressions(arguments.slice(listOf(2, 3, 0, 1))))
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
// reorder parameters: srcBegin(0), srcEnd(1), dst(2), dstOffset(3) -> destination(2), destinationOffset(3), startIndex(0), endIndex(1)
val argumentList = ArgumentList.withNoPrototype(codeConverter.convertExpressions(arguments.slice(listOf(2, 3, 0, 1))))
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), "toCharArray", argumentList)
}
},
STRING_VALUE_OF_CHAR_ARRAY(JAVA_LANG_STRING, "valueOf", null) {
@@ -373,7 +389,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
}
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(null, "String", codeConverter.convertExpressions(arguments), emptyList(), false)
= MethodCallExpression.buildNonNull(null, "String", ArgumentList.withNoPrototype(codeConverter.convertExpressions (arguments)))
},
STRING_COPY_VALUE_OF_CHAR_ARRAY(JAVA_LANG_STRING, "copyValueOf", null) {
@@ -389,7 +405,7 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
STRING_VALUE_OF(JAVA_LANG_STRING, "valueOf", 1) {
override fun convertCall(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.build(codeConverter.convertExpression(arguments.single(), true), "toString", emptyList(), emptyList(), false)
= MethodCallExpression.buildNonNull(codeConverter.convertExpression(arguments.single(), true), "toString")
},
SYSTEM_OUT_PRINTLN(PrintStream::class.java.name, "println", null) {
@@ -425,14 +441,16 @@ enum class SpecialMethod(val qualifiedClassName: String?, val methodName: String
protected fun Array<PsiExpression>.notNull() = map { it to Nullability.NotNull }
protected fun convertWithChangedName(name: String, qualifier: PsiExpression?, arguments: List<Pair<PsiExpression, Nullability>>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter)
= MethodCallExpression.buildNotNull(codeConverter.convertExpression(qualifier), name, arguments.map { codeConverter.convertExpression(it.first, null, it.second) }, typeArgumentsConverted)
protected fun convertWithChangedName(name: String, qualifier: PsiExpression?, arguments: List<Pair<PsiExpression, Nullability>>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression {
val argumentList = ArgumentList.withNoPrototype(arguments.map { codeConverter.convertExpression(it.first, null, it.second) })
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier), name, argumentList, typeArgumentsConverted)
}
protected fun convertMethodCallWithReceiverCast(qualifier: PsiExpression?, arguments: Array<PsiExpression>, typeArgumentsConverted: List<Type>, codeConverter: CodeConverter): MethodCallExpression? {
val convertedArguments = arguments.map { codeConverter.convertExpression(it) }
val qualifierWithCast = castQualifierToType(codeConverter, qualifier!!, qualifiedClassName!!)
if (qualifierWithCast != null) {
return MethodCallExpression.build(qualifierWithCast, methodName, convertedArguments, typeArgumentsConverted, false)
return MethodCallExpression.buildNonNull(qualifierWithCast, methodName, ArgumentList.withNoPrototype(convertedArguments), typeArgumentsConverted)
}
return null
}
@@ -470,11 +488,12 @@ private fun convertSystemOutMethodCall(
if (qqualifier.canonicalText != "java.lang.System") return null
if (qualifier.referenceName != "out") return null
if (typeArgumentsConverted.isNotEmpty()) return null
return MethodCallExpression.build(null, methodName, arguments.map { codeConverter.convertExpression(it) }, emptyList(), false)
val argumentList = ArgumentList.withNoPrototype(arguments.map { codeConverter.convertExpression(it) })
return MethodCallExpression.buildNonNull(null, methodName, argumentList)
}
private fun CodeConverter.convertToRegex(expression: PsiExpression?): Expression
= MethodCallExpression.build(convertExpression(expression, true), "toRegex", emptyList(), emptyList(), false).assignNoPrototype()
= MethodCallExpression.buildNonNull(convertExpression(expression, true), "toRegex").assignNoPrototype()
private fun addIgnoreCaseArgument(
qualifier: PsiExpression?,
@@ -486,8 +505,10 @@ private fun addIgnoreCaseArgument(
): Expression {
val ignoreCaseExpression = ignoreCaseArgument?.let { codeConverter.convertExpression(it) } ?: LiteralExpression("true").assignNoPrototype()
val ignoreCaseArgumentExpression = AssignmentExpression(Identifier.withNoPrototype("ignoreCase"), ignoreCaseExpression, Operator.EQ).assignNoPrototype()
return MethodCallExpression.build(codeConverter.convertExpression(qualifier), methodName,
arguments.map { codeConverter.convertExpression(it, null, Nullability.NotNull) } + ignoreCaseArgumentExpression,
typeArgumentsConverted, false)
val argumentList = ArgumentList.withNoPrototype(arguments.map { codeConverter.convertExpression(it, null, Nullability.NotNull) } + ignoreCaseArgumentExpression)
return MethodCallExpression.buildNonNull(codeConverter.convertExpression(qualifier),
methodName,
argumentList,
typeArgumentsConverted)
}
@@ -54,18 +54,18 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
val descriptionExpr = statement.assertDescription
val condition = codeConverter.convertExpression(statement.assertCondition)
if (descriptionExpr == null) {
result = MethodCallExpression.buildNotNull(null, "assert", listOf(condition))
result = MethodCallExpression.buildNonNull(null, "assert", ArgumentList.withNoPrototype(condition))
}
else {
val description = codeConverter.convertExpression(descriptionExpr)
val lambda = LambdaExpression(null, Block.of(description).assignNoPrototype())
result = MethodCallExpression.build(null, "assert", listOf(condition, lambda), listOf(), false)
result = MethodCallExpression.buildNonNull(null, "assert", ArgumentList.withNoPrototype(condition, lambda))
}
}
override fun visitBlockStatement(statement: PsiBlockStatement) {
val block = codeConverter.convertBlock(statement.codeBlock)
result = MethodCallExpression.build(null, "run", listOf(LambdaExpression(null, block).assignNoPrototype()), listOf(), false)
result = MethodCallExpression.buildNonNull(null, "run", ArgumentList.withNoPrototype(LambdaExpression(null, block).assignNoPrototype()))
}
override fun visitBreakStatement(statement: PsiBreakStatement) {
@@ -218,7 +218,7 @@ class DefaultStatementConverter : JavaElementVisitor(), StatementConverter {
val parameter = LambdaParameter(Identifier.withNoPrototype(variable.name!!), null).assignNoPrototype()
val parameterList = ParameterList(listOf(parameter), lPar = null, rPar = null).assignNoPrototype()
val lambda = LambdaExpression(parameterList, block)
expression = MethodCallExpression.build(codeConverter.convertExpression(variable.initializer), "use", listOf(lambda), listOf(), false)
expression = MethodCallExpression.buildNonNull(codeConverter.convertExpression(variable.initializer), "use", ArgumentList.withNoPrototype(lambda))
expression.assignNoPrototype()
block = Block.of(expression).assignNoPrototype()
}
+2 -2
View File
@@ -34,8 +34,8 @@ fun getDefaultInitializer(property: Property): Expression? {
when (t.name.name) {
"Boolean" -> LiteralExpression("false")
"Char" -> LiteralExpression("' '")
"Double" -> MethodCallExpression.buildNotNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.DOUBLE.toString())
"Float" -> MethodCallExpression.buildNotNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.FLOAT.toString())
"Double" -> MethodCallExpression.buildNonNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.DOUBLE.toString())
"Float" -> MethodCallExpression.buildNonNull(LiteralExpression("0").assignNoPrototype(), OperatorConventions.FLOAT.toString())
else -> LiteralExpression("0")
}
}
@@ -19,11 +19,22 @@ package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class ExpressionList(val expressions: List<Expression>) : Expression() {
class ArgumentList(
val expressions: List<Expression>,
val lPar: LPar,
val rPar: RPar
) : Expression() {
override fun generateCode(builder: CodeBuilder) {
builder.append(lPar)
builder.append(expressions, ", ")
builder.append(rPar)
}
override val isEmpty: Boolean
get() = expressions.isEmpty()
companion object {
fun withNoPrototype(arguments: List<Expression>): ArgumentList {
return ArgumentList(arguments, LPar().assignNoPrototype(), RPar().assignNoPrototype()).assignNoPrototype()
}
fun withNoPrototype(vararg arguments: Expression): ArgumentList = withNoPrototype(arguments.asList())
}
}
@@ -22,19 +22,19 @@ class EnumConstant(
val identifier: Identifier,
annotations: Annotations,
modifiers: Modifiers,
val params: DeferredElement<ExpressionList>,
val params: DeferredElement<ArgumentList>?,
val body: AnonymousClassBody?
) : Member(annotations, modifiers) {
override fun generateCode(builder: CodeBuilder) {
builder append annotations append identifier
builder.append(annotations).append(identifier)
if (!params.isEmpty) {
builder append "(" append params append ")"
if (params != null) {
builder.append(params)
}
if (body != null) {
builder append body
builder.append(body)
}
}
}
@@ -257,5 +257,5 @@ fun createArrayInitializerExpression(arrayType: ArrayType, initializers: List<Ex
"arrayOf<" + arrayType.elementType.canonicalCode() + ">"
else
"arrayOf"
return MethodCallExpression.buildNotNull(null, createArrayFunction, initializers)
return MethodCallExpression.buildNonNull(null, createArrayFunction, ArgumentList.withNoPrototype(initializers))
}
@@ -21,37 +21,41 @@ import org.jetbrains.kotlin.j2k.append
class MethodCallExpression(
val methodExpression: Expression,
val arguments: List<Expression>,
val argumentList: ArgumentList,
val typeArguments: List<Type>,
override val isNullable: Boolean
) : Expression() {
override fun generateCode(builder: CodeBuilder) {
builder.appendOperand(this, methodExpression).append(typeArguments, ", ", "<", ">")
builder.append("(").append(arguments, ", ").append(")")
builder.append(argumentList)
}
companion object {
fun buildNotNull(receiver: Expression?,
methodName: String,
arguments: List<Expression> = listOf(),
typeArguments: List<Type> = listOf()): MethodCallExpression
= build(receiver, methodName, arguments, typeArguments, false)
fun buildNonNull(
receiver: Expression?,
methodName: String,
argumentList: ArgumentList = ArgumentList.withNoPrototype(),
typeArguments: List<Type> = emptyList()
): MethodCallExpression = build(receiver, methodName, argumentList, typeArguments, false)
fun buildNullable(receiver: Expression?,
methodName: String,
arguments: List<Expression> = listOf(),
typeArguments: List<Type> = listOf()): MethodCallExpression
= build(receiver, methodName, arguments, typeArguments, true)
fun buildNullable(
receiver: Expression?,
methodName: String,
argumentList: ArgumentList = ArgumentList.withNoPrototype(),
typeArguments: List<Type> = emptyList()
): MethodCallExpression = build(receiver, methodName, argumentList, typeArguments, true)
fun build(receiver: Expression?,
methodName: String,
arguments: List<Expression>,
typeArguments: List<Type>,
isNullable: Boolean): MethodCallExpression {
fun build(
receiver: Expression?,
methodName: String,
argumentList: ArgumentList,
typeArguments: List<Type>,
isNullable: Boolean
): MethodCallExpression {
val identifier = Identifier.withNoPrototype(methodName, isNullable = false)
return MethodCallExpression(if (receiver != null) QualifiedExpression(receiver, identifier).assignNoPrototype() else identifier,
arguments,
argumentList,
typeArguments,
isNullable)
}
@@ -17,11 +17,10 @@
package org.jetbrains.kotlin.j2k.ast
import org.jetbrains.kotlin.j2k.CodeBuilder
import org.jetbrains.kotlin.j2k.append
class NewClassExpression(
val name: ReferenceElement?,
val arguments: List<Expression>,
val argumentList: ArgumentList,
val qualifier: Expression = Expression.Empty,
val anonymousClass: AnonymousClassBody? = null
) : Expression() {
@@ -40,7 +39,7 @@ class NewClassExpression(
}
if (anonymousClass == null || !anonymousClass.extendsInterface) {
builder.append("(").append(arguments, ", ").append(")")
builder.append(argumentList)
}
if (anonymousClass != null) {
@@ -5,6 +5,7 @@ class F {
void f2(int[] array) {
f1(1, 2,
3, 4,
array);
array
);
}
}
@@ -5,6 +5,7 @@ internal class F {
fun f2(array: IntArray) {
f1(1, 2,
3, 4,
*array)
*array
)
}
}