IG: use isEmpty() if available (IDEA-186484)

This commit is contained in:
Bas Leijdekkers
2018-02-12 17:23:26 +01:00
parent 6cc539f6c8
commit d83875ca88
7 changed files with 87 additions and 31 deletions
@@ -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()'
@@ -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;
}
}
}
@@ -0,0 +1,6 @@
class useisEmptyMethod {
boolean x(String s) {
return !s.isEmpty() && s.charAt(0) == 'x';
}
}
@@ -0,0 +1,6 @@
class useisEmptyMethod {
boolean x(String s) {
return s.<warning descr="Single character 'startsWith()' could be replaced with 'charAt()' expression"><caret>startsWith</warning>("x");
}
}
@@ -0,0 +1,6 @@
class UseLengthMethod {
boolean x(String s) {
return s.length() > 0 && s.charAt(0) == 'x';
}
}
@@ -0,0 +1,6 @@
class UseLengthMethod {
boolean x(String s) {
return s.<warning descr="Single character 'startsWith()' could be replaced with 'charAt()' expression"><caret>startsWith</warning>("x");
}
}
@@ -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"
}