J2k: for through range with != comparison is also recognized
This commit is contained in:
@@ -152,81 +152,78 @@ class ForConverter(
|
|||||||
&& !loopVar.hasWriteAccesses(referenceSearcher, condition)
|
&& !loopVar.hasWriteAccesses(referenceSearcher, condition)
|
||||||
&& condition is PsiBinaryExpression) {
|
&& condition is PsiBinaryExpression) {
|
||||||
|
|
||||||
val operationTokenType = condition.getOperationTokenType()
|
|
||||||
val reversed = when (operationTokenType) {
|
|
||||||
JavaTokenType.LT, JavaTokenType.LE -> false
|
|
||||||
JavaTokenType.GT, JavaTokenType.GE -> true
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val left = condition.getLOperand() as? PsiReferenceExpression ?: return null
|
val left = condition.getLOperand() as? PsiReferenceExpression ?: return null
|
||||||
val right = condition.getROperand() ?: return null
|
val right = condition.getROperand() ?: return null
|
||||||
if (left.resolve() == loopVar) {
|
if (left.resolve() == loopVar) {
|
||||||
val start = loopVar.getInitializer() ?: return null
|
val start = loopVar.getInitializer() ?: return null
|
||||||
val operationType = if (reversed) JavaTokenType.MINUSMINUS else JavaTokenType.PLUSPLUS
|
val operationType = (update as? PsiExpressionStatement)?.getExpression()?.isVariableIncrementOrDecrement(loopVar)
|
||||||
if ((update as? PsiExpressionStatement)?.getExpression()?.isVariableIncrementOrDecrement(loopVar, operationType) ?: false) {
|
val reversed = when (operationType) {
|
||||||
val range = forIterationRange(start, right, operationTokenType).assignNoPrototype()
|
JavaTokenType.PLUSPLUS -> false
|
||||||
val explicitType = if (settings.specifyLocalVariableTypeByDefault)
|
JavaTokenType.MINUSMINUS -> true
|
||||||
PrimitiveType(Identifier("Int").assignNoPrototype()).assignNoPrototype()
|
else -> return null
|
||||||
else
|
|
||||||
null
|
|
||||||
return ForeachStatement(loopVar.declarationIdentifier(), explicitType, range, codeConverter.convertStatementOrBlock(body), statement.isInSingleLine())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val inclusive = when (condition.getOperationTokenType()) {
|
||||||
|
JavaTokenType.LT -> if (reversed) return null else false
|
||||||
|
JavaTokenType.LE -> if (reversed) return null else true
|
||||||
|
JavaTokenType.GT -> if (reversed) false else return null
|
||||||
|
JavaTokenType.GE -> if (reversed) true else return null
|
||||||
|
JavaTokenType.NE -> false
|
||||||
|
else -> return null
|
||||||
|
}
|
||||||
|
|
||||||
|
val range = forIterationRange(start, right, reversed, inclusive).assignNoPrototype()
|
||||||
|
val explicitType = if (settings.specifyLocalVariableTypeByDefault)
|
||||||
|
PrimitiveType(Identifier("Int").assignNoPrototype()).assignNoPrototype()
|
||||||
|
else
|
||||||
|
null
|
||||||
|
return ForeachStatement(loopVar.declarationIdentifier(), explicitType, range, codeConverter.convertStatementOrBlock(body), statement.isInSingleLine())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiElement.isVariableIncrementOrDecrement(variable: PsiVariable, operationTokenType: IElementType): Boolean {
|
private fun PsiElement.isVariableIncrementOrDecrement(variable: PsiVariable): IElementType? {
|
||||||
//TODO: simplify code when KT-5453 fixed
|
//TODO: simplify code when KT-5453 fixed
|
||||||
val pair = when (this) {
|
val pair = when (this) {
|
||||||
is PsiPostfixExpression -> getOperationTokenType() to getOperand()
|
is PsiPostfixExpression -> getOperationTokenType() to getOperand()
|
||||||
is PsiPrefixExpression -> getOperationTokenType() to getOperand()
|
is PsiPrefixExpression -> getOperationTokenType() to getOperand()
|
||||||
else -> return false
|
else -> return null
|
||||||
}
|
}
|
||||||
return pair.first == operationTokenType && (pair.second as? PsiReferenceExpression)?.resolve() == variable
|
if ((pair.second as? PsiReferenceExpression)?.resolve() != variable) return null
|
||||||
|
return pair.first
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun forIterationRange(start: PsiExpression, bound: PsiExpression, comparisonTokenType: IElementType): Expression {
|
private fun forIterationRange(start: PsiExpression, bound: PsiExpression, reversed: Boolean, inclusiveComparison: Boolean): Expression {
|
||||||
val indicesRange = indicesIterationRange(start, bound, comparisonTokenType)
|
val indicesRange = indicesIterationRange(start, bound, reversed, inclusiveComparison)
|
||||||
if (indicesRange != null) return indicesRange
|
if (indicesRange != null) return indicesRange
|
||||||
|
|
||||||
val startConverted = codeConverter.convertExpression(start)
|
val startConverted = codeConverter.convertExpression(start)
|
||||||
return when (comparisonTokenType) {
|
return if (reversed)
|
||||||
JavaTokenType.LT, JavaTokenType.LE ->
|
DownToExpression(startConverted, convertBound(bound, if (inclusiveComparison) 0 else +1))
|
||||||
RangeExpression(startConverted, convertBound(bound, if (comparisonTokenType == JavaTokenType.LT) -1 else 0))
|
else
|
||||||
|
RangeExpression(startConverted, convertBound(bound, if (inclusiveComparison) 0 else -1))
|
||||||
JavaTokenType.GT, JavaTokenType.GE ->
|
|
||||||
DownToExpression(startConverted, convertBound(bound, if (comparisonTokenType == JavaTokenType.GT) +1 else 0))
|
|
||||||
|
|
||||||
else ->
|
|
||||||
throw IllegalAccessException()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun indicesIterationRange(start: PsiExpression, bound: PsiExpression, comparisonTokenType: IElementType): Expression? {
|
private fun indicesIterationRange(start: PsiExpression, bound: PsiExpression, reversed: Boolean, inclusiveComparison: Boolean): Expression? {
|
||||||
val reversed = when (comparisonTokenType) {
|
|
||||||
JavaTokenType.LT -> false
|
|
||||||
JavaTokenType.GE -> true
|
|
||||||
else -> return null
|
|
||||||
}
|
|
||||||
|
|
||||||
val lower = if (reversed) bound else start
|
|
||||||
val upper = if (reversed) start else bound
|
|
||||||
|
|
||||||
if ((lower as? PsiLiteralExpression)?.getValue() != 0) return null
|
|
||||||
|
|
||||||
val collectionSize = if (reversed) {
|
val collectionSize = if (reversed) {
|
||||||
if (upper !is PsiBinaryExpression) return null
|
if (!inclusiveComparison) return null
|
||||||
if (upper.getOperationTokenType() != JavaTokenType.MINUS) return null
|
|
||||||
if ((upper.getROperand() as? PsiLiteralExpression)?.getValue() != 1) return null
|
if ((bound as? PsiLiteralExpression)?.getValue() != 0) return null
|
||||||
upper.getLOperand()
|
|
||||||
|
if (start !is PsiBinaryExpression) return null
|
||||||
|
if (start.getOperationTokenType() != JavaTokenType.MINUS) return null
|
||||||
|
if ((start.getROperand() as? PsiLiteralExpression)?.getValue() != 1) return null
|
||||||
|
start.getLOperand()
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
upper
|
if (inclusiveComparison) return null
|
||||||
|
if ((start as? PsiLiteralExpression)?.getValue() != 0) return null
|
||||||
|
bound
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var indices: Expression? = null
|
var indices: Expression? = null
|
||||||
|
|
||||||
// check if it's iteration through list indices
|
// check if it's iteration through list indices
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
public class A {
|
||||||
|
void foo(int min) {
|
||||||
|
for(int i = 10; i != min; i--) {
|
||||||
|
System.out.println(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
public class A {
|
||||||
|
fun foo(min: Int) {
|
||||||
|
for (i in 10 downTo min + 1) {
|
||||||
|
println(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
//statement
|
||||||
|
int[] array = new int[10];
|
||||||
|
for (int i = 0; i != 10; i++) {array[i] = i;}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
val array = IntArray(10)
|
||||||
|
for (i in 0..9) {
|
||||||
|
array[i] = i
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
class C{
|
||||||
|
void foo(List<String> list) {
|
||||||
|
for (int i = 0; i != list.size(); i++) {
|
||||||
|
list.set(i, "a");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import java.util.ArrayList
|
||||||
|
|
||||||
|
class C {
|
||||||
|
fun foo(list: MutableList<String>) {
|
||||||
|
for (i in list.indices) {
|
||||||
|
list.set(i, "a")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1892,6 +1892,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("downTo4.java")
|
||||||
|
public void testDownTo4() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/downTo4.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("falseArrayIndicesReversed.java")
|
@TestMetadata("falseArrayIndicesReversed.java")
|
||||||
public void testFalseArrayIndicesReversed() throws Exception {
|
public void testFalseArrayIndicesReversed() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/falseArrayIndicesReversed.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/falseArrayIndicesReversed.java");
|
||||||
@@ -1940,6 +1946,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forRangeWithNE.java")
|
||||||
|
public void testForRangeWithNE() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forRangeWithNE.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("forThroughArrayIndices.java")
|
@TestMetadata("forThroughArrayIndices.java")
|
||||||
public void testForThroughArrayIndices() throws Exception {
|
public void testForThroughArrayIndices() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughArrayIndices.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughArrayIndices.java");
|
||||||
@@ -1958,6 +1970,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forThroughListIndicesNE.java")
|
||||||
|
public void testForThroughListIndicesNE() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughListIndicesNE.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("forThroughNonArrayIndices.java")
|
@TestMetadata("forThroughNonArrayIndices.java")
|
||||||
public void testForThroughNonArrayIndices() throws Exception {
|
public void testForThroughNonArrayIndices() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughNonArrayIndices.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughNonArrayIndices.java");
|
||||||
|
|||||||
@@ -1892,6 +1892,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("downTo4.java")
|
||||||
|
public void testDownTo4() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/downTo4.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("falseArrayIndicesReversed.java")
|
@TestMetadata("falseArrayIndicesReversed.java")
|
||||||
public void testFalseArrayIndicesReversed() throws Exception {
|
public void testFalseArrayIndicesReversed() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/falseArrayIndicesReversed.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/falseArrayIndicesReversed.java");
|
||||||
@@ -1940,6 +1946,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forRangeWithNE.java")
|
||||||
|
public void testForRangeWithNE() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forRangeWithNE.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("forThroughArrayIndices.java")
|
@TestMetadata("forThroughArrayIndices.java")
|
||||||
public void testForThroughArrayIndices() throws Exception {
|
public void testForThroughArrayIndices() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughArrayIndices.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughArrayIndices.java");
|
||||||
@@ -1958,6 +1970,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("forThroughListIndicesNE.java")
|
||||||
|
public void testForThroughListIndicesNE() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughListIndicesNE.java");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("forThroughNonArrayIndices.java")
|
@TestMetadata("forThroughNonArrayIndices.java")
|
||||||
public void testForThroughNonArrayIndices() throws Exception {
|
public void testForThroughNonArrayIndices() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughNonArrayIndices.java");
|
String fileName = JetTestUtils.navigationMetadata("j2k/testData/fileOrElement/for/forThroughNonArrayIndices.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user