From 509975fd47ac2b6b9addb2e15df829249e896ee6 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 24 Aug 2022 16:18:23 +0200 Subject: [PATCH] IG: fix manual array copy fix when encountering != (IDEA-300459) GitOrigin-RevId: a03e070c889f46364ffbadb036105126e6f49a87 --- .../ManualArrayCopyInspection.java | 93 +++++-------------- .../NotEqual.after.java | 10 ++ .../NotEqual.java | 11 +++ .../performance/ManualArrayCopyFixTest.java | 6 +- 4 files changed, 45 insertions(+), 75 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.java diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java index 5b21feb56974..79173e2815fd 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/performance/ManualArrayCopyInspection.java @@ -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) { diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.after.java new file mode 100644 index 000000000000..c04c6d0c2317 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.after.java @@ -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); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.java new file mode 100644 index 000000000000..b9190e95d5b1 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/performance/replace_with_system_arraycopy/NotEqual.java @@ -0,0 +1,11 @@ +class NotEqual { + + void colors() { + String[] input = new String[] { "Color.WHITE", "Color.GREEN" }; + String[] copy = new String[input.length]; + + for (int i = 0; i != input.length; ++i) { // Manual array copy + copy[i] = input[i]; + } + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/ManualArrayCopyFixTest.java b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/ManualArrayCopyFixTest.java index 406d3e9a5c54..820aea4641a7 100644 --- a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/ManualArrayCopyFixTest.java +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/performance/ManualArrayCopyFixTest.java @@ -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(); } } \ No newline at end of file