mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-05-06 13:20:53 +07:00
[java-inspections] RedundantStringOperation: suggest using 'String#contentEquals' to compare strings with StringBuilder
IDEA-273162 GitOrigin-RevId: 89c0c2d697cec22b8d5c661f2063e35ccab9e9aa
This commit is contained in:
committed by
intellij-monorepo-bot
parent
f88fdf391c
commit
f0efafd51c
@@ -0,0 +1,6 @@
|
||||
// "Use 'contentEquals()' and remove redundant 'toString()' call" "true-preview"
|
||||
class Main {
|
||||
boolean foo(String s, StringBuffer sb) {
|
||||
return ((s)).contentEquals(((((sb)))));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// "Use 'contentEquals()' and remove redundant 'toString()' call" "true-preview"
|
||||
class Main {
|
||||
boolean foo(String s, StringBuilder sb) {
|
||||
return s.contentEquals(sb);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// "Use 'contentEquals()' and remove redundant 'toString()' call" "true-preview"
|
||||
class Main {
|
||||
boolean foo(String s, StringBuffer sb) {
|
||||
return ((s)).equals(((((sb)).toString<caret>())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
// "Use 'contentEquals()' and remove redundant 'toString()' call" "true-preview"
|
||||
class Main {
|
||||
boolean foo(String s, StringBuilder sb) {
|
||||
return s.equals(sb.toString<caret>());
|
||||
}
|
||||
}
|
||||
@@ -2383,7 +2383,8 @@ unnecessary.fully.qualified.name.fix.family.name=Replace fully qualified name
|
||||
return.of.collection.field.fix.family.name=Make return collection 'unmodifiable'
|
||||
remove.redundant.substring.fix.family.name=Remove redundant 'substring()' call
|
||||
remove.redundant.string.fix.text=Use ''{0}()'' and remove redundant ''{1}()'' call
|
||||
use.equalsignorecase.for.case.insensitive.comparison=Use equalsIgnoreCase() for case-insensitive comparison
|
||||
use.equalsignorecase.for.case.insensitive.comparison=Use 'equalsIgnoreCase()' for case-insensitive comparison
|
||||
use.contentequals=Use 'contentEquals()' for comparison with 'AbstractStringBuilder'
|
||||
use.isblank.to.check.if.string.is.whitespace.or.empty=Use 'isBlank()' to check if a string is empty or only contains whitespace
|
||||
make.class.final.fix.family.name=Make class final
|
||||
side.effects.method.ref.to.lambda.fix.family.name={0} (side effects)
|
||||
|
||||
@@ -6,7 +6,6 @@ import com.intellij.codeInsight.daemon.QuickFixBundle;
|
||||
import com.intellij.codeInsight.daemon.impl.quickfix.DeleteElementFix;
|
||||
import com.intellij.codeInspection.*;
|
||||
import com.intellij.codeInspection.options.OptPane;
|
||||
import com.intellij.codeInspection.ui.SingleCheckboxOptionsPanel;
|
||||
import com.intellij.codeInspection.util.IntentionFamilyName;
|
||||
import com.intellij.codeInspection.util.IntentionName;
|
||||
import com.intellij.java.analysis.JavaAnalysisBundle;
|
||||
@@ -26,17 +25,18 @@ import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.*;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static com.intellij.codeInspection.options.OptPane.*;
|
||||
import static com.intellij.codeInspection.options.OptPane.checkbox;
|
||||
import static com.intellij.codeInspection.options.OptPane.pane;
|
||||
import static com.intellij.psi.CommonClassNames.*;
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
import static com.siyeh.HardcodedMethodConstants.EQUALS_IGNORE_CASE;
|
||||
import static com.siyeh.HardcodedMethodConstants.TO_STRING;
|
||||
import static com.siyeh.InspectionGadgetsBundle.BUNDLE;
|
||||
import static com.siyeh.ig.callMatcher.CallMatcher.*;
|
||||
|
||||
@@ -46,6 +46,8 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
|
||||
REPLACE_WITH_ARGUMENTS
|
||||
}
|
||||
|
||||
public static final String CONTENT_EQUALS = "contentEquals";
|
||||
|
||||
private static final CallMatcher BYTE_ARRAY_OUTPUT_STREAM_INTO_BYTE_ARRAY =
|
||||
exactInstanceCall(JAVA_IO_BYTE_ARRAY_OUTPUT_STREAM, "toByteArray").parameterCount(0);
|
||||
private static final CallMatcher STRING_TO_STRING = exactInstanceCall(JAVA_LANG_STRING, "toString").parameterCount(0);
|
||||
@@ -99,7 +101,7 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
|
||||
.register(STRING_TO_STRING, call -> getProblem(call, "inspection.redundant.string.call.message"))
|
||||
.register(STRING_SUBSTRING, this::getSubstringProblem)
|
||||
.register(STRING_BUILDER_APPEND, this::getAppendProblem)
|
||||
.register(STRING_BUILDER_TO_STRING, this::getRedundantStringBuilderToStringProblem)
|
||||
.register(STRING_BUILDER_TO_STRING, this::getStringBuilderToStringProblem)
|
||||
.register(STRING_INTERN, this::getInternProblem)
|
||||
.register(PRINTSTREAM_PRINTLN, call ->
|
||||
getRedundantArgumentProblem(getSingleEmptyStringArgument(call), "inspection.redundant.empty.string.argument.message"))
|
||||
@@ -417,6 +419,13 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
|
||||
return getSingleEmptyStringArgument(call) != null ? getProblem(call, "inspection.redundant.string.call.message") : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProblemDescriptor getStringBuilderToStringProblem(@NotNull final PsiMethodCallExpression call) {
|
||||
final ProblemDescriptor descriptor = getRedundantStringBuilderToStringProblem(call);
|
||||
if (descriptor != null) return descriptor;
|
||||
return getUseContentEqualsProblem(call);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProblemDescriptor getRedundantStringBuilderToStringProblem(@NotNull final PsiMethodCallExpression call) {
|
||||
final PsiMethodCallExpression substringCall = PsiTreeUtil.getParentOfType(call, PsiMethodCallExpression.class);
|
||||
@@ -428,6 +437,21 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
|
||||
return getProblem(call, "inspection.redundant.string.call.message");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProblemDescriptor getUseContentEqualsProblem(@NotNull final PsiMethodCallExpression call) {
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(call.getParent());
|
||||
if (parent instanceof PsiExpressionList list &&
|
||||
list.getExpressionCount() == 1 &&
|
||||
parent.getParent() instanceof PsiMethodCallExpression parentCall &&
|
||||
STRING_EQUALS.test(parentCall)) {
|
||||
PsiElement nameElement = Objects.requireNonNull(call.getMethodExpression().getReferenceNameElement());
|
||||
final String message = InspectionGadgetsBundle.message("inspection.x.call.can.be.replaced.with.y", CONTENT_EQUALS);
|
||||
return myManager.createProblemDescriptor(nameElement, message, new UseContentEqualsFix(),
|
||||
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, myIsOnTheFly);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private ProblemDescriptor getInternProblem(PsiMethodCallExpression call) {
|
||||
return PsiUtil.isConstantExpression(call.getMethodExpression().getQualifierExpression())
|
||||
@@ -665,6 +689,38 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
|
||||
}
|
||||
}
|
||||
|
||||
private static void useMethodInsteadOfRedundantCall(String methodToUse, PsiMethodCallExpression redundantCall) {
|
||||
PsiMethodCallExpression equalsCall = PsiTreeUtil.getParentOfType(redundantCall, PsiMethodCallExpression.class);
|
||||
if (equalsCall == null) return;
|
||||
PsiExpression qualifierBeforeChangeCase = ExpressionUtils.getEffectiveQualifier(redundantCall.getMethodExpression());
|
||||
if (qualifierBeforeChangeCase == null) return;
|
||||
CommentTracker ct = new CommentTracker();
|
||||
ct.replaceAndRestoreComments(redundantCall, qualifierBeforeChangeCase);
|
||||
ExpressionUtils.bindCallTo(equalsCall, methodToUse);
|
||||
}
|
||||
|
||||
private static class UseContentEqualsFix implements LocalQuickFix {
|
||||
|
||||
@Override
|
||||
public @NotNull String getFamilyName() {
|
||||
return InspectionGadgetsBundle.message("use.contentequals");
|
||||
}
|
||||
|
||||
@Nls(capitalization = Nls.Capitalization.Sentence)
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionGadgetsBundle.message("remove.redundant.string.fix.text", CONTENT_EQUALS, TO_STRING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiMethodCallExpression changeCaseCall = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiMethodCallExpression.class);
|
||||
if (changeCaseCall == null) return;
|
||||
useMethodInsteadOfRedundantCall(CONTENT_EQUALS, changeCaseCall);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RemoveRedundantChangeCaseFix implements LocalQuickFix {
|
||||
private final @NotNull String caseRedundant;
|
||||
private final @NotNull PlaceCaseEqualType myPlaceCaseEqualType;
|
||||
@@ -699,23 +755,13 @@ public class RedundantStringOperationInspection extends AbstractBaseJavaLocalIns
|
||||
if (changeCaseCall == null) return;
|
||||
|
||||
if (myPlaceCaseEqualType == PlaceCaseEqualType.RIGHT) {
|
||||
fixRightChangeCase(changeCaseCall);
|
||||
useMethodInsteadOfRedundantCall(EQUALS_IGNORE_CASE, changeCaseCall);
|
||||
return;
|
||||
}
|
||||
|
||||
fixLeftAndBothChangeCase(changeCaseCall);
|
||||
}
|
||||
|
||||
private static void fixRightChangeCase(PsiMethodCallExpression changeCaseCall) {
|
||||
PsiMethodCallExpression equalsCall = PsiTreeUtil.getParentOfType(changeCaseCall, PsiMethodCallExpression.class);
|
||||
if (equalsCall == null) return;
|
||||
PsiExpression qualifierBeforeChangeCase = ExpressionUtils.getEffectiveQualifier(changeCaseCall.getMethodExpression());
|
||||
if (qualifierBeforeChangeCase == null) return;
|
||||
CommentTracker ct = new CommentTracker();
|
||||
ct.replaceAndRestoreComments(changeCaseCall, qualifierBeforeChangeCase);
|
||||
ExpressionUtils.bindCallTo(equalsCall, EQUALS_IGNORE_CASE);
|
||||
}
|
||||
|
||||
private void fixLeftAndBothChangeCase(PsiMethodCallExpression changeCaseCall) {
|
||||
PsiExpression qualifierBeforeChangeCase = changeCaseCall.getMethodExpression().getQualifierExpression();
|
||||
if (qualifierBeforeChangeCase == null) return;
|
||||
|
||||
Reference in New Issue
Block a user