mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-166499 Stream API migration: support array filling in a loop
This commit is contained in:
+37
-1
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInsight.ExceptionUtil;
|
||||
import com.intellij.codeInsight.PsiEquivalenceUtil;
|
||||
import com.intellij.codeInsight.daemon.GroupNames;
|
||||
import com.intellij.codeInsight.daemon.impl.analysis.HighlightControlFlowUtil;
|
||||
import com.intellij.codeInspection.BaseJavaBatchLocalInspectionTool;
|
||||
@@ -566,6 +567,9 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
if (tb.getCountExpression() != null || tb.isEmpty()) return null;
|
||||
if (nonFinalVariables.isEmpty() && extractArray(tb) != null) {
|
||||
return new ToArrayMigration();
|
||||
}
|
||||
if (getAccumulatedVariable(tb, nonFinalVariables) != null) {
|
||||
return new SumMigration();
|
||||
}
|
||||
@@ -691,6 +695,34 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
static PsiLocalVariable extractArray(TerminalBlock tb) {
|
||||
CountingLoop loop = tb.getLastOperation(CountingLoop.class);
|
||||
if(loop == null || loop.myIncluding) return null;
|
||||
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
|
||||
if(assignment == null || !assignment.getOperationTokenType().equals(JavaTokenType.EQ)) return null;
|
||||
PsiArrayAccessExpression arrayAccess = tryCast(assignment.getLExpression(), PsiArrayAccessExpression.class);
|
||||
if(arrayAccess == null) return null;
|
||||
if(!ExpressionUtils.isReferenceTo(arrayAccess.getIndexExpression(), loop.getVariable())) return null;
|
||||
PsiReferenceExpression arrayReference = tryCast(arrayAccess.getArrayExpression(), PsiReferenceExpression.class);
|
||||
if(arrayReference == null) return null;
|
||||
PsiLocalVariable arrayVariable = tryCast(arrayReference.resolve(), PsiLocalVariable.class);
|
||||
if(arrayVariable == null || getInitializerUsageStatus(arrayVariable, tb.getMainLoop()) == UNKNOWN) return null;
|
||||
PsiNewExpression initializer = tryCast(arrayVariable.getInitializer(), PsiNewExpression.class);
|
||||
if(initializer == null) return null;
|
||||
PsiArrayType arrayType = tryCast(initializer.getType(), PsiArrayType.class);
|
||||
if(arrayType == null || !isSupported(arrayType.getComponentType())) return null;
|
||||
PsiExpression dimension = ArrayUtil.getFirstElement(initializer.getArrayDimensions());
|
||||
if(dimension == null) return null;
|
||||
PsiExpression bound = loop.myBound;
|
||||
if (!PsiEquivalenceUtil.areElementsEquivalent(dimension, bound) &&
|
||||
!ExpressionUtils.isReferenceTo(ExpressionUtils.getArrayFromLengthExpression(bound), arrayVariable)) {
|
||||
return null;
|
||||
}
|
||||
if(VariableAccessUtils.variableIsUsed(arrayVariable, assignment.getRExpression())) return null;
|
||||
return arrayVariable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Intermediate stream operation representation
|
||||
*/
|
||||
@@ -1085,7 +1117,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
final boolean myIncluding;
|
||||
|
||||
private CountingLoop(PsiLoopStatement loop,
|
||||
PsiLocalVariable counter,
|
||||
PsiVariable counter,
|
||||
PsiExpression initializer,
|
||||
PsiExpression bound,
|
||||
boolean including) {
|
||||
@@ -1106,6 +1138,10 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return className+"."+methodName+"("+myExpression.getText()+", "+myBound.getText()+")";
|
||||
}
|
||||
|
||||
CountingLoop withBound(PsiExpression bound) {
|
||||
return new CountingLoop(getLoop(), getVariable(), getExpression(), bound, myIncluding);
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isWriteAllowed(PsiVariable variable, PsiExpression reference) {
|
||||
if(variable == myVariable) {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.CountingLoop;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.InitializerUsageStatus;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.MapOp;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
*/
|
||||
public class ToArrayMigration extends BaseStreamApiMigration {
|
||||
protected ToArrayMigration() {
|
||||
super("toArray");
|
||||
}
|
||||
|
||||
@Override
|
||||
PsiElement migrate(@NotNull Project project, @NotNull PsiStatement body, @NotNull TerminalBlock tb) {
|
||||
PsiLocalVariable arrayVariable = StreamApiMigrationInspection.extractArray(tb);
|
||||
if(arrayVariable == null) return null;
|
||||
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
|
||||
if(assignment == null) return null;
|
||||
PsiExpression rValue = assignment.getRExpression();
|
||||
if(rValue == null) return null;
|
||||
PsiNewExpression initializer = tryCast(arrayVariable.getInitializer(), PsiNewExpression.class);
|
||||
if(initializer == null) return null;
|
||||
PsiExpression dimension = ArrayUtil.getFirstElement(initializer.getArrayDimensions());
|
||||
if(dimension == null) return null;
|
||||
CountingLoop loop = tb.getLastOperation(CountingLoop.class);
|
||||
if(loop == null) return null;
|
||||
PsiArrayType arrayType = tryCast(initializer.getType(), PsiArrayType.class);
|
||||
if(arrayType == null) return null;
|
||||
InitializerUsageStatus status = StreamApiMigrationInspection.getInitializerUsageStatus(arrayVariable, tb.getMainLoop());
|
||||
if(status == InitializerUsageStatus.UNKNOWN) return null;
|
||||
PsiType componentType = arrayType.getComponentType();
|
||||
String supplier;
|
||||
if(componentType instanceof PsiPrimitiveType || componentType.equalsToText(CommonClassNames.JAVA_LANG_OBJECT)) {
|
||||
supplier = "";
|
||||
} else {
|
||||
supplier = arrayType.getCanonicalText()+"::new";
|
||||
}
|
||||
MapOp mapping = new MapOp(rValue, tb.getVariable(), assignment.getType());
|
||||
String replacementText = loop.withBound(dimension).createReplacement() + mapping.createReplacement() + ".toArray(" + supplier + ")";
|
||||
return replaceInitializer(tb.getMainLoop(), arrayVariable, initializer, replacementText, status);
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Test {
|
||||
public void test(List<Integer> ints) {
|
||||
long[] arr = IntStream.range(0, ints.size()).mapToLong(ints::get).toArray();
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Test {
|
||||
public void test(int bound) {
|
||||
Object[] arr = IntStream.range(0, bound).boxed().toArray(Integer[]::new);
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Test {
|
||||
public void test(int bound) {
|
||||
Integer[][] arr = IntStream.range(0, bound).mapToObj(i -> new Integer[]{i}).toArray(Integer[][]::new);
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.IntStream;
|
||||
|
||||
public class Test {
|
||||
public void test(List<List<String>> list) {
|
||||
List<?>[] arr = IntStream.range(0, list.size()).mapToObj(list::get).toArray(List[]::new);
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Test {
|
||||
public void test(List<Integer> ints) {
|
||||
long[] arr = new long[ints.size()];
|
||||
for(int <caret>i = 0; i < ints.size(); i++) {
|
||||
arr[i] = ints.get(i);
|
||||
}
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Test {
|
||||
public void test(int bound) {
|
||||
Object[] arr = new Integer[bound];
|
||||
for(int <caret>i = 0; i < bound; i++) {
|
||||
arr[i] = i;
|
||||
}
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Test {
|
||||
public void test(int bound) {
|
||||
Integer[][] arr = new Integer[bound][];
|
||||
for(int <caret>i = 0; i < arr.length; i++) {
|
||||
arr[i] = new Integer[] {i};
|
||||
}
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Replace with toArray" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class Test {
|
||||
public void test(List<List<String>> list) {
|
||||
List<?>[] arr = new List[list.size()];
|
||||
for(i<caret>nt i = 0; i < arr.length; i++) {
|
||||
arr[i] = list.get(i);
|
||||
}
|
||||
System.out.println(Arrays.toString(arr));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user