intention to create simple for-loop from foreach (IDEA-66487)

This commit is contained in:
anna
2012-08-01 12:27:00 +02:00
parent 018c010942
commit 4ffa2bfa49
8 changed files with 133 additions and 36 deletions
@@ -277,6 +277,10 @@
<className>com.siyeh.ipp.forloop.ReplaceForEachLoopWithIndexedForLoopIntention</className>
<categoryKey>intention.category.control.flow</categoryKey>
</intentionAction>
<intentionAction>
<className>com.siyeh.ipp.forloop.ReplaceForEachLoopWithOptimizedIndexedForLoopIntention</className>
<categoryKey>intention.category.control.flow</categoryKey>
</intentionAction>
<intentionAction>
<className>com.siyeh.ipp.forloop.ReplaceForEachLoopWithIteratorForLoopIntention</className>
<categoryKey>intention.category.control.flow</categoryKey>
@@ -18,6 +18,8 @@ replace.equality.with.safe.equals.intention.family.name=Replace Equality with Sa
replace.for.each.loop.with.indexed.for.loop.intention.name=Replace 'for each' loop with indexed 'for' loop
replace.for.each.loop.with.iterator.for.loop.intention.name=Replace 'for each' loop with iterator 'for' loop
replace.for.each.loop.with.indexed.for.loop.intention.family.name=Replace For-each Loop with Indexed For Loop
replace.for.each.loop.with.optimized.indexed.for.loop.intention.name=Replace 'for each' loop with optimized indexed 'for' loop
replace.for.each.loop.with.optimized.indexed.for.loop.intention.family.name=Replace For-each Loop with Optimized Indexed For Loop
replace.for.each.loop.with.iterator.for.loop.intention.family.name=Replace For-each Loop with Iterator For Loop
replace.for.loop.with.while.loop.intention.name=Replace 'for' loop with 'while' loop
replace.for.loop.with.while.loop.intention.family.name=Replace For Loop with While Loop
@@ -60,42 +60,9 @@ public class ReplaceForEachLoopWithIndexedForLoopIntention extends Intention {
context = statement;
}
final String iteratedValueText = getReferenceToIterate(iteratedValue, context);
final String lengthText;
if (isArray) {
lengthText = createVariableName(iteratedValueText + "Length", PsiType.INT, statement);
}
else {
lengthText = createVariableName(iteratedValueText + "Size", PsiType.INT, statement);
}
@NonNls final StringBuilder newStatement = new StringBuilder();
newStatement.append("for(int ");
final String indexText =
createVariableName("i", PsiType.INT, statement);
newStatement.append(indexText);
newStatement.append(" = 0, ");
newStatement.append(lengthText);
newStatement.append(" = ");
if (iteratedValue instanceof PsiTypeCastExpression) {
newStatement.append('(');
newStatement.append(iteratedValueText);
newStatement.append(')');
}
else {
newStatement.append(iteratedValueText);
}
if (isArray) {
newStatement.append(".length;");
}
else {
newStatement.append(".size();");
}
newStatement.append(indexText);
newStatement.append('<');
newStatement.append(lengthText);
newStatement.append(';');
newStatement.append(indexText);
newStatement.append("++)");
newStatement.append("{ ");
final String indexText = createVariableName("i", PsiType.INT, statement);
createForLoopDeclaration(statement, iteratedValue, isArray, iteratedValueText, newStatement, indexText);
final Project project = statement.getProject();
final CodeStyleSettings codeStyleSettings =
CodeStyleSettingsManager.getSettings(project);
@@ -136,6 +103,36 @@ public class ReplaceForEachLoopWithIndexedForLoopIntention extends Intention {
replaceStatementAndShorten(newStatement.toString(), statement);
}
protected void createForLoopDeclaration(PsiForeachStatement statement,
PsiExpression iteratedValue,
boolean array,
String iteratedValueText, StringBuilder newStatement,
final String indexText) {
newStatement.append("for(int ");
newStatement.append(indexText);
newStatement.append(" = 0; ");
newStatement.append(indexText);
newStatement.append('<');
if (iteratedValue instanceof PsiTypeCastExpression) {
newStatement.append('(');
newStatement.append(iteratedValueText);
newStatement.append(')');
}
else {
newStatement.append(iteratedValueText);
}
if (array) {
newStatement.append(".length");
}
else {
newStatement.append(".size()");
}
newStatement.append(';');
newStatement.append(indexText);
newStatement.append("++)");
newStatement.append("{ ");
}
private static String getVariableName(PsiExpression expression) {
if (expression instanceof PsiMethodCallExpression) {
final PsiMethodCallExpression methodCallExpression =
@@ -0,0 +1,70 @@
/*
* Copyright 2000-2012 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.siyeh.ipp.forloop;
import com.intellij.psi.PsiExpression;
import com.intellij.psi.PsiForeachStatement;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiTypeCastExpression;
/**
* User: anna
* Date: 8/1/12
*/
public class ReplaceForEachLoopWithOptimizedIndexedForLoopIntention extends ReplaceForEachLoopWithIndexedForLoopIntention {
@Override
protected void createForLoopDeclaration(PsiForeachStatement statement,
PsiExpression iteratedValue,
boolean isArray,
String iteratedValueText,
StringBuilder newStatement, final String indexText) {
final String lengthText;
if (isArray) {
lengthText = createVariableName(iteratedValueText + "Length", PsiType.INT, statement);
}
else {
lengthText = createVariableName(iteratedValueText + "Size", PsiType.INT, statement);
}
newStatement.append("for(int ");
newStatement.append(indexText);
newStatement.append(" = 0, ");
newStatement.append(lengthText);
newStatement.append(" = ");
if (iteratedValue instanceof PsiTypeCastExpression) {
newStatement.append('(');
newStatement.append(iteratedValueText);
newStatement.append(')');
}
else {
newStatement.append(iteratedValueText);
}
if (isArray) {
newStatement.append(".length;");
}
else {
newStatement.append(".size();");
}
newStatement.append(indexText);
newStatement.append('<');
newStatement.append(lengthText);
newStatement.append(';');
newStatement.append(indexText);
newStatement.append("++)");
newStatement.append("{ ");
}
}
@@ -0,0 +1,9 @@
public class X {
void f() {
String[] array = new String[]{"foo", "bar", "baz"};
for (int i = 0, arrayLength = array.length; i < arrayLength; i++) {
String content = array[i];
System.out.println(content);
}
}
}
@@ -0,0 +1,8 @@
public class X {
void f() {
String[] array = new String[]{"foo", "bar", "baz"};
<spot>for</spot> (String content : array) {
System.out.println(content);
}
}
}
@@ -0,0 +1,7 @@
<html>
<body>
This intention replaces a JDK 5.0 for-each loop which
iterates over a collection or array with an equivalent <b>for</b> loop that uses an index to
iterate over the collection or array and the size or length is stored in local variable.
</body>
</html>
@@ -25,7 +25,7 @@ public class ReplaceForEachLoopWithIndexedForLoopIntentionTest extends IPPTestCa
@Override
protected String getIntentionName() {
return IntentionPowerPackBundle.message("replace.for.each.loop.with.indexed.for.loop.intention.name");
return IntentionPowerPackBundle.message("replace.for.each.loop.with.optimized.indexed.for.loop.intention.name");
}
@Override