diff --git a/src/org/jetbrains/jet/j2k/ast/ForeachWithRangeStatement.java b/src/org/jetbrains/jet/j2k/ast/ForeachWithRangeStatement.java new file mode 100644 index 00000000000..b5669d33a68 --- /dev/null +++ b/src/org/jetbrains/jet/j2k/ast/ForeachWithRangeStatement.java @@ -0,0 +1,29 @@ +package org.jetbrains.jet.j2k.ast; + +import org.jetbrains.annotations.NotNull; + +/** + * @author ignatov + */ +public class ForeachWithRangeStatement extends Statement { + private Expression myStart; + private IdentifierImpl myIdentifier; + private Expression myEnd; + private Statement myBody; + + public ForeachWithRangeStatement(IdentifierImpl identifier, Expression start, Expression end, Statement body) { + myStart = start; + myIdentifier = identifier; + myEnd = end; + myBody = body; + } + + @NotNull + @Override + public String toKotlin() { + return "for" + SPACE + "(" + + myIdentifier.toKotlin() + SPACE + "in" + SPACE + myStart.toKotlin() + ".." + myEnd.toKotlin() + + ")" + SPACE + + myBody.toKotlin(); + } +} diff --git a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java index a61f0fc7f37..cd26ad0f662 100644 --- a/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java +++ b/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.java @@ -1,6 +1,9 @@ package org.jetbrains.jet.j2k.visitors; import com.intellij.psi.*; +import com.intellij.psi.search.searches.ReferencesSearch; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.j2k.ast.*; @@ -93,17 +96,66 @@ public class StatementVisitor extends ElementVisitor { } @Override - public void visitForStatement(PsiForStatement statement) { + public void visitForStatement(@NotNull PsiForStatement statement) { super.visitForStatement(statement); - List forStatements = new LinkedList(); - forStatements.add(statementToStatement(statement.getInitialization())); - forStatements.add(new WhileStatement( - expressionToExpression(statement.getCondition()), - new Block( - Arrays.asList(statementToStatement(statement.getBody()), - new Block(Arrays.asList(statementToStatement(statement.getUpdate()))))))); - myResult = new Block(forStatements); + final PsiStatement initialization = statement.getInitialization(); + final PsiStatement update = statement.getUpdate(); + final PsiExpression condition = statement.getCondition(); + final PsiLocalVariable firstChild = initialization != null && initialization.getFirstChild() instanceof PsiLocalVariable ? + (PsiLocalVariable) initialization.getFirstChild() : null; + + final IElementType operationTokenType = condition != null && condition instanceof PsiBinaryExpression ? + ((PsiBinaryExpression) condition).getOperationTokenType() : null; + if ( + initialization != null && + initialization instanceof PsiDeclarationStatement + && initialization.getFirstChild() == initialization.getLastChild() + && condition != null + && update != null + && update.getChildren().length == 1 + && update.getChildren()[0] instanceof PsiPostfixExpression + && ((PsiPostfixExpression) update.getChildren()[0]).getOperationTokenType() == JavaTokenType.PLUSPLUS + && operationTokenType != null + && (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE) + && initialization.getFirstChild() != null + && initialization.getFirstChild() instanceof PsiLocalVariable + && firstChild != null + && firstChild.getNameIdentifier() != null + && isOnceWritableIterator(firstChild) + ) { + final Expression end = expressionToExpression(((PsiBinaryExpression) condition).getROperand()); + final Expression endExpression = operationTokenType == JavaTokenType.LT ? + new BinaryExpression(end, new IdentifierImpl("1"), "-"): + end; + myResult = new ForeachWithRangeStatement( + new IdentifierImpl(firstChild.getName()), + expressionToExpression(firstChild.getInitializer()), + endExpression, + statementToStatement(statement.getBody()) + ); + } else { // common case: while loop instead of for loop + List forStatements = new LinkedList(); + forStatements.add(statementToStatement(initialization)); + forStatements.add(new WhileStatement( + expressionToExpression(condition), + new Block( + Arrays.asList(statementToStatement(statement.getBody()), + new Block(Arrays.asList(statementToStatement(update))))))); + myResult = new Block(forStatements); + } + } + + private static boolean isOnceWritableIterator(PsiLocalVariable firstChild) { + int counter = 0; + if (firstChild != null) + for (PsiReference r : (ReferencesSearch.search(firstChild))) { + if (r instanceof PsiExpression) { + if (PsiUtil.isAccessedForWriting((PsiExpression) r)) + counter++; + } + } + return counter == 1; // only increment usage } @Override diff --git a/testData/ast/for/statement/forRangeWithLE.jav b/testData/ast/for/statement/forRangeWithLE.jav new file mode 100644 index 00000000000..a0069d48943 --- /dev/null +++ b/testData/ast/for/statement/forRangeWithLE.jav @@ -0,0 +1,2 @@ +int[] array = new int[10]; +for (int i = 0; i <= 10; i++) {array[i] = i;} \ No newline at end of file diff --git a/testData/ast/for/statement/forRangeWithLE.kt b/testData/ast/for/statement/forRangeWithLE.kt new file mode 100644 index 00000000000..125e3d65192 --- /dev/null +++ b/testData/ast/for/statement/forRangeWithLE.kt @@ -0,0 +1,4 @@ +var array : IntArray? = IntArray?(10, {null}) +for (i in 0..10) { +array[i] = i +} \ No newline at end of file diff --git a/testData/ast/for/statement/forRangeWithLT.jav b/testData/ast/for/statement/forRangeWithLT.jav new file mode 100644 index 00000000000..19b24cf03fb --- /dev/null +++ b/testData/ast/for/statement/forRangeWithLT.jav @@ -0,0 +1,2 @@ +int[] array = new int[10]; +for (int i = 0; i < 10; i++) {array[i] = i;} \ No newline at end of file diff --git a/testData/ast/for/statement/forRangeWithLT.kt b/testData/ast/for/statement/forRangeWithLT.kt new file mode 100644 index 00000000000..a5a4520c43a --- /dev/null +++ b/testData/ast/for/statement/forRangeWithLT.kt @@ -0,0 +1,4 @@ +var array : IntArray? = IntArray?(10, {null}) +for (i in 0..(10 - 1)) { +array[i] = i +} \ No newline at end of file diff --git a/testData/ast/for/statement/forWithBlock.jav b/testData/ast/for/statement/forWithBlock.jav index b470371f4a3..19b24cf03fb 100644 --- a/testData/ast/for/statement/forWithBlock.jav +++ b/testData/ast/for/statement/forWithBlock.jav @@ -1 +1,2 @@ -for (int i = 0; i < 0; i++) {int i = 1; i++;} \ No newline at end of file +int[] array = new int[10]; +for (int i = 0; i < 10; i++) {array[i] = i;} \ No newline at end of file diff --git a/testData/ast/for/statement/forWithBlock.kt b/testData/ast/for/statement/forWithBlock.kt index 2ed9ae1e9a0..a5a4520c43a 100644 --- a/testData/ast/for/statement/forWithBlock.kt +++ b/testData/ast/for/statement/forWithBlock.kt @@ -1,13 +1,4 @@ -{ -var i : Int = 0 -while ((i < 0)) -{ -{ -var i : Int = 1 -(i++) -} -{ -(i++) -} -} +var array : IntArray? = IntArray?(10, {null}) +for (i in 0..(10 - 1)) { +array[i] = i } \ No newline at end of file diff --git a/testData/ast/for/statement/forWithExpression.kt b/testData/ast/for/statement/forWithExpression.kt index 2fa4c89935e..6333d6a9828 100644 --- a/testData/ast/for/statement/forWithExpression.kt +++ b/testData/ast/for/statement/forWithExpression.kt @@ -1,10 +1 @@ -{ -var i : Int = 0 -while ((i < 0)) -{ -(t++) -{ -(i++) -} -} -} \ No newline at end of file +for (i in 0..(0 - 1)) (t++) \ No newline at end of file diff --git a/testData/ast/labelStatement/statement/complicatedExampleFromJavaTutorial.kt b/testData/ast/labelStatement/statement/complicatedExampleFromJavaTutorial.kt index fbdba6d9552..f636c05dd7f 100644 --- a/testData/ast/labelStatement/statement/complicatedExampleFromJavaTutorial.kt +++ b/testData/ast/labelStatement/statement/complicatedExampleFromJavaTutorial.kt @@ -1,8 +1,4 @@ -@test { -var i : Int = 0 -while ((i <= max)) -{ -{ +@test for (i in 0..max) { var n : Int = substring.length() var j : Int = i var k : Int = 0 @@ -16,11 +12,6 @@ continue@test foundIt = true break@test } -{ -(i++) -} -} -} System.out?.println((if (foundIt) "Found it" else