add support for binary operation reduction in stream migration

This commit is contained in:
Roman Ivanov
2017-07-20 17:15:07 +07:00
parent 5ce1ab82c5
commit dd4ba58889
39 changed files with 762 additions and 121 deletions
@@ -21,7 +21,6 @@ import com.intellij.psi.controlFlow.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.ControlFlowUtils.InitializerUsageStatus;
import com.siyeh.ig.psiutils.ExpressionUtils;
import org.jetbrains.annotations.NotNull;
/**
@@ -46,22 +45,25 @@ abstract class BaseStreamApiMigration {
return myShouldWarn;
}
static PsiElement replaceWithNumericAddition(PsiLoopStatement loopStatement,
PsiVariable var,
String streamText,
PsiType expressionType) {
static PsiElement replaceWithOperation(PsiLoopStatement loopStatement,
PsiVariable var,
String streamText,
PsiType expressionType,
OperationReductionMigration.ReductionOperation reductionOperation) {
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(loopStatement.getProject());
restoreComments(loopStatement, loopStatement.getBody());
InitializerUsageStatus status = ControlFlowUtils.getInitializerUsageStatus(var, loopStatement);
if (status != ControlFlowUtils.InitializerUsageStatus.UNKNOWN) {
if (status != InitializerUsageStatus.UNKNOWN) {
PsiExpression initializer = var.getInitializer();
if (ExpressionUtils.isZero(initializer)) {
if (initializer != null && reductionOperation.getInitializerExpressionRestriction().test(initializer)) {
PsiType type = var.getType();
String replacement = (type.equals(expressionType) ? "" : "(" + type.getCanonicalText() + ") ") + streamText;
String replacement = (type.isAssignableFrom(expressionType) ? "" : "(" + type.getCanonicalText() + ") ") + streamText;
return replaceInitializer(loopStatement, var, initializer, replacement, status);
}
}
return loopStatement.replace(elementFactory.createStatementFromText(var.getName() + "+=" + streamText + ";", loopStatement));
return loopStatement
.replace(elementFactory.createStatementFromText(var.getName() + reductionOperation.getOperation() + "=" + streamText + ";",
loopStatement));
}
static PsiElement replaceInitializer(PsiLoopStatement loopStatement,
@@ -71,12 +73,13 @@ abstract class BaseStreamApiMigration {
InitializerUsageStatus status) {
Project project = loopStatement.getProject();
PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(project);
if(status == ControlFlowUtils.InitializerUsageStatus.DECLARED_JUST_BEFORE) {
if (status == ControlFlowUtils.InitializerUsageStatus.DECLARED_JUST_BEFORE) {
initializer.replace(elementFactory.createExpressionFromText(replacement, loopStatement));
removeLoop(loopStatement);
return var;
} else {
if(status == ControlFlowUtils.InitializerUsageStatus.AT_WANTED_PLACE_ONLY) {
}
else {
if (status == ControlFlowUtils.InitializerUsageStatus.AT_WANTED_PLACE_ONLY) {
initializer.delete();
}
return
@@ -19,6 +19,8 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInspection.streamMigration.OperationReductionMigration.SUM_OPERATION;
/**
* @author Tagir Valeev
*/
@@ -39,6 +41,6 @@ class CountMigration extends BaseStreamApiMigration {
PsiElement element = ((PsiReferenceExpression)operand).resolve();
if (!(element instanceof PsiLocalVariable)) return null;
PsiLocalVariable var = (PsiLocalVariable)element;
return replaceWithNumericAddition(tb.getMainLoop(), var, tb.generate() + ".count()", PsiType.LONG);
return replaceWithOperation(tb.getMainLoop(), var, tb.generate() + ".count()", PsiType.LONG, SUM_OPERATION);
}
}
@@ -0,0 +1,191 @@
/*
* 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.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.TypeConversionUtil;
import com.siyeh.ig.psiutils.ExpressionUtils;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import java.util.Locale;
import java.util.function.Predicate;
/**
* Created by Roman Ivanov.
*/
public class OperationReductionMigration extends BaseStreamApiMigration {
private final ReductionOperation myReductionOperation;
protected OperationReductionMigration(boolean shouldWarn,
ReductionOperation context) {
super(shouldWarn, "reduce()");
myReductionOperation = context;
}
@Override
PsiElement migrate(@NotNull Project project, @NotNull PsiStatement body, @NotNull TerminalBlock tb) {
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
if (assignment == null) return null;
PsiVariable var = StreamApiMigrationInspection.extractAccumulator(assignment, myReductionOperation.getCompoundAssignmentOp());
if (var == null) return null;
PsiExpression operand = StreamApiMigrationInspection.extractOperand(assignment, myReductionOperation.getCompoundAssignmentOp());
if (operand == null) return null;
PsiType type = var.getType();
PsiType operandType = operand.getType();
if (operandType != null && !TypeConversionUtil.isAssignable(type, operandType)) {
operand = JavaPsiFacade.getElementFactory(project).createExpressionFromText(
"(" + type.getCanonicalText() + ")" + ParenthesesUtils.getText(operand, ParenthesesUtils.MULTIPLICATIVE_PRECEDENCE), operand);
}
JavaCodeStyleManager javaStyle = JavaCodeStyleManager.getInstance(project);
String leftOperand = javaStyle.suggestUniqueVariableName("a", body, true);
String rightOperand = javaStyle.suggestUniqueVariableName("b", body, true);
if(type.equals(PsiType.BOOLEAN)) {
type = PsiType.BOOLEAN.getBoxedType(body); // hack to avoid .map(b -> b) when boxing needed
}
PsiExpression initializer = var.getInitializer();
String identity = initializer != null && myReductionOperation.getInitializerExpressionRestriction().test(initializer)
? initializer.getText()
: myReductionOperation.myIdentity;
String stream = tb.add(new StreamApiMigrationInspection.MapOp(operand, tb.getVariable(), type)).generate()
+ String.format(Locale.ENGLISH, ".reduce(%s, (%s, %s) -> %s %s %s)",
identity, leftOperand, rightOperand, leftOperand,
myReductionOperation.getOperation(), rightOperand);
return replaceWithOperation(tb.getMainLoop(), var, stream, type, myReductionOperation);
}
static class ReductionOperation {
private final IElementType myCompoundAssignmentOp;
private final Predicate<PsiExpression> myInitializerReplaceCondition;
private final Predicate<PsiVariable> myAccumulatorRestriction;
private final String myIdentity;
private final String myOperation;
public ReductionOperation(IElementType compoundAssignmentOp,
Predicate<PsiExpression> initializerReplaceCondition,
Predicate<PsiVariable> accumulatorRestriction,
String identity,
String operation) {
myCompoundAssignmentOp = compoundAssignmentOp;
myInitializerReplaceCondition = initializerReplaceCondition;
myAccumulatorRestriction = accumulatorRestriction;
myIdentity = identity;
myOperation = operation;
}
public IElementType getCompoundAssignmentOp() {
return myCompoundAssignmentOp;
}
public Predicate<PsiExpression> getInitializerExpressionRestriction() {
return myInitializerReplaceCondition;
}
public String getIdentity() {
return myIdentity;
}
public String getOperation() {
return myOperation;
}
public Predicate<PsiVariable> getAccumulatorRestriction() {
return myAccumulatorRestriction;
}
}
static final ReductionOperation SUM_OPERATION = new ReductionOperation(
JavaTokenType.PLUSEQ,
ExpressionUtils::isZero,
OperationReductionMigration::arithmeticTypeRestriction,
"0",
"+"
);
static final ReductionOperation[] OPERATIONS = {
new ReductionOperation(
JavaTokenType.ASTERISKEQ,
ExpressionUtils::isOne,
OperationReductionMigration::arithmeticTypeRestriction,
"1",
"*"
),
new ReductionOperation(
JavaTokenType.ANDEQ,
expression -> Boolean.TRUE.equals(ExpressionUtils.computeConstantExpression(expression)),
OperationReductionMigration::booleanTypeRestriction,
"true",
"&&"
),
new ReductionOperation(
JavaTokenType.OREQ,
expression -> Boolean.FALSE.equals(ExpressionUtils.computeConstantExpression(expression)),
OperationReductionMigration::booleanTypeRestriction,
"false",
"||"
),
new ReductionOperation(
JavaTokenType.OREQ,
ExpressionUtils::isZero,
OperationReductionMigration::arithmeticTypeRestriction,
"0",
"|"
),
new ReductionOperation(
JavaTokenType.ANDEQ,
OperationReductionMigration::isMinusOne,
OperationReductionMigration::bitwiseTypeRestriction,
"-1",
"&"
),
new ReductionOperation(
JavaTokenType.XOREQ,
ExpressionUtils::isZero,
OperationReductionMigration::bitwiseTypeRestriction,
"0",
"^"
)
};
private static boolean isMinusOne(PsiExpression expression) {
Object constant = ExpressionUtils.computeConstantExpression(expression);
if(constant == null) {
return false;
}
return (constant instanceof Integer || constant instanceof Long) && ((Number)constant).longValue() == -1;
}
static boolean bitwiseTypeRestriction(@NotNull PsiVariable variable) {
return variable.getType() instanceof PsiPrimitiveType
&& (variable.getType().equals(PsiType.INT) || variable.getType().equals(PsiType.LONG));
}
static boolean arithmeticTypeRestriction(@NotNull PsiVariable variable) {
return variable.getType() instanceof PsiPrimitiveType && !variable.getType().equals(PsiType.FLOAT);
}
private static boolean booleanTypeRestriction(@NotNull PsiVariable variable) {
return variable.getType().equalsToText("boolean") || variable.getType().equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN);
}
}
@@ -34,6 +34,7 @@ import com.intellij.psi.*;
import com.intellij.psi.controlFlow.*;
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;
@@ -51,6 +52,7 @@ import java.util.Collection;
import java.util.List;
import java.util.Objects;
import static com.intellij.codeInspection.streamMigration.OperationReductionMigration.SUM_OPERATION;
import static com.intellij.util.ObjectUtils.tryCast;
import static com.siyeh.ig.psiutils.ControlFlowUtils.InitializerUsageStatus.UNKNOWN;
@@ -109,22 +111,22 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Nullable
static PsiReturnStatement getNextReturnStatement(PsiStatement statement) {
PsiElement nextStatement = PsiTreeUtil.skipWhitespacesAndCommentsForward(statement);
if(nextStatement instanceof PsiReturnStatement) return (PsiReturnStatement)nextStatement;
if (nextStatement instanceof PsiReturnStatement) return (PsiReturnStatement)nextStatement;
PsiElement parent = statement.getParent();
if(parent instanceof PsiCodeBlock) {
if (parent instanceof PsiCodeBlock) {
PsiStatement[] statements = ((PsiCodeBlock)parent).getStatements();
if(statements.length == 0 || statements[statements.length-1] != statement) return null;
if (statements.length == 0 || statements[statements.length - 1] != statement) return null;
parent = parent.getParent();
if(!(parent instanceof PsiBlockStatement)) return null;
if (!(parent instanceof PsiBlockStatement)) return null;
parent = parent.getParent();
}
if(parent instanceof PsiIfStatement) return getNextReturnStatement((PsiStatement)parent);
if (parent instanceof PsiIfStatement) return getNextReturnStatement((PsiStatement)parent);
return null;
}
@Contract("null, null -> true; null, !null -> false")
private static boolean sameReference(PsiExpression expr1, PsiExpression expr2) {
if(expr1 == null && expr2 == null) return true;
if (expr1 == null && expr2 == null) return true;
if (!(expr1 instanceof PsiReferenceExpression) || !(expr2 instanceof PsiReferenceExpression)) return false;
PsiReferenceExpression ref1 = (PsiReferenceExpression)expr1;
PsiReferenceExpression ref2 = (PsiReferenceExpression)expr2;
@@ -140,36 +142,53 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
*/
@Nullable
static PsiExpression extractAddend(PsiAssignmentExpression assignment) {
if(JavaTokenType.PLUSEQ.equals(assignment.getOperationTokenType())) {
return assignment.getRExpression();
} else if(JavaTokenType.EQ.equals(assignment.getOperationTokenType())) {
if (assignment.getRExpression() instanceof PsiBinaryExpression) {
PsiBinaryExpression binOp = (PsiBinaryExpression)assignment.getRExpression();
if(JavaTokenType.PLUS.equals(binOp.getOperationTokenType())) {
if(sameReference(binOp.getLOperand(), assignment.getLExpression())) {
return binOp.getROperand();
}
if(sameReference(binOp.getROperand(), assignment.getLExpression())) {
return binOp.getLOperand();
}
return extractOperand(assignment, JavaTokenType.PLUSEQ);
}
@Nullable
static PsiExpression extractOperand(PsiAssignmentExpression assignment, IElementType compoundAssignmentOp) {
if (compoundAssignmentOp.equals(assignment.getOperationTokenType())) {
return assignment.getRExpression();
}
else if (JavaTokenType.EQ.equals(assignment.getOperationTokenType())) {
if (assignment.getRExpression() instanceof PsiBinaryExpression) {
PsiBinaryExpression binOp = (PsiBinaryExpression)assignment.getRExpression();
IElementType op = TypeConversionUtil.convertEQtoOperation(compoundAssignmentOp);
if (op.equals(binOp.getOperationTokenType())) {
if (sameReference(binOp.getLOperand(), assignment.getLExpression())) {
return binOp.getROperand();
}
if (sameReference(binOp.getROperand(), assignment.getLExpression())) {
return binOp.getLOperand();
}
}
}
return null;
}
return null;
}
@Nullable
static PsiVariable extractAccumulator(PsiAssignmentExpression assignment) {
static PsiVariable extractSumAccumulator(PsiAssignmentExpression assignment) {
return extractAccumulator(assignment, JavaTokenType.PLUSEQ);
}
@Nullable
static PsiVariable extractAccumulator(PsiAssignmentExpression assignment, IElementType compoundAssignmentOp) {
PsiReferenceExpression lExpr = tryCast(assignment.getLExpression(), PsiReferenceExpression.class);
if(lExpr == null) return null;
if (lExpr == null) return null;
PsiVariable var = tryCast(lExpr.resolve(), PsiVariable.class);
if(var == null) return null;
if(JavaTokenType.PLUSEQ.equals(assignment.getOperationTokenType())) {
if (var == null) return null;
if (compoundAssignmentOp.equals(assignment.getOperationTokenType())) {
return var;
} else if(JavaTokenType.EQ.equals(assignment.getOperationTokenType())) {
}
else if (JavaTokenType.EQ.equals(assignment.getOperationTokenType())) {
if (assignment.getRExpression() instanceof PsiBinaryExpression) {
PsiBinaryExpression binOp = (PsiBinaryExpression)assignment.getRExpression();
if(JavaTokenType.PLUS.equals(binOp.getOperationTokenType())) {
IElementType op = TypeConversionUtil.convertEQtoOperation(compoundAssignmentOp);
if (op.equals(binOp.getOperationTokenType())) {
PsiExpression left = binOp.getLOperand();
PsiExpression right = binOp.getROperand();
if (sameReference(left, lExpr) || sameReference(right, lExpr)) {
@@ -189,17 +208,19 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
*/
@Contract("null -> null")
static PsiExpression extractIncrementedLValue(PsiExpression expression) {
if(expression instanceof PsiPostfixExpression) {
if(JavaTokenType.PLUSPLUS.equals(((PsiPostfixExpression)expression).getOperationTokenType())) {
if (expression instanceof PsiPostfixExpression) {
if (JavaTokenType.PLUSPLUS.equals(((PsiPostfixExpression)expression).getOperationTokenType())) {
return ((PsiPostfixExpression)expression).getOperand();
}
} else if(expression instanceof PsiPrefixExpression) {
if(JavaTokenType.PLUSPLUS.equals(((PsiPrefixExpression)expression).getOperationTokenType())) {
}
else if (expression instanceof PsiPrefixExpression) {
if (JavaTokenType.PLUSPLUS.equals(((PsiPrefixExpression)expression).getOperationTokenType())) {
return ((PsiPrefixExpression)expression).getOperand();
}
} else if(expression instanceof PsiAssignmentExpression) {
}
else if (expression instanceof PsiAssignmentExpression) {
PsiAssignmentExpression assignment = (PsiAssignmentExpression)expression;
if(ExpressionUtils.isLiteral(extractAddend(assignment), 1)) {
if (ExpressionUtils.isLiteral(extractAddend(assignment), 1)) {
return assignment.getLExpression();
}
}
@@ -209,11 +230,11 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Nullable
private static PsiLocalVariable getIncrementedVariable(PsiExpression expression, TerminalBlock tb, List<PsiVariable> variables) {
// have only one non-final variable
if(variables.size() != 1) return null;
if (variables.size() != 1) return null;
// have single expression which is either ++x or x++ or x+=1 or x=x+1
PsiReferenceExpression operand = tryCast(extractIncrementedLValue(expression), PsiReferenceExpression.class);
if(operand == null) return null;
if (operand == null) return null;
PsiLocalVariable variable = tryCast(operand.resolve(), PsiLocalVariable.class);
// the referred variable is the same as non-final variable and not used in intermediate operations
@@ -224,23 +245,26 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
@Nullable
private static PsiVariable getAccumulatedVariable(TerminalBlock tb, List<PsiVariable> variables) {
private static PsiVariable getAccumulatedVariable(TerminalBlock tb,
List<PsiVariable> variables,
OperationReductionMigration.ReductionOperation operation) {
IElementType compoundAssignmentOp = operation.getCompoundAssignmentOp();
// have only one non-final variable
if(variables.size() != 1) return null;
if (variables.size() != 1) return null;
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
if(assignment == null) return null;
PsiVariable var = extractAccumulator(assignment);
if (assignment == null) return null;
PsiVariable var = extractAccumulator(assignment, compoundAssignmentOp);
// the referred variable is the same as non-final variable
if(var == null || !variables.contains(var)) return null;
if (!(var.getType() instanceof PsiPrimitiveType) || var.getType().equalsToText("float")) return null;
if (var == null || !variables.contains(var)) return null;
if (!operation.getAccumulatorRestriction().test(var)) return null;
// the referred variable is not used in intermediate operations
if(tb.isReferencedInOperations(var)) return null;
PsiExpression addend = extractAddend(assignment);
LOG.assertTrue(addend != null);
if(VariableAccessUtils.variableIsUsed(var, addend)) return null;
if (tb.isReferencedInOperations(var)) return null;
PsiExpression operand = extractOperand(assignment, compoundAssignmentOp);
LOG.assertTrue(operand != null);
if (VariableAccessUtils.variableIsUsed(var, operand)) return null;
return var;
}
@@ -284,7 +308,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
if (tb.isEmpty()) {
// like "if(++count == limit) break"
variable = getIncrementedVariable(counter, tb, nonFinalVariables);
} else if (!ExpressionUtils.isReferenceTo(counter, variable)) {
}
else if (!ExpressionUtils.isReferenceTo(counter, variable)) {
return false;
}
return variable != null &&
@@ -310,7 +335,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
static boolean isVariableSuitableForStream(PsiVariable variable, PsiStatement statement, TerminalBlock tb) {
if(ReferencesSearch.search(variable).forEach(ref -> {
if (ReferencesSearch.search(variable).forEach(ref -> {
PsiExpression expression = tryCast(ref.getElement(), PsiExpression.class);
return expression == null ||
!PsiUtil.isAccessedForWriting(expression) ||
@@ -324,14 +349,16 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
static String tryUnbox(PsiVariable variable) {
PsiType type = variable.getType();
String mapOp = null;
if(type.equals(PsiType.INT)) {
if (type.equals(PsiType.INT)) {
mapOp = "mapToInt";
} else if(type.equals(PsiType.LONG)) {
}
else if (type.equals(PsiType.LONG)) {
mapOp = "mapToLong";
} else if(type.equals(PsiType.DOUBLE)) {
}
else if (type.equals(PsiType.DOUBLE)) {
mapOp = "mapToDouble";
}
return mapOp == null ? "" : "."+mapOp+"("+variable.getName()+" -> "+variable.getName()+")";
return mapOp == null ? "" : "." + mapOp + "(" + variable.getName() + " -> " + variable.getName() + ")";
}
static boolean isExpressionDependsOnUpdatedCollections(PsiExpression condition,
@@ -403,9 +430,9 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
void processLoop(PsiLoopStatement statement) {
final PsiStatement body = statement.getBody();
if(body == null) return;
if (body == null) return;
StreamSource source = StreamSource.tryCreate(statement);
if(source == null) return;
if (source == null) return;
if (!ExceptionUtil.getThrownCheckedExceptions(body).isEmpty()) return;
TerminalBlock tb = TerminalBlock.from(source, body);
@@ -435,7 +462,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
int startOffset = controlFlow.getStartOffset(body);
int endOffset = controlFlow.getEndOffset(body);
if(startOffset < 0 || endOffset < 0) return null;
if (startOffset < 0 || endOffset < 0) return null;
PsiElement surrounder = PsiTreeUtil.getParentOfType(loop, PsiLambdaExpression.class, PsiClass.class);
final List<PsiVariable> nonFinalVariables = StreamEx.of(ControlFlowUtil.getUsedVariables(controlFlow, startOffset, endOffset))
.remove(variable -> variable instanceof PsiField)
@@ -447,11 +474,11 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
if (nonFinalVariables.isEmpty()) {
CollectMigration.CollectTerminal terminal = CollectMigration.extractCollectTerminal(tb);
if(terminal != null) {
if (terminal != null) {
boolean addAll = loop instanceof PsiForeachStatement && !tb.hasOperations() && isAddAllCall(tb);
// Don't suggest to convert the loop which can be trivially replaced via addAll:
// this is covered by UseBulkOperationInspection and ManualArrayToCollectionCopyInspection
if(addAll) return null;
if (addAll) return null;
boolean shouldWarn = REPLACE_TRIVIAL_FOREACH ||
tb.hasOperations() ||
tb.getLastOperation() instanceof BufferedReaderLines ||
@@ -463,9 +490,14 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
if (nonFinalVariables.isEmpty() && extractArray(tb) != null) {
return new ToArrayMigration(true);
}
if (getAccumulatedVariable(tb, nonFinalVariables) != null) {
if (getAccumulatedVariable(tb, nonFinalVariables, SUM_OPERATION) != null) {
return new SumMigration(true);
}
for (OperationReductionMigration.ReductionOperation reductionOperation : OperationReductionMigration.OPERATIONS) {
if (getAccumulatedVariable(tb, nonFinalVariables, reductionOperation) != null) {
return new OperationReductionMigration(true, reductionOperation);
}
}
Collection<PsiStatement> exitPoints = tb.findExitPoints(controlFlow);
if (exitPoints == null) return null;
if (exitPoints.isEmpty() && nonFinalVariables.isEmpty()) {
@@ -508,14 +540,14 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
if (nonFinalVariables.size() == 1) {
PsiAssignmentExpression assignment = ExpressionUtils.getAssignment(statement);
if(assignment == null) return null;
if (assignment == null) return null;
PsiReferenceExpression lValue = tryCast(assignment.getLExpression(), PsiReferenceExpression.class);
if (lValue == null) return null;
PsiVariable var = tryCast(lValue.resolve(), PsiVariable.class);
if(var == null || !nonFinalVariables.contains(var)) return null;
if (var == null || !nonFinalVariables.contains(var)) return null;
PsiExpression rValue = assignment.getRExpression();
if(rValue == null || VariableAccessUtils.variableIsUsed(var, rValue)) return null;
if(tb.getVariable().getType() instanceof PsiPrimitiveType && !ExpressionUtils.isReferenceTo(rValue, tb.getVariable())) return null;
if (rValue == null || VariableAccessUtils.variableIsUsed(var, rValue)) return null;
if (tb.getVariable().getType() instanceof PsiPrimitiveType && !ExpressionUtils.isReferenceTo(rValue, tb.getVariable())) return null;
return new FindFirstMigration(shouldWarn);
}
return null;
@@ -537,12 +569,12 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
else {
methodName = "noneMatch";
FilterOp lastFilter = tb.getLastOperation(FilterOp.class);
if(lastFilter != null && (lastFilter.isNegated() ^ BoolUtils.isNegation(lastFilter.getExpression()))) {
if (lastFilter != null && (lastFilter.isNegated() ^ BoolUtils.isNegation(lastFilter.getExpression()))) {
methodName = "allMatch";
}
}
if(nextReturnStatement.getParent() == statement.getParent() ||
ExpressionUtils.isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) {
if (nextReturnStatement.getParent() == statement.getParent() ||
ExpressionUtils.isLiteral(nextReturnStatement.getReturnValue(), !foundResult)) {
return new MatchMigration(shouldWarn, methodName);
}
}
@@ -553,8 +585,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
return new MatchMigration(shouldWarn, "anyMatch");
}
if(nextReturnStatement != null && ExpressionUtils.isSimpleExpression(nextReturnStatement.getReturnValue())
&& (!(tb.getVariable().getType() instanceof PsiPrimitiveType) || ExpressionUtils.isReferenceTo(value, tb.getVariable()))) {
if (nextReturnStatement != null && ExpressionUtils.isSimpleExpression(nextReturnStatement.getReturnValue())
&& (!(tb.getVariable().getType() instanceof PsiPrimitiveType) || ExpressionUtils.isReferenceTo(value, tb.getVariable()))) {
return new FindFirstMigration(shouldWarn);
}
return null;
@@ -564,7 +596,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
private TextRange getRange(boolean shouldWarn, PsiLoopStatement statement) {
boolean wholeStatement =
myIsOnTheFly && (!shouldWarn || InspectionProjectProfileManager.isInformationLevel(getShortName(), statement));
if(statement instanceof PsiForeachStatement) {
if (statement instanceof PsiForeachStatement) {
PsiJavaToken rParenth = ((PsiForeachStatement)statement).getRParenth();
if (wholeStatement && rParenth != null) {
return new TextRange(statement.getTextOffset(), rParenth.getTextOffset() + 1);
@@ -572,7 +604,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
PsiExpression iteratedValue = ((PsiForeachStatement)statement).getIteratedValue();
LOG.assertTrue(iteratedValue != null);
return iteratedValue.getTextRange();
} else if(statement instanceof PsiForStatement) {
}
else if (statement instanceof PsiForStatement) {
PsiJavaToken rParenth = ((PsiForStatement)statement).getRParenth();
if (wholeStatement && rParenth != null) {
return new TextRange(statement.getTextOffset(), rParenth.getTextOffset() + 1);
@@ -580,14 +613,16 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
PsiStatement initialization = ((PsiForStatement)statement).getInitialization();
LOG.assertTrue(initialization != null);
return initialization.getTextRange();
} else if(statement instanceof PsiWhileStatement) {
}
else if (statement instanceof PsiWhileStatement) {
PsiJavaToken rParenth = ((PsiWhileStatement)statement).getRParenth();
if (wholeStatement && rParenth != null) {
return new TextRange(statement.getTextOffset(), rParenth.getTextOffset() + 1);
}
return statement.getFirstChild().getTextRange();
} else {
throw new IllegalStateException("Unexpected statement type: "+statement);
}
else {
throw new IllegalStateException("Unexpected statement type: " + statement);
}
}
}
@@ -595,28 +630,28 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Nullable
static PsiLocalVariable extractArray(TerminalBlock tb) {
CountingLoopSource loop = tb.getLastOperation(CountingLoopSource.class);
if(loop == null || loop.myIncluding) return null;
if (loop == null || loop.myIncluding) return null;
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
if(assignment == null || !assignment.getOperationTokenType().equals(JavaTokenType.EQ)) return null;
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;
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;
if (arrayReference == null) return null;
PsiLocalVariable arrayVariable = tryCast(arrayReference.resolve(), PsiLocalVariable.class);
if(arrayVariable == null || ControlFlowUtils.getInitializerUsageStatus(arrayVariable, tb.getMainLoop()) == UNKNOWN) return null;
if (arrayVariable == null || ControlFlowUtils.getInitializerUsageStatus(arrayVariable, tb.getMainLoop()) == UNKNOWN) return null;
PsiNewExpression initializer = tryCast(arrayVariable.getInitializer(), PsiNewExpression.class);
if(initializer == null) return null;
if (initializer == null) return null;
PsiArrayType arrayType = tryCast(initializer.getType(), PsiArrayType.class);
if(arrayType == null || !StreamApiUtil.isSupportedStreamElement(arrayType.getComponentType())) return null;
if (arrayType == null || !StreamApiUtil.isSupportedStreamElement(arrayType.getComponentType())) return null;
PsiExpression dimension = ArrayUtil.getFirstElement(initializer.getArrayDimensions());
if(dimension == null) return null;
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;
if (VariableAccessUtils.variableIsUsed(arrayVariable, assignment.getRExpression())) return null;
return arrayVariable;
}
@@ -712,8 +747,8 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Override
PsiExpression makeIntermediateExpression(PsiElementFactory factory) {
return factory.createExpressionFromText(myFlatMapOp.getStreamExpression()+".anyMatch("+
LambdaUtil.createLambda(myMatchVariable, myExpression)+")", myExpression);
return factory.createExpressionFromText(myFlatMapOp.getStreamExpression() + ".anyMatch(" +
LambdaUtil.createLambda(myMatchVariable, myExpression) + ")", myExpression);
}
@Override
@@ -760,16 +795,18 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
PsiType inType = myVariable.getType();
PsiType outType = mySource.getVariable().getType();
String lambda = myVariable.getName() + " -> " + getStreamExpression();
if(outType instanceof PsiPrimitiveType && !outType.equals(inType)) {
if(outType.equals(PsiType.INT)) {
if (outType instanceof PsiPrimitiveType && !outType.equals(inType)) {
if (outType.equals(PsiType.INT)) {
operation = "flatMapToInt";
} else if(outType.equals(PsiType.LONG)) {
}
else if (outType.equals(PsiType.LONG)) {
operation = "flatMapToLong";
} else if(outType.equals(PsiType.DOUBLE)) {
}
else if (outType.equals(PsiType.DOUBLE)) {
operation = "flatMapToDouble";
}
}
if(inType instanceof PsiPrimitiveType && !outType.equals(inType)) {
if (inType instanceof PsiPrimitiveType && !outType.equals(inType)) {
return ".mapToObj(" + lambda + ")." + operation + "(" + CommonClassNames.JAVA_UTIL_FUNCTION_FUNCTION + ".identity())";
}
return "." + operation + "(" + lambda + ")";
@@ -827,7 +864,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Override
void cleanUp() {
if(myCounterVariable != null) {
if (myCounterVariable != null) {
myCounterVariable.delete();
}
}
@@ -838,7 +875,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
}
private String getLimitExpression() {
if(myDelta == 0) {
if (myDelta == 0) {
return myExpression.getText();
}
if (myExpression instanceof PsiLiteralExpression) {
@@ -876,14 +913,14 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Contract("null -> null")
static StreamSource tryCreate(PsiLoopStatement statement) {
if(statement instanceof PsiForStatement) {
if (statement instanceof PsiForStatement) {
return CountingLoopSource.from((PsiForStatement)statement);
}
if(statement instanceof PsiForeachStatement) {
if (statement instanceof PsiForeachStatement) {
ArrayStream source = ArrayStream.from((PsiForeachStatement)statement);
return source == null ? CollectionStream.from((PsiForeachStatement)statement) : source;
}
if(statement instanceof PsiWhileStatement) {
if (statement instanceof PsiWhileStatement) {
return BufferedReaderLines.from((PsiWhileStatement)statement);
}
return null;
@@ -897,7 +934,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Override
String createReplacement() {
return myExpression.getText()+".lines()";
return myExpression.getText() + ".lines()";
}
@Override
@@ -914,30 +951,30 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
public static BufferedReaderLines from(PsiWhileStatement whileLoop) {
// while ((line = br.readLine()) != null)
PsiBinaryExpression binOp = tryCast(PsiUtil.skipParenthesizedExprDown(whileLoop.getCondition()), PsiBinaryExpression.class);
if(binOp == null) return null;
if(!JavaTokenType.NE.equals(binOp.getOperationTokenType())) return null;
if (binOp == null) return null;
if (!JavaTokenType.NE.equals(binOp.getOperationTokenType())) return null;
PsiExpression operand = ExpressionUtils.getValueComparedWithNull(binOp);
if(operand == null) return null;
if (operand == null) return null;
PsiAssignmentExpression assignment = ExpressionUtils.getAssignment(PsiUtil.skipParenthesizedExprDown(operand));
if(assignment == null) return null;
if (assignment == null) return null;
PsiReferenceExpression lValue = tryCast(assignment.getLExpression(), PsiReferenceExpression.class);
if(lValue == null) return null;
if (lValue == null) return null;
PsiLocalVariable var = tryCast(lValue.resolve(), PsiLocalVariable.class);
if(var == null) return null;
if(!ReferencesSearch.search(var).forEach(ref -> {
if (var == null) return null;
if (!ReferencesSearch.search(var).forEach(ref -> {
return PsiTreeUtil.isAncestor(whileLoop, ref.getElement(), true);
})) {
return null;
}
PsiMethodCallExpression call = tryCast(PsiUtil.skipParenthesizedExprDown(assignment.getRExpression()), PsiMethodCallExpression.class);
if (call == null || call.getArgumentList().getExpressions().length != 0) return null;
if(!"readLine".equals(call.getMethodExpression().getReferenceName())) return null;
if (!"readLine".equals(call.getMethodExpression().getReferenceName())) return null;
PsiExpression readerExpression = call.getMethodExpression().getQualifierExpression();
if(readerExpression == null) return null;
if (readerExpression == null) return null;
PsiMethod method = call.resolveMethod();
if(method == null) return null;
if (method == null) return null;
PsiClass aClass = method.getContainingClass();
if(aClass == null || !"java.io.BufferedReader".equals(aClass.getQualifiedName())) return null;
if (aClass == null || !"java.io.BufferedReader".equals(aClass.getQualifiedName())) return null;
return new BufferedReaderLines(whileLoop, var, readerExpression);
}
}
@@ -1053,7 +1090,7 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
public String createReplacement() {
String className = myVariable.getType().equals(PsiType.LONG) ? "java.util.stream.LongStream" : "java.util.stream.IntStream";
String methodName = myIncluding ? "rangeClosed" : "range";
return className+"."+methodName+"("+myExpression.getText()+", "+myBound.getText()+")";
return className + "." + methodName + "(" + myExpression.getText() + ", " + myBound.getText() + ")";
}
CountingLoopSource withBound(PsiExpression bound) {
@@ -1062,9 +1099,9 @@ public class StreamApiMigrationInspection extends BaseJavaBatchLocalInspectionTo
@Override
boolean isWriteAllowed(PsiVariable variable, PsiExpression reference) {
if(variable == myVariable) {
if (variable == myVariable) {
PsiForStatement forStatement = PsiTreeUtil.getParentOfType(variable, PsiForStatement.class);
if(forStatement != null) {
if (forStatement != null) {
return PsiTreeUtil.isAncestor(forStatement.getUpdate(), reference, false);
}
}
@@ -22,6 +22,8 @@ import com.intellij.psi.util.TypeConversionUtil;
import com.siyeh.ig.psiutils.ParenthesesUtils;
import org.jetbrains.annotations.NotNull;
import static com.intellij.codeInspection.streamMigration.OperationReductionMigration.SUM_OPERATION;
/**
* @author Tagir Valeev
*/
@@ -33,7 +35,7 @@ class SumMigration extends BaseStreamApiMigration {
PsiElement migrate(@NotNull Project project, @NotNull PsiStatement body, @NotNull TerminalBlock tb) {
PsiAssignmentExpression assignment = tb.getSingleExpression(PsiAssignmentExpression.class);
if (assignment == null) return null;
PsiVariable var = StreamApiMigrationInspection.extractAccumulator(assignment);
PsiVariable var = StreamApiMigrationInspection.extractSumAccumulator(assignment);
if (var == null) return null;
PsiExpression addend = StreamApiMigrationInspection.extractAddend(assignment);
@@ -49,6 +51,6 @@ class SumMigration extends BaseStreamApiMigration {
"(" + type.getCanonicalText() + ")" + ParenthesesUtils.getText(addend, ParenthesesUtils.MULTIPLICATIVE_PRECEDENCE), addend);
}
String stream = tb.add(new MapOp(addend, tb.getVariable(), type)).generate()+".sum()";
return replaceWithNumericAddition(tb.getMainLoop(), var, stream, type);
return replaceWithOperation(tb.getMainLoop(), var, stream, type, SUM_OPERATION);
}
}
@@ -0,0 +1,11 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAnd() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12443;
acc &= Arrays.stream(arr).reduce(-1, (a, b) -> a & b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndHighestBit() {
int[] arr = {0x80000000, 0xffffffff};
int acc = Arrays.stream(arr).reduce(-1, (a, b) -> a & b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndReplacingInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = Arrays.stream(arr).reduce(0xFFFFFFFF, (a, b) -> a & b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndReplacingInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = Arrays.stream(arr).reduce(-1, (a, b) -> a & b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndReplacingLongInitializer() {
long[] arr = new long[]{1, 2, 3, 4};
long acc = Arrays.stream(arr).reduce(-1l, (a, b) -> a & b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testConjunction() {
List<Boolean> booleans = new ArrayList<>();
boolean acc = booleans.stream().reduce(true, (a, b) -> a && b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testConjunctionBoxed() {
List<Boolean> booleans = new ArrayList<>();
Boolean acc = booleans.stream().reduce(true, (a, b) -> a && b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testDisjunction() {
List<Boolean> booleans = new ArrayList<>();
boolean acc = booleans.stream().reduce(false, (a, b) -> a || b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiply() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = Arrays.stream(arr).reduce(1, (a, b) -> a * b);
}
}
@@ -0,0 +1,12 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithComplexInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
int x = 10;
int acc = 12 + x;
acc *= Arrays.stream(arr).reduce(1, (a, b) -> a * b);
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithConflictingNamesInScope() {
int a = 1;
int b = 2;
int b1 = 3;
int[] arr = new int[]{1, 2, 3, 4};
int acc = Arrays.stream(arr).reduce(1, (a1, b2) -> a1 * b2);
}
}
@@ -0,0 +1,11 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithNarrowingTypeInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
short acc = (byte) 12;
acc *= Arrays.stream(arr).map(i -> (short) i).reduce(1, (a, b) -> a * b);
}
}
@@ -0,0 +1,11 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithNotOneInitializerConstant() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12;
acc *= Arrays.stream(arr).reduce(1, (a, b) -> a * b);
}
}
@@ -0,0 +1,10 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithMapping() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = Arrays.stream(arr).map(i -> i + 2).reduce(1, (a, b) -> a * b);
}
}
@@ -0,0 +1,11 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseOr() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12443;
acc |= Arrays.stream(arr).reduce(0, (a, b) -> a | b);
}
}
@@ -0,0 +1,11 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseXor() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12443;
acc ^= Arrays.stream(arr).reduce(0, (a, b) -> a ^ b);
}
}
@@ -0,0 +1,11 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseXorLong() {
int[] arr = new int[]{1, 2, 3, 4};
long acc = 12443;
acc ^= Arrays.stream(arr).asLongStream().reduce(0, (a, b) -> a ^ b);
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAnd() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12443;
for <caret> (int i: arr) {
acc &= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndHighestBit() {
int[] arr = {0x80000000, 0xffffffff};
int acc = -1;
for <caret> (int i: arr) {
acc &= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndReplacingInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 0xFFFFFFFF;
for <caret> (int i: arr) {
acc &= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndReplacingInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = -1;
for <caret> (int i: arr) {
acc &= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseAndReplacingLongInitializer() {
long[] arr = new long[]{1, 2, 3, 4};
long acc = -1l;
for <caret> (long i: arr) {
acc &= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testConjunction() {
List<Boolean> booleans = new ArrayList<>();
boolean acc = true;
for <caret> (Boolean bool : booleans) {
acc &= bool;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testConjunctionBoxed() {
List<Boolean> booleans = new ArrayList<>();
Boolean acc = true;
for <caret> (Boolean bool : booleans) {
acc &= bool;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testDisjunction() {
List<Boolean> booleans = new ArrayList<>();
boolean acc = false;
for <caret> (Boolean bool : booleans) {
acc |= bool;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiply() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 1;
for <caret> (int i : arr) {
acc *= i;
}
}
}
@@ -0,0 +1,14 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithComplexInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
int x = 10;
int acc = 12 + x;
for <caret> (int i : arr) {
acc *= i;
}
}
}
@@ -0,0 +1,16 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithConflictingNamesInScope() {
int a = 1;
int b = 2;
int b1 = 3;
int[] arr = new int[]{1, 2, 3, 4};
int acc = 1;
for <caret> (int i : arr) {
acc *= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithNarrowingTypeInitializer() {
int[] arr = new int[]{1, 2, 3, 4};
short acc = (byte) 12;
for <caret> (int i : arr) {
acc *= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithNotOneInitializerConstant() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12;
for <caret> (int i : arr) {
acc *= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testMultiplyWithMapping() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 1;
for <caret> (int i : arr) {
acc *= i + 2;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseOr() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12443;
for <caret> (int i: arr) {
acc |= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseXor() {
int[] arr = new int[]{1, 2, 3, 4};
int acc = 12443;
for <caret> (int i: arr) {
acc ^= i;
}
}
}
@@ -0,0 +1,13 @@
// "Replace with reduce()" "true"
import java.util.*;
public class Main {
public void testBitwiseXorLong() {
int[] arr = new int[]{1, 2, 3, 4};
long acc = 12443;
for <caret> (int i: arr) {
acc ^= i;
}
}
}