From d83875ca889651bbf953fdc60a184552e0a6befe Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Mon, 12 Feb 2018 17:02:21 +0100 Subject: [PATCH] IG: use isEmpty() if available (IDEA-186484) --- .../siyeh/InspectionGadgetsBundle.properties | 2 +- .../SingleCharacterStartsWithInspection.java | 58 +++++++++---------- .../UseIsEmptyMethod.after.java | 6 ++ .../UseIsEmptyMethod.java | 6 ++ .../UseLengthMethod.after.java | 6 ++ .../UseLengthMethod.java | 6 ++ .../SingleCharacterStartsWithLengthTest.kt | 34 +++++++++++ 7 files changed, 87 insertions(+), 31 deletions(-) create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.after.java create mode 100644 plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.java create mode 100644 plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/j2me/SingleCharacterStartsWithLengthTest.kt diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties index 772bb038de76..0a5dec378b4c 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/InspectionGadgetsBundle.properties @@ -1397,7 +1397,7 @@ format.decode.date.time=Date/Time format.decode.char=char format.decode.integer.type=integer type format.decode.floating.point=floating point -single.character.startswith.quickfix=Replace with 'charAt()' +single.character.startswith.quickfix=Replace with 'charAt()' expression interface.never.implemented.option=Ignore interfaces which only declare constants size.replaceable.by.isempty.display.name='size() == 0' replaceable with 'isEmpty()' size.replaceable.by.isempty.quickfix=Replace with 'isEmpty()' diff --git a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java index 1f43425d4bfd..ce52c33282d4 100644 --- a/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java +++ b/plugins/InspectionGadgets/InspectionGadgetsAnalysis/src/com/siyeh/ig/j2me/SingleCharacterStartsWithInspection.java @@ -24,6 +24,7 @@ import com.siyeh.ig.BaseInspection; import com.siyeh.ig.BaseInspectionVisitor; import com.siyeh.ig.InspectionGadgetsFix; import com.siyeh.ig.PsiReplacementUtil; +import com.siyeh.ig.psiutils.ClassUtils; import com.siyeh.ig.psiutils.CommentTracker; import com.siyeh.ig.psiutils.TypeUtils; import org.jetbrains.annotations.NonNls; @@ -52,8 +53,7 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { return new SingleCharacterStartsWithFix(); } - private static class SingleCharacterStartsWithFix - extends InspectionGadgetsFix { + private static class SingleCharacterStartsWithFix extends InspectionGadgetsFix { @Override @NotNull @@ -65,10 +65,8 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { @Override protected void doFix(Project project, ProblemDescriptor descriptor) { final PsiElement element = descriptor.getPsiElement(); - final PsiReferenceExpression methodExpression = - (PsiReferenceExpression)element.getParent(); - final PsiMethodCallExpression methodCall = - (PsiMethodCallExpression)methodExpression.getParent(); + final PsiReferenceExpression methodExpression = (PsiReferenceExpression)element.getParent(); + final PsiMethodCallExpression methodCall = (PsiMethodCallExpression)methodExpression.getParent(); final PsiElement qualifier = methodExpression.getQualifier(); if (qualifier == null) { return; @@ -77,26 +75,33 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { final PsiExpression[] expressions = argumentList.getExpressions(); final PsiExpression expression = expressions[0]; final String expressionText = expression.getText(); - String character = expressionText.substring(1, - expressionText.length() - 1); + String character = expressionText.substring(1, expressionText.length() - 1); if (character.equals("'")) { character = "\\'"; } final String qualifierText = qualifier.getText(); - @NonNls final String newExpression; - final String referenceName = methodExpression.getReferenceName(); - if (HardcodedMethodConstants.STARTS_WITH.equals(referenceName)) { - newExpression = qualifierText + ".length() > 0 && " + - qualifierText + ".charAt(0) == '" + character + '\''; + @NonNls final StringBuilder newExpression = new StringBuilder(); + final PsiClass stringClass = ClassUtils.findClass(CommonClassNames.JAVA_LANG_STRING, qualifier); + // String.isEmpty() was introduced in Java 6 + final PsiMethod[] isEmptyMethod = (stringClass == null) ? PsiMethod.EMPTY_ARRAY : stringClass.findMethodsByName("isEmpty", false); + if (isEmptyMethod.length > 0) { + newExpression.append("!").append(qualifierText).append(".isEmpty() && "); } else { - newExpression = qualifierText + ".length() > 0 && " + - qualifierText + ".charAt(" + qualifierText + - ".length() - 1) == '" + character + '\''; + newExpression.append(qualifierText).append(".length() > 0 && "); } - CommentTracker commentTracker = new CommentTracker(); + final String referenceName = methodExpression.getReferenceName(); + newExpression.append(qualifierText).append(".charAt("); + if (HardcodedMethodConstants.STARTS_WITH.equals(referenceName)) { + newExpression.append("0) == '"); + } + else { + newExpression.append(qualifierText).append(".length() - 1) == '"); + } + newExpression.append(character).append('\''); + final CommentTracker commentTracker = new CommentTracker(); commentTracker.markUnchanged(qualifier); - PsiReplacementUtil.replaceExpression(methodCall, newExpression, commentTracker); + PsiReplacementUtil.replaceExpression(methodCall, newExpression.toString(), commentTracker); } } @@ -109,11 +114,9 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { extends BaseInspectionVisitor { @Override - public void visitMethodCallExpression( - @NotNull PsiMethodCallExpression call) { + public void visitMethodCallExpression(@NotNull PsiMethodCallExpression call) { super.visitMethodCallExpression(call); - final PsiReferenceExpression methodExpression = - call.getMethodExpression(); + final PsiReferenceExpression methodExpression = call.getMethodExpression(); final String methodName = methodExpression.getReferenceName(); if (!HardcodedMethodConstants.STARTS_WITH.equals(methodName) && !HardcodedMethodConstants.ENDS_WITH.equals(methodName)) { @@ -127,8 +130,7 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { if (!isSingleCharacterStringLiteral(args[0])) { return; } - final PsiExpression qualifier = - methodExpression.getQualifierExpression(); + final PsiExpression qualifier = methodExpression.getQualifierExpression(); if (qualifier == null) { return; } @@ -139,8 +141,7 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { registerMethodCallError(call); } - private static boolean isSingleCharacterStringLiteral( - PsiExpression arg) { + private static boolean isSingleCharacterStringLiteral(PsiExpression arg) { final PsiType type = arg.getType(); if (!TypeUtils.isJavaLangString(type)) { return false; @@ -150,10 +151,7 @@ public class SingleCharacterStartsWithInspection extends BaseInspection { } final PsiLiteralExpression literal = (PsiLiteralExpression)arg; final String value = (String)literal.getValue(); - if (value == null) { - return false; - } - return value.length() == 1; + return value != null && value.length() == 1; } } } \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.after.java new file mode 100644 index 000000000000..f6c23f6d567e --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.after.java @@ -0,0 +1,6 @@ +class useisEmptyMethod { + + boolean x(String s) { + return !s.isEmpty() && s.charAt(0) == 'x'; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.java new file mode 100644 index 000000000000..fd621ef8c880 --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseIsEmptyMethod.java @@ -0,0 +1,6 @@ +class useisEmptyMethod { + + boolean x(String s) { + return s.startsWith("x"); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.after.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.after.java new file mode 100644 index 000000000000..708b2e92c77a --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.after.java @@ -0,0 +1,6 @@ +class UseLengthMethod { + + boolean x(String s) { + return s.length() > 0 && s.charAt(0) == 'x'; + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.java b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.java new file mode 100644 index 000000000000..5cbdc64e16ad --- /dev/null +++ b/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with/UseLengthMethod.java @@ -0,0 +1,6 @@ +class UseLengthMethod { + + boolean x(String s) { + return s.startsWith("x"); + } +} \ No newline at end of file diff --git a/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/j2me/SingleCharacterStartsWithLengthTest.kt b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/j2me/SingleCharacterStartsWithLengthTest.kt new file mode 100644 index 000000000000..e45a59b34373 --- /dev/null +++ b/plugins/InspectionGadgets/testsrc/com/siyeh/ig/fixes/j2me/SingleCharacterStartsWithLengthTest.kt @@ -0,0 +1,34 @@ +// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. +package com.siyeh.ig.fixes.j2me + +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase +import com.siyeh.InspectionGadgetsBundle +import com.siyeh.ig.j2me.SingleCharacterStartsWithInspection + +/** + * @author Bas Leijdekkers + */ +class SingleCharacterStartsWithLengthTest : SingleCharacterStartsWithFixTestCase() { + + fun testUseLengthMethod() = quickfixTest() + + override fun getProjectDescriptor() = JAVA_1_4 +} +class SingleCharacterStartsWithIsEmptyTest : SingleCharacterStartsWithFixTestCase() { + + fun testUseIsEmptyMethod() = quickfixTest(); + + override fun getProjectDescriptor() = JAVA_1_6 +} +open class SingleCharacterStartsWithFixTestCase : LightCodeInsightFixtureTestCase() { + + protected fun quickfixTest() { + myFixture.enableInspections(SingleCharacterStartsWithInspection()) + myFixture.configureByFile(getTestName(false) + ".java") + myFixture.testHighlighting() + myFixture.launchAction(myFixture.findSingleIntention(InspectionGadgetsBundle.message("single.character.startswith.quickfix"))) + myFixture.checkResultByFile(getTestName(false) + ".after.java") + } + + override fun getBasePath() = "/plugins/InspectionGadgets/test/com/siyeh/igfixes/j2me/single_character_starts_with" +} \ No newline at end of file