From 8b4f950405c7dac819f5befa7ce8e1f4bb61a59e Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Tue, 17 Jan 2017 11:34:30 +0700 Subject: [PATCH] CountingLoop extracted and used; IndexedContainer simplified --- .../UseBulkOperationInspection.java | 33 +---- .../StreamApiMigrationInspection.java | 64 ++------- .../streamMigration/ToArrayMigration.java | 4 +- .../com/siyeh/ig/psiutils/CountingLoop.java | 131 ++++++++++++++++++ .../siyeh/ig/psiutils/IndexedContainer.java | 58 +------- 5 files changed, 161 insertions(+), 129 deletions(-) create mode 100644 plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/psiutils/CountingLoop.java diff --git a/java/java-impl/src/com/intellij/codeInspection/bulkOperation/UseBulkOperationInspection.java b/java/java-impl/src/com/intellij/codeInspection/bulkOperation/UseBulkOperationInspection.java index 1ae01e2c90bb..f2033424cde8 100644 --- a/java/java-impl/src/com/intellij/codeInspection/bulkOperation/UseBulkOperationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/bulkOperation/UseBulkOperationInspection.java @@ -25,7 +25,6 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.util.RefactoringUtil; -import com.intellij.util.ObjectUtils; import com.siyeh.ig.psiutils.*; import one.util.streamex.StreamEx; import org.jetbrains.annotations.Contract; @@ -138,31 +137,13 @@ public class UseBulkOperationInspection extends BaseJavaBatchLocalInspectionTool @Nullable private static PsiExpression findIterableForIndexedLoop(PsiForStatement loop, PsiExpression getElementExpression) { - IndexedContainer container = IndexedContainer.fromGetExpression(getElementExpression); - if(container == null) return null; - PsiExpression indexExpression = container.extractIndexFromGetExpression(getElementExpression); - - // Check that loop initialization is like `int idx = 0` and loop update is like `idx++` - PsiStatement initialization = loop.getInitialization(); - if (!(initialization instanceof PsiDeclarationStatement)) return null; - PsiElement[] declaredElements = ((PsiDeclarationStatement)initialization).getDeclaredElements(); - if (declaredElements.length != 1 || !(declaredElements[0] instanceof PsiLocalVariable)) return null; - PsiLocalVariable indexVariable = (PsiLocalVariable)declaredElements[0]; - if (!ExpressionUtils.isReferenceTo(indexExpression, indexVariable) || - !ExpressionUtils.isZero(indexVariable.getInitializer()) || - !VariableAccessUtils.variableIsIncremented(indexVariable, loop.getUpdate())) { - return null; - } - - // Check that loop condition is like `idx < arr.length` or `idx < list.size()` - PsiBinaryExpression condition = ObjectUtils.tryCast(loop.getCondition(), PsiBinaryExpression.class); - if (condition == null || - !condition.getOperationTokenType().equals(JavaTokenType.LT) || - !ExpressionUtils.isReferenceTo(condition.getLOperand(), indexVariable)) { - return null; - } - PsiExpression bound = condition.getROperand(); - return container.extractQualifierFromLengthExpression(bound); + CountingLoop countingLoop = CountingLoop.from(loop); + if (countingLoop == null || countingLoop.isIncluding() || !ExpressionUtils.isZero(countingLoop.getInitializer())) return null; + IndexedContainer container = IndexedContainer.fromLengthExpression(countingLoop.getBound()); + if (container == null) return null; + PsiExpression index = container.extractIndexFromGetExpression(getElementExpression); + if (!ExpressionUtils.isReferenceTo(index, countingLoop.getCounter())) return null; + return container.getQualifier(); } @Nullable diff --git a/java/java-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java b/java/java-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java index 05d4e6f115ef..9934a9ba4102 100644 --- a/java/java-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/streamMigration/StreamApiMigrationInspection.java @@ -32,7 +32,6 @@ import com.intellij.psi.controlFlow.*; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.searches.ReferencesSearch; -import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.InheritanceUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; @@ -688,7 +687,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo @Nullable static PsiLocalVariable extractArray(TerminalBlock tb) { - CountingLoop loop = tb.getLastOperation(CountingLoop.class); + CountingLoopSource loop = tb.getLastOperation(CountingLoopSource.class); if(loop == null || loop.myIncluding) return null; PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class); if(assignment == null || !assignment.getOperationTokenType().equals(JavaTokenType.EQ)) return null; @@ -945,7 +944,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo @Contract("null -> null") static StreamSource tryCreate(PsiLoopStatement statement) { if(statement instanceof PsiForStatement) { - return CountingLoop.from((PsiForStatement)statement); + return CountingLoopSource.from((PsiForStatement)statement); } if(statement instanceof PsiForeachStatement) { ArrayStream source = ArrayStream.from((PsiForeachStatement)statement); @@ -1073,15 +1072,15 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } } - static class CountingLoop extends StreamSource { + static class CountingLoopSource extends StreamSource { final PsiExpression myBound; final boolean myIncluding; - private CountingLoop(PsiLoopStatement loop, - PsiVariable counter, - PsiExpression initializer, - PsiExpression bound, - boolean including) { + private CountingLoopSource(PsiLoopStatement loop, + PsiVariable counter, + PsiExpression initializer, + PsiExpression bound, + boolean including) { super(loop, counter, initializer); myBound = bound; myIncluding = including; @@ -1099,8 +1098,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo return className+"."+methodName+"("+myExpression.getText()+", "+myBound.getText()+")"; } - CountingLoop withBound(PsiExpression bound) { - return new CountingLoop(getLoop(), getVariable(), getExpression(), bound, myIncluding); + CountingLoopSource withBound(PsiExpression bound) { + return new CountingLoopSource(getLoop(), getVariable(), getExpression(), bound, myIncluding); } @Override @@ -1115,45 +1114,10 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo } @Nullable - public static CountingLoop from(PsiForStatement forStatement) { - // check that initialization is for(int/long i = ;...;...) - PsiDeclarationStatement initialization = tryCast(forStatement.getInitialization(), PsiDeclarationStatement.class); - if (initialization == null || initialization.getDeclaredElements().length != 1) return null; - PsiLocalVariable counter = tryCast(initialization.getDeclaredElements()[0], PsiLocalVariable.class); - if(counter == null) return null; - if(!counter.getType().equals(PsiType.INT) && !counter.getType().equals(PsiType.LONG)) return null; - - PsiExpression initializer = counter.getInitializer(); - if(initializer == null) return null; - - // check that increment is like for(...;...;i++) - if(!VariableAccessUtils.variableIsIncremented(counter, forStatement.getUpdate())) return null; - - // check that condition is like for(...;i;...;...) + PsiDeclarationStatement initialization = tryCast(forStatement.getInitialization(), PsiDeclarationStatement.class); + if (initialization == null || initialization.getDeclaredElements().length != 1) return null; + PsiLocalVariable counter = tryCast(initialization.getDeclaredElements()[0], PsiLocalVariable.class); + if(counter == null) return null; + if(!counter.getType().equals(PsiType.INT) && !counter.getType().equals(PsiType.LONG)) return null; + + PsiExpression initializer = PsiUtil.skipParenthesizedExprDown(counter.getInitializer()); + if(initializer == null) return null; + + // check that increment is like for(...;...;i++) + if(!VariableAccessUtils.variableIsIncremented(counter, forStatement.getUpdate())) return null; + + // check that condition is like for(...;i