KT-584 Convert C-style for statement more correctly

This commit is contained in:
Sergey Ignatov
2011-11-23 13:22:33 +04:00
parent d7e06aeb6a
commit 75a4d34da7
10 changed files with 109 additions and 42 deletions
@@ -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();
}
}
@@ -1,6 +1,9 @@
package org.jetbrains.jet.j2k.visitors; package org.jetbrains.jet.j2k.visitors;
import com.intellij.psi.*; 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.annotations.NotNull;
import org.jetbrains.jet.j2k.ast.*; import org.jetbrains.jet.j2k.ast.*;
@@ -93,17 +96,66 @@ public class StatementVisitor extends ElementVisitor {
} }
@Override @Override
public void visitForStatement(PsiForStatement statement) { public void visitForStatement(@NotNull PsiForStatement statement) {
super.visitForStatement(statement); super.visitForStatement(statement);
List<Statement> forStatements = new LinkedList<Statement>(); final PsiStatement initialization = statement.getInitialization();
forStatements.add(statementToStatement(statement.getInitialization())); final PsiStatement update = statement.getUpdate();
forStatements.add(new WhileStatement( final PsiExpression condition = statement.getCondition();
expressionToExpression(statement.getCondition()), final PsiLocalVariable firstChild = initialization != null && initialization.getFirstChild() instanceof PsiLocalVariable ?
new Block( (PsiLocalVariable) initialization.getFirstChild() : null;
Arrays.asList(statementToStatement(statement.getBody()),
new Block(Arrays.asList(statementToStatement(statement.getUpdate()))))))); final IElementType operationTokenType = condition != null && condition instanceof PsiBinaryExpression ?
myResult = new Block(forStatements); ((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<Statement> forStatements = new LinkedList<Statement>();
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 @Override
@@ -0,0 +1,2 @@
int[] array = new int[10];
for (int i = 0; i <= 10; i++) {array[i] = i;}
@@ -0,0 +1,4 @@
var array : IntArray? = IntArray?(10, {null})
for (i in 0..10) {
array[i] = i
}
@@ -0,0 +1,2 @@
int[] array = new int[10];
for (int i = 0; i < 10; i++) {array[i] = i;}
@@ -0,0 +1,4 @@
var array : IntArray? = IntArray?(10, {null})
for (i in 0..(10 - 1)) {
array[i] = i
}
+2 -1
View File
@@ -1 +1,2 @@
for (int i = 0; i < 0; i++) {int i = 1; i++;} int[] array = new int[10];
for (int i = 0; i < 10; i++) {array[i] = i;}
+3 -12
View File
@@ -1,13 +1,4 @@
{ var array : IntArray? = IntArray?(10, {null})
var i : Int = 0 for (i in 0..(10 - 1)) {
while ((i < 0)) array[i] = i
{
{
var i : Int = 1
(i++)
}
{
(i++)
}
}
} }
@@ -1,10 +1 @@
{ for (i in 0..(0 - 1)) (t++)
var i : Int = 0
while ((i < 0))
{
(t++)
{
(i++)
}
}
}
@@ -1,8 +1,4 @@
@test { @test for (i in 0..max) {
var i : Int = 0
while ((i <= max))
{
{
var n : Int = substring.length() var n : Int = substring.length()
var j : Int = i var j : Int = i
var k : Int = 0 var k : Int = 0
@@ -16,11 +12,6 @@ continue@test
foundIt = true foundIt = true
break@test break@test
} }
{
(i++)
}
}
}
System.out?.println((if (foundIt) System.out?.println((if (foundIt)
"Found it" "Found it"
else else