mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 05:10:22 +07:00
IDEA-243019 Unroll loop: get loop size from dataflow
GitOrigin-RevId: 0ba4a16c098414fcb539502446b6cd138922f398
This commit is contained in:
committed by
intellij-monorepo-bot
parent
7bef713cfd
commit
c180e2cec5
@@ -2,12 +2,18 @@
|
||||
package com.intellij.codeInsight.intention.impl;
|
||||
|
||||
import com.intellij.codeInsight.intention.PsiElementBaseIntentionAction;
|
||||
import com.intellij.codeInspection.dataFlow.CommonDataflow;
|
||||
import com.intellij.codeInspection.dataFlow.SpecialField;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfConstantType;
|
||||
import com.intellij.codeInspection.dataFlow.types.DfType;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.search.LocalSearchScope;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiPrecedenceUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.InlineUtil;
|
||||
@@ -104,16 +110,59 @@ public class UnrollLoopAction extends PsiElementBaseIntentionAction {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ExpressionUtils.isSafelyRecomputableExpression(expression)) {
|
||||
PsiType type = expression.getType();
|
||||
if (type instanceof PsiArrayType) {
|
||||
DfType dfType = CommonDataflow.getDfType(expression);
|
||||
Integer arraySize = DfConstantType.getConstantOfType(SpecialField.ARRAY_LENGTH.getFromQualifier(dfType), Integer.class);
|
||||
if (arraySize != null) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(loop.getProject());
|
||||
PsiExpression array = expression;
|
||||
return new AbstractList<PsiExpression>() {
|
||||
@Override
|
||||
public PsiExpression get(int index) {
|
||||
return factory.createExpressionFromText(ParenthesesUtils.getText(array, PsiPrecedenceUtil.POSTFIX_PRECEDENCE)
|
||||
+"["+index+"]", loop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return arraySize;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
if (InheritanceUtil.isInheritor(type, CommonClassNames.JAVA_UTIL_LIST)) {
|
||||
DfType dfType = CommonDataflow.getDfType(expression);
|
||||
Integer listSize = DfConstantType.getConstantOfType(SpecialField.COLLECTION_SIZE.getFromQualifier(dfType), Integer.class);
|
||||
if (listSize != null) {
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(loop.getProject());
|
||||
PsiExpression array = expression;
|
||||
return new AbstractList<PsiExpression>() {
|
||||
@Override
|
||||
public PsiExpression get(int index) {
|
||||
return factory.createExpressionFromText(ParenthesesUtils.getText(array, PsiPrecedenceUtil.METHOD_CALL_PRECEDENCE)
|
||||
+".get("+index+")", loop);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return listSize;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (loop instanceof PsiForStatement) {
|
||||
CountingLoop countingLoop = CountingLoop.from((PsiForStatement)loop);
|
||||
if (countingLoop != null) {
|
||||
boolean descending = countingLoop.isDescending();
|
||||
long multiplier = descending ? -1 : 1;
|
||||
Object from = ExpressionUtils.computeConstantExpression(countingLoop.getInitializer());
|
||||
Object from = CommonDataflow.computeValue(countingLoop.getInitializer());
|
||||
if (!(from instanceof Integer) && !(from instanceof Long)) return Collections.emptyList();
|
||||
long fromValue = ((Number)from).longValue();
|
||||
Object to = ExpressionUtils.computeConstantExpression(countingLoop.getBound());
|
||||
Object to = CommonDataflow.computeValue(countingLoop.getBound());
|
||||
if (!(to instanceof Integer) && !(to instanceof Long)) return Collections.emptyList();
|
||||
long toValue = ((Number)to).longValue();
|
||||
long diff = multiplier * (toValue - fromValue);
|
||||
@@ -200,7 +249,7 @@ public class UnrollLoopAction extends PsiElementBaseIntentionAction {
|
||||
if (loop instanceof PsiForeachStatement) {
|
||||
PsiExpression iteratedValue = ((PsiForeachStatement)loop).getIteratedValue();
|
||||
PsiLocalVariable variable = ExpressionUtils.resolveLocalVariable(iteratedValue);
|
||||
if (variable != null) ct.delete(variable);
|
||||
if (variable != null && PsiTreeUtil.isAncestor(variable, expressions.get(0), true)) ct.delete(variable);
|
||||
}
|
||||
ct.deleteAndRestoreComments(loop);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// "Unroll loop" "true"
|
||||
import java.util.Arrays;
|
||||
|
||||
class X {
|
||||
void test() {
|
||||
int[] array = new int[10];
|
||||
Arrays.setAll(array, i -> i);
|
||||
System.out.println(array[0]);
|
||||
System.out.println(array[1]);
|
||||
System.out.println(array[2]);
|
||||
System.out.println(array[3]);
|
||||
System.out.println(array[4]);
|
||||
System.out.println(array[5]);
|
||||
System.out.println(array[6]);
|
||||
System.out.println(array[7]);
|
||||
System.out.println(array[8]);
|
||||
System.out.println(array[9]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Unroll loop" "true"
|
||||
import java.util.Arrays;
|
||||
|
||||
class X {
|
||||
void testLoop(int size) {
|
||||
if (size == 5) {
|
||||
System.out.println(0);
|
||||
System.out.println(1);
|
||||
System.out.println(2);
|
||||
System.out.println(3);
|
||||
System.out.println(4);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
// "Unroll loop" "true"
|
||||
import java.util.List;
|
||||
|
||||
class X {
|
||||
void testList(List<String> list) {
|
||||
if (list.size() == 2) {
|
||||
System.out.println(list.get(0));
|
||||
System.out.println(list.get(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Unroll loop" "true"
|
||||
import java.util.Arrays;
|
||||
|
||||
class X {
|
||||
void test() {
|
||||
int[] array = new int[10];
|
||||
Arrays.setAll(array, i -> i);
|
||||
<caret>for (int i : array) {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Unroll loop" "true"
|
||||
import java.util.Arrays;
|
||||
|
||||
class X {
|
||||
void testLoop(int size) {
|
||||
if (size == 5) {
|
||||
<caret>for (int i = 0; i < size; i++) {
|
||||
System.out.println(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Unroll loop" "true"
|
||||
import java.util.List;
|
||||
|
||||
class X {
|
||||
void testList(List<String> list) {
|
||||
if (list.size() == 2) {
|
||||
<caret>for (String s : list) {
|
||||
System.out.println(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user