Fix for KT-5312 J2K: Correct bit operations priority after conversion
Now `PolyadicExpression` breaks down to BinaryExpression`s
This commit is contained in:
@@ -666,6 +666,26 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun polyadicExpressionToBinaryExpressions(operands: List<Expression>, operators: List<Operator>): Expression {
|
||||
if (operators.isEmpty())
|
||||
return operands.first()
|
||||
else {
|
||||
var op: Operator = operators.first()
|
||||
var index = 0
|
||||
operators.forEachIndexed { i, operator ->
|
||||
if(operator.precedence >= op.precedence) {
|
||||
op = operator
|
||||
index = i
|
||||
}
|
||||
}
|
||||
val left = polyadicExpressionToBinaryExpressions(operands.subList(0, index + 1), operators.subList(0, index))
|
||||
val right = polyadicExpressionToBinaryExpressions(operands.subList(index + 1, operands.size),
|
||||
operators.subList(index + 1, operators.size))
|
||||
return BinaryExpression(left, right, op).assignNoPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPolyadicExpression(expression: PsiPolyadicExpression) {
|
||||
val args = expression.operands.map {
|
||||
codeConverter.convertExpression(it, expression.type).assignPrototype(it, CommentsAndSpacesInheritance.LINE_BREAKS)
|
||||
@@ -677,8 +697,7 @@ class DefaultExpressionConverter : JavaElementVisitor(), ExpressionConverter {
|
||||
operator.assignPrototype(it, commentsAndSpacesInheritance)
|
||||
}
|
||||
}
|
||||
|
||||
result = PolyadicExpression(args, operators).assignPrototype(expression)
|
||||
result = polyadicExpressionToBinaryExpressions(args, operators).assignPrototype(expression)
|
||||
}
|
||||
|
||||
private fun convertArguments(expression: PsiCallExpression, isExtension: Boolean = false): ArgumentList {
|
||||
|
||||
@@ -145,20 +145,6 @@ class QualifiedExpression(val qualifier: Expression, val identifier: Expression,
|
||||
}
|
||||
}
|
||||
|
||||
class PolyadicExpression(val expressions: List<Expression>, val operators: List<Operator>) : Expression() {
|
||||
override fun generateCode(builder: CodeBuilder) {
|
||||
assert(expressions.size == operators.size + 1)
|
||||
for ((i, expression) in expressions.withIndex()) {
|
||||
builder.append(expression)
|
||||
if (i < operators.size) {
|
||||
builder.append(" ")
|
||||
builder.append(operators[i])
|
||||
builder.append(" ")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open class Operator(val operatorType: IElementType): Expression() {
|
||||
override fun generateCode(builder: CodeBuilder) {
|
||||
builder.append(asString(operatorType))
|
||||
@@ -176,8 +162,21 @@ open class Operator(val operatorType: IElementType): Expression() {
|
||||
}
|
||||
}
|
||||
|
||||
val precedence: Int
|
||||
get() = when (this.operatorType) {
|
||||
JavaTokenType.ASTERISK, JavaTokenType.DIV, JavaTokenType.PERC -> 3
|
||||
JavaTokenType.PLUS, JavaTokenType.MINUS -> 4
|
||||
KtTokens.ELVIS -> 7
|
||||
JavaTokenType.GT, JavaTokenType.LT, JavaTokenType.GE, JavaTokenType.LE -> 9
|
||||
JavaTokenType.EQEQ, JavaTokenType.NE, KtTokens.EQEQEQ, KtTokens.EXCLEQEQEQ -> 10
|
||||
JavaTokenType.ANDAND -> 11
|
||||
JavaTokenType.OROR -> 12
|
||||
JavaTokenType.GTGTGT, JavaTokenType.GTGT, JavaTokenType.LTLT -> 7
|
||||
else -> 6 /* simple name */
|
||||
}
|
||||
|
||||
private fun asString(tokenType: IElementType): String {
|
||||
return when(tokenType) {
|
||||
return when (tokenType) {
|
||||
JavaTokenType.EQ -> "="
|
||||
JavaTokenType.EQEQ -> "=="
|
||||
JavaTokenType.NE -> "!="
|
||||
|
||||
@@ -33,23 +33,14 @@ fun CodeBuilder.appendOperand(expression: Expression, operand: Expression, paren
|
||||
}
|
||||
|
||||
private fun Expression.precedence(): Int? {
|
||||
return when(this) {
|
||||
return when (this) {
|
||||
is QualifiedExpression, is MethodCallExpression, is ArrayAccessExpression, is PostfixExpression, is BangBangExpression, is StarExpression -> 0
|
||||
|
||||
is PrefixExpression -> 1
|
||||
|
||||
is TypeCastExpression -> 2
|
||||
|
||||
is BinaryExpression -> when(op.asString()) {
|
||||
"*", "/", "%" -> 3
|
||||
"+", "-" -> 4
|
||||
"?:" -> 7
|
||||
">", "<", ">=", "<=" -> 9
|
||||
"==", "!=", "===", "!===" -> 10
|
||||
"&&" -> 11
|
||||
"||" -> 12
|
||||
else -> 6 /* simple name */
|
||||
}
|
||||
is BinaryExpression -> op.precedence
|
||||
|
||||
is RangeExpression, is DownToExpression -> 5
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
//expression
|
||||
5 << 16 | 0 >> 8 | 1
|
||||
@@ -0,0 +1 @@
|
||||
5 shl 16 or (0 shr 8) or 1
|
||||
+2
@@ -0,0 +1,2 @@
|
||||
//expression
|
||||
/*pre*/ 5 /*operand '5'*/ << /*left shift*/ 16 /*operand '16'*/ | /*or*/ 1 /*operand '1'*/ >> /*right shift*/ 8 /*operand '8'*/ | /*or*/ 0 /*operand '0'*/ /*post comment*/
|
||||
+1
@@ -0,0 +1 @@
|
||||
/*pre*/ 5 /*operand '5'*/ shl /*left shift*/ 16 or /*or*/ (1 /*operand '1'*/ shr /*right shift*/ 8 /*operand '8'*/) or /*or*/ 0 /*operand '0'*/ /*post comment*/
|
||||
@@ -418,6 +418,18 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("bitOperationPriority.java")
|
||||
public void testBitOperationPriority() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/assignmentExpression/bitOperationPriority.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("bitOperationPriorityComments.java")
|
||||
public void testBitOperationPriorityComments() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/assignmentExpression/bitOperationPriorityComments.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("divideAssign.java")
|
||||
public void testDivideAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/assignmentExpression/divideAssign.java");
|
||||
|
||||
@@ -418,6 +418,18 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("bitOperationPriority.java")
|
||||
public void testBitOperationPriority() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/assignmentExpression/bitOperationPriority.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("bitOperationPriorityComments.java")
|
||||
public void testBitOperationPriorityComments() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/assignmentExpression/bitOperationPriorityComments.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("divideAssign.java")
|
||||
public void testDivideAssign() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/assignmentExpression/divideAssign.java");
|
||||
|
||||
Reference in New Issue
Block a user