IG: fix manual array copy fix when encountering != (IDEA-300459)

GitOrigin-RevId: a03e070c889f46364ffbadb036105126e6f49a87
This commit is contained in:
Bas Leijdekkers
2022-08-24 16:29:33 +00:00
committed by intellij-monorepo-bot
parent c7c709a23a
commit 509975fd47
4 changed files with 45 additions and 75 deletions
@@ -52,18 +52,11 @@ public class ManualArrayCopyInspection extends BaseInspection implements Cleanup
@Override
public InspectionGadgetsFix buildFix(Object... infos) {
final Boolean decrement = (Boolean)infos[0];
return new ManualArrayCopyFix(decrement.booleanValue());
return new ManualArrayCopyFix();
}
private static class ManualArrayCopyFix extends InspectionGadgetsFix {
private final boolean decrement;
ManualArrayCopyFix(boolean decrement) {
this.decrement = decrement;
}
@Override
@NotNull
public String getFamilyName() {
@@ -87,48 +80,17 @@ public class ManualArrayCopyInspection extends BaseInspection implements Cleanup
}
}
private @Nullable @NonNls String buildSystemArrayCopyText(PsiForStatement forStatement, CommentTracker commentTracker) {
final PsiExpression condition = forStatement.getCondition();
final PsiBinaryExpression binaryExpression = (PsiBinaryExpression)PsiUtil.skipParenthesizedExprDown(condition);
if (binaryExpression == null) {
private static @Nullable @NonNls String buildSystemArrayCopyText(PsiForStatement forStatement, CommentTracker commentTracker) {
final CountingLoop countingLoop = CountingLoop.from(forStatement);
if (countingLoop == null) {
return null;
}
final IElementType tokenType = binaryExpression.getOperationTokenType();
final PsiExpression limit;
if (decrement ^ JavaTokenType.LT.equals(tokenType) || JavaTokenType.LE.equals(tokenType)) {
limit = binaryExpression.getROperand();
}
else {
limit = binaryExpression.getLOperand();
}
if (limit == null) {
return null;
}
final PsiStatement initialization = forStatement.getInitialization();
if (initialization == null) {
return null;
}
if (!(initialization instanceof PsiDeclarationStatement)) {
return null;
}
final PsiDeclarationStatement declaration = (PsiDeclarationStatement)initialization;
final PsiElement[] declaredElements = declaration.getDeclaredElements();
if (declaredElements.length != 1) {
return null;
}
final PsiElement declaredElement = declaredElements[0];
if (!(declaredElement instanceof PsiLocalVariable)) {
return null;
}
final PsiLocalVariable variable = (PsiLocalVariable)declaredElement;
final String lengthText;
final PsiExpression initializer = variable.getInitializer();
if (decrement) {
lengthText = buildLengthText(initializer, limit, JavaTokenType.LE.equals(tokenType) || JavaTokenType.GE.equals(tokenType), commentTracker);
}
else {
lengthText = buildLengthText(limit, initializer, JavaTokenType.LE.equals(tokenType) || JavaTokenType.GE.equals(tokenType), commentTracker);
}
final PsiExpression limit = countingLoop.getBound();
final PsiExpression initializer = countingLoop.getInitializer();
final String lengthText =
countingLoop.isDescending()
? buildLengthText(initializer, limit, countingLoop.isIncluding(), commentTracker)
: buildLengthText(limit, initializer, countingLoop.isIncluding(), commentTracker);
if (lengthText == null) {
return null;
}
@@ -144,23 +106,13 @@ public class ManualArrayCopyInspection extends BaseInspection implements Cleanup
}
final PsiExpression rArray = rhs.getArrayExpression();
final String fromArrayText = commentTracker.text(rArray);
final PsiExpression rhsIndexExpression = rhs.getIndexExpression();
final PsiExpression strippedRhsIndexExpression = PsiUtil.skipParenthesizedExprDown(rhsIndexExpression);
final PsiExpression limitExpression;
if (decrement) {
limitExpression = limit;
}
else {
limitExpression = initializer;
}
final String fromOffsetText = buildOffsetText(strippedRhsIndexExpression, variable, limitExpression, decrement &&
(JavaTokenType.LT.equals(tokenType) || JavaTokenType.GT.equals(tokenType)), commentTracker);
final PsiExpression lhsIndexExpression = lhs.getIndexExpression();
final PsiExpression strippedLhsIndexExpression = PsiUtil.skipParenthesizedExprDown(lhsIndexExpression);
final String toOffsetText =
buildOffsetText(strippedLhsIndexExpression, variable, limitExpression,
decrement && (JavaTokenType.LT.equals(tokenType) || JavaTokenType.GT.equals(tokenType)),
commentTracker);
final PsiExpression rhsIndexExpression = PsiUtil.skipParenthesizedExprDown(rhs.getIndexExpression());
final PsiExpression limitExpression = countingLoop.isDescending() ? limit : initializer;
final String fromOffsetText = buildOffsetText(rhsIndexExpression, countingLoop.getCounter(), limitExpression,
countingLoop.isDescending() && !countingLoop.isIncluding(), commentTracker);
final PsiExpression lhsIndexExpression = PsiUtil.skipParenthesizedExprDown(lhs.getIndexExpression());
final String toOffsetText = buildOffsetText(lhsIndexExpression, countingLoop.getCounter(), limitExpression,
countingLoop.isDescending() && !countingLoop.isIncluding(), commentTracker);
return "if(" + lengthText + ">=0)" +
"System.arraycopy(" + fromArrayText + "," + fromOffsetText + "," + toArrayText + "," + toOffsetText + "," + lengthText + ");";
}
@@ -272,12 +224,9 @@ public class ManualArrayCopyInspection extends BaseInspection implements Cleanup
}
}
final String maxText = buildExpressionText(max, false, commentTracker);
if (minValue > 0) {
return maxText + '-' + minValue;
}
else {
return maxText + '+' + -minValue;
}
return minValue > 0
? maxText + '-' + minValue
: maxText + '+' + -minValue;
}
// - 1 because of the increment inside the com.siyeh.ig.psiutils.CommentTracker.text(com.intellij.psi.PsiExpression, int)
final String minText = commentTracker.text(min, ParenthesesUtils.ADDITIVE_PRECEDENCE - 1);
@@ -360,7 +309,7 @@ public class ManualArrayCopyInspection extends BaseInspection implements Cleanup
if (!bodyIsArrayCopy(body, countingLoop.getCounter())) {
return;
}
registerStatementError(statement, Boolean.valueOf(countingLoop.isDescending()));
registerStatementError(statement);
}
private static boolean bodyIsArrayCopy(PsiStatement body, PsiVariable variable) {
@@ -0,0 +1,10 @@
class NotEqual {
void colors() {
String[] input = new String[] { "Color.WHITE", "Color.GREEN" };
String[] copy = new String[input.length];
// Manual array copy
System.arraycopy(input, 0, copy, 0, input.length);
}
}
@@ -0,0 +1,11 @@
class NotEqual {
void colors() {
String[] input = new String[] { "Color.WHITE", "Color.GREEN" };
String[] copy = new String[input.length];
for<caret> (int i = 0; i != input.length; ++i) { // Manual array copy
copy[i] = input[i];
}
}
}
@@ -1,3 +1,4 @@
// Copyright 2000-2022 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.siyeh.ig.fixes.performance;
import com.intellij.codeInspection.CommonQuickFixBundle;
@@ -17,7 +18,6 @@ public class ManualArrayCopyFixTest extends IGQuickFixesTestCase {
public void testSimple() { doTest(); }
public void testDecrement() { doTest(); }
public void testLengthSmallerThanOffset() { doTest(); }
public void testInitializerContainsSubtraction() {
doTest();
}
public void testInitializerContainsSubtraction() { doTest(); }
public void testNotEqual() { doTest(); }
}