mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 21:55:01 +07:00
IDEA-161706 Migration to Stream API: support primitive types int/long/double
This commit is contained in:
+16
-10
@@ -19,6 +19,7 @@ import com.intellij.codeInsight.FileModificationService;
|
||||
import com.intellij.codeInspection.LambdaCanBeMethodReferenceInspection;
|
||||
import com.intellij.codeInspection.LocalQuickFix;
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
@@ -50,9 +51,8 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
final PsiParameter parameter = foreachStatement.getIterationParameter();
|
||||
StreamApiMigrationInspection.TerminalBlock tb = StreamApiMigrationInspection.TerminalBlock.from(parameter, body);
|
||||
if (!FileModificationService.getInstance().preparePsiElementForWrite(foreachStatement)) return;
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
List<String> replacements = tb.extractOperationReplacements(factory);
|
||||
migrate(project, descriptor, foreachStatement, iteratedValue, body, tb, replacements);
|
||||
List<Operation> operations = tb.extractOperations();
|
||||
migrate(project, descriptor, foreachStatement, iteratedValue, body, tb, operations);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,20 +63,20 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> replacements);
|
||||
@NotNull List<Operation> operations);
|
||||
|
||||
static void replaceWithNumericAddition(@NotNull Project project,
|
||||
PsiForeachStatement foreachStatement,
|
||||
PsiVariable var,
|
||||
StringBuilder builder,
|
||||
String expressionType) {
|
||||
PsiType expressionType) {
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
restoreComments(foreachStatement, foreachStatement.getBody());
|
||||
if (StreamApiMigrationInspection.isDeclarationJustBefore(var, foreachStatement)) {
|
||||
PsiExpression initializer = var.getInitializer();
|
||||
if (ExpressionUtils.isZero(initializer)) {
|
||||
String typeStr = var.getType().getCanonicalText();
|
||||
String replacement = (typeStr.equals(expressionType) ? "" : "(" + typeStr + ") ") + builder;
|
||||
PsiType type = var.getType();
|
||||
String replacement = (type.equals(expressionType) ? "" : "(" + type.getCanonicalText() + ") ") + builder;
|
||||
initializer.replace(elementFactory.createExpressionFromText(replacement, foreachStatement));
|
||||
removeLoop(foreachStatement);
|
||||
simplifyAndFormat(project, var);
|
||||
@@ -102,7 +102,12 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static StringBuilder generateStream(PsiExpression iteratedValue, List<String> intermediateOps) {
|
||||
static StringBuilder generateStream(PsiExpression iteratedValue, List<Operation> intermediateOps) {
|
||||
return generateStream(iteratedValue, intermediateOps, false);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
static StringBuilder generateStream(PsiExpression iteratedValue, List<Operation> intermediateOps, boolean noStreamForEmpty) {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
if (iteratedValueType instanceof PsiArrayType) {
|
||||
@@ -110,11 +115,12 @@ abstract class MigrateToStreamFix implements LocalQuickFix {
|
||||
}
|
||||
else {
|
||||
buffer.append(getIteratedValueText(iteratedValue));
|
||||
if (!intermediateOps.isEmpty()) {
|
||||
if (!(noStreamForEmpty && intermediateOps.isEmpty())) {
|
||||
buffer.append(".stream()");
|
||||
}
|
||||
}
|
||||
intermediateOps.forEach(buffer::append);
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(iteratedValue.getProject());
|
||||
intermediateOps.stream().map(op -> op.createReplacement(factory)).forEach(buffer::append);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
+19
-12
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
@@ -23,6 +24,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.SuggestedNameInfo;
|
||||
import com.intellij.psi.codeStyle.VariableKind;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -42,6 +44,16 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
return "Replace with " + myMethodName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
PsiType getAddedElementType(PsiMethodCallExpression call) {
|
||||
JavaResolveResult resolveResult = call.resolveMethodGenerics();
|
||||
PsiMethod method = call.resolveMethod();
|
||||
if(method == null) return null;
|
||||
PsiParameter[] parameters = method.getParameterList().getParameters();
|
||||
if(parameters.length != 1) return null;
|
||||
return resolveResult.getSubstitutor().substitute(parameters[0].getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
void migrate(@NotNull Project project,
|
||||
@NotNull ProblemDescriptor descriptor,
|
||||
@@ -49,7 +61,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> intermediateOps) {
|
||||
@NotNull List<Operation> operations) {
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
final PsiMethodCallExpression methodCallExpression = tb.getSingleMethodCall();
|
||||
@@ -57,7 +69,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
if (methodCallExpression == null) return;
|
||||
|
||||
restoreComments(foreachStatement, body);
|
||||
if (intermediateOps.isEmpty() && StreamApiMigrationInspection.isAddAllCall(tb)) {
|
||||
if (operations.isEmpty() && StreamApiMigrationInspection.isAddAllCall(tb)) {
|
||||
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
|
||||
final String qualifierText = qualifierExpression != null ? qualifierExpression.getText() : "";
|
||||
final String collectionText =
|
||||
@@ -69,8 +81,10 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
return;
|
||||
}
|
||||
PsiExpression itemToAdd = methodCallExpression.getArgumentList().getExpressions()[0];
|
||||
intermediateOps.add(createMapperFunctionalExpressionText(tb.getVariable(), itemToAdd));
|
||||
final StringBuilder builder = generateStream(iteratedValue, intermediateOps);
|
||||
PsiType addedType = getAddedElementType(methodCallExpression);
|
||||
if (addedType == null) addedType = itemToAdd.getType();
|
||||
operations.add(new StreamApiMigrationInspection.MapOp(itemToAdd, tb.getVariable(), addedType));
|
||||
final StringBuilder builder = generateStream(iteratedValue, operations);
|
||||
|
||||
final PsiExpression qualifierExpression = methodCallExpression.getMethodExpression().getQualifierExpression();
|
||||
final PsiExpression initializer = StreamApiMigrationInspection
|
||||
@@ -88,7 +102,7 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
|
||||
JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(project);
|
||||
SuggestedNameInfo suggestedNameInfo =
|
||||
codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, itemToAdd.getType(), false);
|
||||
codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, null, null, addedType, false);
|
||||
if (suggestedNameInfo.names.length == 0) {
|
||||
suggestedNameInfo = codeStyleManager.suggestVariableName(VariableKind.LOCAL_VARIABLE, "item", null, itemToAdd.getType(), false);
|
||||
}
|
||||
@@ -124,11 +138,4 @@ class ReplaceWithCollectFix extends MigrateToStreamFix {
|
||||
return "toCollection(() -> " + initializer.getText() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
private static String createMapperFunctionalExpressionText(PsiVariable variable, PsiExpression expression) {
|
||||
if (!StreamApiMigrationInspection.isIdentityMapping(variable, expression)) {
|
||||
return new StreamApiMigrationInspection.MapOp(expression, variable).createReplacement(null);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
+4
-3
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -40,14 +41,14 @@ class ReplaceWithCountFix extends MigrateToStreamFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> intermediateOps) {
|
||||
@NotNull List<Operation> operations) {
|
||||
PsiExpression operand = StreamApiMigrationInspection.extractIncrementedLValue(tb.getSingleExpression(PsiExpression.class));
|
||||
if (!(operand instanceof PsiReferenceExpression)) return;
|
||||
PsiElement element = ((PsiReferenceExpression)operand).resolve();
|
||||
if (!(element instanceof PsiLocalVariable)) return;
|
||||
PsiLocalVariable var = (PsiLocalVariable)element;
|
||||
final StringBuilder builder = generateStream(iteratedValue, intermediateOps);
|
||||
final StringBuilder builder = generateStream(iteratedValue, operations);
|
||||
builder.append(".count()");
|
||||
replaceWithNumericAddition(project, foreachStatement, var, builder, "long");
|
||||
replaceWithNumericAddition(project, foreachStatement, var, builder, PsiType.LONG);
|
||||
}
|
||||
}
|
||||
|
||||
+4
-4
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
@@ -40,10 +41,9 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> intermediateOps) {
|
||||
@NotNull List<Operation> operations) {
|
||||
PsiStatement statement = tb.getSingleStatement();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
intermediateOps.add("");
|
||||
if (statement instanceof PsiReturnStatement) {
|
||||
PsiReturnStatement returnStatement = (PsiReturnStatement)statement;
|
||||
PsiExpression value = returnStatement.getReturnValue();
|
||||
@@ -52,7 +52,7 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
if (nextReturnStatement == null) return;
|
||||
PsiExpression orElseExpression = nextReturnStatement.getReturnValue();
|
||||
if (!ExpressionUtils.isSimpleExpression(orElseExpression)) return;
|
||||
StringBuilder builder = generateStream(iteratedValue, intermediateOps).append(".findFirst()");
|
||||
StringBuilder builder = generateStream(iteratedValue, operations).append(".findFirst()");
|
||||
if (!(value instanceof PsiReferenceExpression) || ((PsiReferenceExpression)value).resolve() != tb.getVariable()) {
|
||||
builder.append(".map(").append(tb.getVariable().getName()).append(" -> ").append(value.getText()).append(")");
|
||||
}
|
||||
@@ -77,7 +77,7 @@ class ReplaceWithFindFirstFix extends MigrateToStreamFix {
|
||||
PsiVariable var = (PsiVariable)element;
|
||||
PsiExpression value = assignment.getRExpression();
|
||||
if (value == null) return;
|
||||
StringBuilder builder = generateStream(iteratedValue, intermediateOps).append(".findFirst()");
|
||||
StringBuilder builder = generateStream(iteratedValue, operations).append(".findFirst()");
|
||||
if (!(value instanceof PsiReferenceExpression) || ((PsiReferenceExpression)value).resolve() != tb.getVariable()) {
|
||||
builder.append(".map(").append(tb.getVariable().getName()).append(" -> ").append(value.getText()).append(")");
|
||||
}
|
||||
|
||||
+3
-2
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
@@ -48,12 +49,12 @@ class ReplaceWithForeachCallFix extends MigrateToStreamFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> intermediateOps) {
|
||||
@NotNull List<Operation> operations) {
|
||||
restoreComments(foreachStatement, body);
|
||||
|
||||
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
|
||||
StringBuilder buffer = generateStream(iteratedValue, intermediateOps);
|
||||
StringBuilder buffer = generateStream(iteratedValue, operations, true);
|
||||
PsiElement block = tb.convertToElement(elementFactory);
|
||||
|
||||
buffer.append(".").append(myForEachMethodName).append("(");
|
||||
|
||||
+4
-4
@@ -16,6 +16,7 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
@@ -49,18 +50,17 @@ class ReplaceWithMatchFix extends MigrateToStreamFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> intermediateOps) {
|
||||
@NotNull List<Operation> operations) {
|
||||
PsiReturnStatement returnStatement = (PsiReturnStatement)tb.getSingleStatement();
|
||||
PsiExpression value = returnStatement.getReturnValue();
|
||||
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
|
||||
intermediateOps.add("");
|
||||
restoreComments(foreachStatement, body);
|
||||
if (StreamApiMigrationInspection.isLiteral(value, Boolean.TRUE) || StreamApiMigrationInspection.isLiteral(value, Boolean.FALSE)) {
|
||||
boolean foundResult = (boolean)((PsiLiteralExpression)value).getValue();
|
||||
PsiReturnStatement nextReturnStatement = StreamApiMigrationInspection.getNextReturnStatement(foreachStatement);
|
||||
if (nextReturnStatement != null && StreamApiMigrationInspection.isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) {
|
||||
String methodName = foundResult ? "anyMatch" : "noneMatch";
|
||||
String streamText = generateStream(iteratedValue, intermediateOps).toString();
|
||||
String streamText = generateStream(iteratedValue, operations).toString();
|
||||
streamText = addTerminalOperation(streamText, methodName, foreachStatement, tb);
|
||||
boolean siblings = nextReturnStatement.getParent() == foreachStatement.getParent();
|
||||
PsiElement result =
|
||||
@@ -73,7 +73,7 @@ class ReplaceWithMatchFix extends MigrateToStreamFix {
|
||||
}
|
||||
}
|
||||
if (!StreamApiMigrationInspection.isVariableReferenced(tb.getVariable(), value)) {
|
||||
String streamText = generateStream(iteratedValue, intermediateOps).toString();
|
||||
String streamText = generateStream(iteratedValue, operations).toString();
|
||||
streamText = addTerminalOperation(streamText, "anyMatch", foreachStatement, tb);
|
||||
String replacement = "if(" + streamText + "){" + returnStatement.getText() + "}";
|
||||
PsiElement result = foreachStatement.replace(elementFactory.createStatementFromText(replacement, foreachStatement));
|
||||
|
||||
+8
-17
@@ -16,12 +16,12 @@
|
||||
package com.intellij.codeInspection.streamMigration;
|
||||
|
||||
import com.intellij.codeInspection.ProblemDescriptor;
|
||||
import com.intellij.codeInspection.streamMigration.StreamApiMigrationInspection.Operation;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
@@ -41,7 +41,7 @@ class ReplaceWithSumFix extends MigrateToStreamFix {
|
||||
@NotNull PsiExpression iteratedValue,
|
||||
@NotNull PsiStatement body,
|
||||
@NotNull StreamApiMigrationInspection.TerminalBlock tb,
|
||||
@NotNull List<String> intermediateOps) {
|
||||
@NotNull List<Operation> operations) {
|
||||
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
|
||||
if (assignment == null) return;
|
||||
PsiVariable var = StreamApiMigrationInspection.extractAccumulator(assignment);
|
||||
@@ -50,22 +50,13 @@ class ReplaceWithSumFix extends MigrateToStreamFix {
|
||||
PsiExpression addend = StreamApiMigrationInspection.extractAddend(assignment);
|
||||
if (addend == null) return;
|
||||
PsiType type = var.getType();
|
||||
if (!(type instanceof PsiPrimitiveType)) return;
|
||||
PsiPrimitiveType primitiveType = (PsiPrimitiveType)type;
|
||||
if (primitiveType.equalsToText("float")) return;
|
||||
String typeName;
|
||||
if (primitiveType.equalsToText("double")) {
|
||||
typeName = "Double";
|
||||
if (!(type instanceof PsiPrimitiveType) || type.equals(PsiType.FLOAT)) return;
|
||||
if (!type.equals(PsiType.DOUBLE) && !type.equals(PsiType.LONG)) {
|
||||
type = PsiType.INT;
|
||||
}
|
||||
else if (primitiveType.equalsToText("long")) {
|
||||
typeName = "Long";
|
||||
}
|
||||
else {
|
||||
typeName = "Int";
|
||||
}
|
||||
intermediateOps.add(".mapTo" + typeName + "(" + StreamApiMigrationInspection.createLambda(tb.getVariable(), addend) + ")");
|
||||
final StringBuilder builder = generateStream(iteratedValue, intermediateOps);
|
||||
operations.add(new StreamApiMigrationInspection.MapOp(addend, tb.getVariable(), type));
|
||||
final StringBuilder builder = generateStream(iteratedValue, operations);
|
||||
builder.append(".sum()");
|
||||
replaceWithNumericAddition(project, foreachStatement, var, builder, typeName.toLowerCase(Locale.ENGLISH));
|
||||
replaceWithNumericAddition(project, foreachStatement, var, builder, type);
|
||||
}
|
||||
}
|
||||
|
||||
+68
-24
@@ -111,8 +111,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
PsiClass collectionClass = null;
|
||||
final boolean isArray;
|
||||
if(iteratedValueType instanceof PsiArrayType) {
|
||||
// Do not handle primitive types now
|
||||
if(((PsiArrayType)iteratedValueType).getComponentType() instanceof PsiPrimitiveType) return;
|
||||
if(!isSupported(((PsiArrayType)iteratedValueType).getComponentType())) return;
|
||||
isArray = true;
|
||||
} else {
|
||||
collectionClass = JavaPsiFacade.getInstance(body.getProject()).findClass(CommonClassNames.JAVA_UTIL_COLLECTION, statement.getResolveScope());
|
||||
@@ -199,6 +198,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
if(!(var instanceof PsiVariable) || !nonFinalVariables.contains(var)) return;
|
||||
PsiExpression rValue = assignment.getRExpression();
|
||||
if(rValue == null || isVariableReferenced((PsiVariable)var, rValue)) return;
|
||||
if(tb.getVariable() instanceof PsiPrimitiveType && !isIdentityMapping(tb.getVariable(), rValue)) return;
|
||||
registerProblem(holder, isOnTheFly, statement, "findFirst", new ReplaceWithFindFirstFix());
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
if (!isVariableReferenced(tb.getVariable(), value)) {
|
||||
registerProblem(holder, isOnTheFly, statement, "anyMatch", new ReplaceWithMatchFix("anyMatch"));
|
||||
}
|
||||
if(nextReturnStatement != null && ExpressionUtils.isSimpleExpression(nextReturnStatement.getReturnValue())) {
|
||||
if(nextReturnStatement != null && ExpressionUtils.isSimpleExpression(nextReturnStatement.getReturnValue())
|
||||
&& (!(tb.getVariable().getType() instanceof PsiPrimitiveType) || isIdentityMapping(tb.getVariable(), value))) {
|
||||
registerProblem(holder, isOnTheFly, statement, "findFirst", new ReplaceWithFindFirstFix());
|
||||
}
|
||||
}
|
||||
@@ -541,6 +542,13 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return method != null && isThrowsCompatible(method);
|
||||
}
|
||||
|
||||
static boolean isSupported(PsiType type) {
|
||||
if(type instanceof PsiPrimitiveType) {
|
||||
return type.equals(PsiType.INT) || type.equals(PsiType.LONG) || type.equals(PsiType.DOUBLE);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isThrowsCompatible(PsiMethod method) {
|
||||
return ContainerUtil.find(method.getThrowsList().getReferencedTypes(), type -> !ExceptionUtil.isUncheckedException(type)) != null;
|
||||
}
|
||||
@@ -633,13 +641,48 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
|
||||
static class MapOp extends Operation {
|
||||
MapOp(PsiExpression expression, PsiVariable variable) {
|
||||
private final @Nullable PsiType myType;
|
||||
|
||||
MapOp(PsiExpression expression, PsiVariable variable, @Nullable PsiType targetType) {
|
||||
super(expression, variable);
|
||||
myType = targetType;
|
||||
}
|
||||
|
||||
MapOp(PsiExpression expression, PsiVariable variable) {
|
||||
this(expression, variable, expression.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createReplacement(PsiElementFactory factory) {
|
||||
return ".map(" + createLambda(myVariable, myExpression) + ")";
|
||||
if (isIdentityMapping(myVariable, myExpression)) {
|
||||
if (!(myType instanceof PsiPrimitiveType)) {
|
||||
return myVariable.getType() instanceof PsiPrimitiveType ? ".boxed()" : "";
|
||||
}
|
||||
if(myType.equals(myVariable.getType())) {
|
||||
return "";
|
||||
}
|
||||
if (PsiType.LONG.equals(myType) && PsiType.INT.equals(myVariable.getType())) {
|
||||
return ".asLongStream()";
|
||||
}
|
||||
if (PsiType.DOUBLE.equals(myType) && (PsiType.LONG.equals(myVariable.getType()) || PsiType.INT.equals(myVariable.getType()))) {
|
||||
return ".asDoubleStream()";
|
||||
}
|
||||
}
|
||||
String operationName = "map";
|
||||
if(myType instanceof PsiPrimitiveType) {
|
||||
if(!myType.equals(myVariable.getType())) {
|
||||
if(PsiType.INT.equals(myType)) {
|
||||
operationName = "mapToInt";
|
||||
} else if(PsiType.LONG.equals(myType)) {
|
||||
operationName = "mapToLong";
|
||||
} else if(PsiType.DOUBLE.equals(myType)) {
|
||||
operationName = "mapToDouble";
|
||||
}
|
||||
}
|
||||
} else if(myVariable.getType() instanceof PsiPrimitiveType) {
|
||||
operationName = "mapToObj";
|
||||
}
|
||||
return "."+operationName+"(" + createLambda(myVariable, myExpression) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -663,7 +706,21 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
@Override
|
||||
public String createReplacement(PsiElementFactory factory) {
|
||||
PsiExpression replacement = factory.createExpressionFromText("java.util.Arrays.stream("+myExpression.getText() + ")", myExpression);
|
||||
return ".flatMap(" + createLambda(myVariable, replacement) + ")";
|
||||
String operation = "flatMap";
|
||||
PsiType type = myExpression.getType();
|
||||
if(type instanceof PsiArrayType) {
|
||||
PsiType componentType = ((PsiArrayType)type).getComponentType();
|
||||
if(componentType instanceof PsiPrimitiveType) {
|
||||
if(componentType.equals(PsiType.INT)) {
|
||||
operation = "flatMapToInt";
|
||||
} else if(componentType.equals(PsiType.LONG)) {
|
||||
operation = "flatMapToLong";
|
||||
} else if(componentType.equals(PsiType.DOUBLE)) {
|
||||
operation = "flatMapToDouble";
|
||||
}
|
||||
}
|
||||
}
|
||||
return "."+operation+"(" + createLambda(myVariable, replacement) + ")";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -740,6 +797,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
}
|
||||
// extract flatMap
|
||||
if(getSingleStatement() instanceof PsiForeachStatement) {
|
||||
// flatMapping of primitive variable is not supported yet
|
||||
if(myVariable.getType() instanceof PsiPrimitiveType) return null;
|
||||
PsiForeachStatement foreachStatement = (PsiForeachStatement)getSingleStatement();
|
||||
final PsiExpression iteratedValue = foreachStatement.getIteratedValue();
|
||||
final PsiStatement body = foreachStatement.getBody();
|
||||
@@ -747,9 +806,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
final PsiType iteratedValueType = iteratedValue.getType();
|
||||
Operation op = null;
|
||||
if(iteratedValueType instanceof PsiArrayType) {
|
||||
// do not handle flatMapToPrimitive
|
||||
if (((PsiArrayType)iteratedValueType).getComponentType() instanceof PsiPrimitiveType)
|
||||
return null;
|
||||
if (!isSupported(((PsiArrayType)iteratedValueType).getComponentType())) return null;
|
||||
op = new ArrayFlatMapOp(iteratedValue, myVariable);
|
||||
} else {
|
||||
final PsiClass iteratorClass = PsiUtil.resolveClassInClassTypeOnly(iteratedValueType);
|
||||
@@ -777,14 +834,13 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
PsiElement element = elements[0];
|
||||
if(element instanceof PsiLocalVariable) {
|
||||
PsiLocalVariable declaredVar = (PsiLocalVariable)element;
|
||||
// do not handle mapToPrimitive
|
||||
if(!(declaredVar.getType() instanceof PsiPrimitiveType)) {
|
||||
if(isSupported(declaredVar.getType())) {
|
||||
PsiExpression initializer = declaredVar.getInitializer();
|
||||
PsiStatement[] leftOver = Arrays.copyOfRange(myStatements, 1, myStatements.length);
|
||||
if (initializer != null &&
|
||||
ReferencesSearch.search(myVariable, new LocalSearchScope(leftOver))
|
||||
.findFirst() == null) {
|
||||
MapOp op = new MapOp(initializer, myVariable);
|
||||
MapOp op = new MapOp(initializer, myVariable, declaredVar.getType());
|
||||
myVariable = declaredVar;
|
||||
myStatements = leftOver;
|
||||
flatten();
|
||||
@@ -845,18 +901,6 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
|
||||
return new TerminalBlock(variable, new PsiStatement[] {statement});
|
||||
}
|
||||
|
||||
@NotNull
|
||||
List<String> extractOperationReplacements(PsiElementFactory factory) {
|
||||
List<String> intermediateOps = new ArrayList<>();
|
||||
while(true) {
|
||||
Operation operation = extractOperation();
|
||||
if(operation == null)
|
||||
break;
|
||||
intermediateOps.add(operation.createReplacement(factory));
|
||||
}
|
||||
return intermediateOps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this TerminalBlock to PsiElement (either PsiStatement or PsiCodeBlock)
|
||||
*
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public boolean testPrimitiveMap(List<String> data) {
|
||||
return data.stream().filter(str -> str.startsWith("xyz")).mapToInt(String::length).anyMatch(len -> len > 10);
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
List<Integer> list = data.stream().filter(str -> str.startsWith("xyz")).mapToInt(String::length).filter(len -> len > 10).boxed().collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
List<String> list = data.stream().filter(str -> str.startsWith("xyz")).mapToInt(String::length).filter(len -> len > 10).mapToObj(String::valueOf).collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// "Replace with count()" "true"
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class Main {
|
||||
public int testPrimitiveArray(int[] data) {
|
||||
int count = (int) Arrays.stream(data).mapToLong(val -> val * val).filter(square -> square > 100).count();
|
||||
return count;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public int testPrimitiveMap(List<String> data) {
|
||||
return data.stream().filter(str -> str.startsWith("xyz")).mapToInt(String::length).filter(len -> len > 10).findFirst().orElse(0);
|
||||
}
|
||||
}
|
||||
+4
-8
@@ -1,17 +1,13 @@
|
||||
// "Replace with forEach" "true"
|
||||
// "Replace with collect" "true"
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class Main {
|
||||
public List<Integer> test(int[][] arr) {
|
||||
List<Integer> result = new ArrayList<>();
|
||||
Arrays.stream(arr).filter(Objects::nonNull).forEach(subArr -> {
|
||||
for (int str : subArr) {
|
||||
result.add(str);
|
||||
}
|
||||
});
|
||||
return result;
|
||||
List<Integer> result = Arrays.stream(arr).filter(Objects::nonNull).flatMapToInt(Arrays::stream).boxed().collect(Collectors.toList());
|
||||
return result;
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -6,9 +6,9 @@ import java.util.Objects;
|
||||
class Sample {
|
||||
List<String> foo = new ArrayList<>();
|
||||
String foo(){
|
||||
foo.stream().filter(Objects::isNull).forEach(s -> {
|
||||
int i = 0;
|
||||
});
|
||||
foo.stream().filter(Objects::isNull).forEach(s -> bar());
|
||||
return null;
|
||||
}
|
||||
|
||||
bar() {}
|
||||
}
|
||||
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace with sum()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
int sum = data.stream().filter(str -> str.startsWith("xyz")).mapToInt(String::length).filter(len -> len > 10).map(len -> len * 2).sum();
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace with sum()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
long sum = data.stream().filter(str -> str.startsWith("xyz")).mapToInt(String::length).filter(len -> len > 10).asLongStream().sum();
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace with anyMatch()" "false"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public boolean testPrimitiveMap(List<String> data) {
|
||||
for(String str : d<caret>ata) {
|
||||
if(str.startsWith("xyz")) {
|
||||
float len = str.length();
|
||||
if(len > 10) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace with anyMatch()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public boolean testPrimitiveMap(List<String> data) {
|
||||
for(String str : d<caret>ata) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
List<Integer> list = new ArrayList<>();
|
||||
for(String str : d<caret>ata) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
list.add(len);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace with collect" "true"
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
List<String> list = new ArrayList<>();
|
||||
for(String str : d<caret>ata) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
list.add(String.valueOf(len));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Replace with count()" "true"
|
||||
|
||||
public class Main {
|
||||
public int testPrimitiveArray(int[] data) {
|
||||
int count = 0;
|
||||
for(int val : dat<caret>a) {
|
||||
long square = val*val;
|
||||
if(square > 100) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
// "Replace with count()" "false"
|
||||
|
||||
public class Main {
|
||||
public int testPrimitiveArray(short[] data) {
|
||||
int count = 0;
|
||||
for(int val : dat<caret>a) {
|
||||
long square = val*val;
|
||||
if(square > 100) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace with findFirst()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public int testPrimitiveMap(List<String> data) {
|
||||
for(String str : dat<caret>a) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
return len;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// "Replace with findFirst()" "false"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// Not supported as OptionalInt lacks mapping method
|
||||
public class Main {
|
||||
public int testPrimitiveMap(List<String> data) {
|
||||
for(String str : dat<caret>a) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
return len * 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
// "Replace with forEach" "true"
|
||||
// "Replace with collect" "true"
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public List<Integer> test(int[][] arr) {
|
||||
|
||||
+3
-1
@@ -6,8 +6,10 @@ class Sample {
|
||||
List<String> foo = new ArrayList<>();
|
||||
String foo(){
|
||||
for (String s : fo<caret>o) {
|
||||
if (s == null) int i = 0;
|
||||
if (s == null) bar();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bar() {}
|
||||
}
|
||||
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace with sum()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
int sum = 0;
|
||||
for(String str : dat<caret>a) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
sum += len*2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace with sum()" "true"
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Main {
|
||||
public void testPrimitiveMap(List<String> data) {
|
||||
long sum = 0;
|
||||
for(String str : da<caret>ta) {
|
||||
if(str.startsWith("xyz")) {
|
||||
int len = str.length();
|
||||
if(len > 10) {
|
||||
sum += len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user