BoxForComparisonInspection enhanced -> UseCompareMethodInspection

Suggests to use Integer.compare(), etc. instead if ternary operator or if chain. Fixes IDEA-173766.
This commit is contained in:
Tagir Valeev
2017-06-06 17:15:35 +07:00
parent 7bf7bb730a
commit dbcddf5a4a
16 changed files with 507 additions and 177 deletions

View File

@@ -1,157 +0,0 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.psiutils.CommentTracker;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Tagir Valeev
*/
public class BoxForComparisonInspection extends BaseJavaBatchLocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
if(!PsiUtil.getLanguageLevel(holder.getFile()).isAtLeast(LanguageLevel.JDK_1_4)) {
return PsiElementVisitor.EMPTY_VISITOR;
}
return new JavaElementVisitor() {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression call) {
PsiElement nameElement = call.getMethodExpression().getReferenceNameElement();
if (nameElement == null) return;
String name = nameElement.getText();
if (!"compareTo".equals(name)) return;
PsiExpression[] args = call.getArgumentList().getExpressions();
if (args.length != 1) return;
PsiExpression arg = args[0];
PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
if (qualifier == null) return;
PsiClassType boxedType = getBoxedType(call);
if (boxedType == null) return;
PsiPrimitiveType primitiveType = PsiPrimitiveType.getUnboxedType(boxedType);
if (primitiveType == null || !PsiType.DOUBLE.equals(primitiveType) && !PsiType.FLOAT.equals(primitiveType) &&
!PsiUtil.isLanguageLevel7OrHigher(call)) {
return;
}
PsiExpression left = extractPrimitive(boxedType, primitiveType, qualifier);
if (left == null) return;
PsiExpression right = extractPrimitive(boxedType, primitiveType, arg);
if (right == null) return;
holder.registerProblem(nameElement, "Can be replaced with '" + boxedType.getClassName() + ".compare'",
new ReplaceWithPrimitiveCompareFix(boxedType.getCanonicalText()));
}
};
}
@Nullable
static PsiClassType getBoxedType(PsiMethodCallExpression call) {
PsiMethod method = call.resolveMethod();
if (method == null) return null;
PsiClass aClass = method.getContainingClass();
if (aClass == null) return null;
return JavaPsiFacade.getElementFactory(call.getProject()).createType(aClass);
}
@Nullable
static PsiExpression extractPrimitive(PsiClassType type, PsiPrimitiveType primitiveType, PsiExpression expression) {
expression = PsiUtil.skipParenthesizedExprDown(expression);
if (expression == null) return null;
if (primitiveType.equals(expression.getType())) {
return expression;
}
if (expression instanceof PsiMethodCallExpression) {
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
if (!"valueOf".equals(call.getMethodExpression().getReferenceName())) return null;
PsiExpression[] args = call.getArgumentList().getExpressions();
if (args.length != 1) return null;
PsiMethod method = call.resolveMethod();
if (method == null || type.resolve() != method.getContainingClass()) return null;
return checkPrimitive(args[0]);
}
if (expression instanceof PsiTypeCastExpression) {
PsiTypeCastExpression cast = (PsiTypeCastExpression)expression;
if (!type.equals(cast.getType())) return null;
return checkPrimitive(cast.getOperand());
}
if (expression instanceof PsiNewExpression) {
PsiNewExpression newExpression = (PsiNewExpression)expression;
if (!type.equals(newExpression.getType())) return null;
PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) return null;
PsiExpression[] args = argumentList.getExpressions();
if (args.length != 1) return null;
if (!(args[0].getType() instanceof PsiPrimitiveType)) return null;
return checkPrimitive(args[0]);
}
return null;
}
private static PsiExpression checkPrimitive(PsiExpression expression) {
return expression != null && expression.getType() instanceof PsiPrimitiveType ? expression : null;
}
private static class ReplaceWithPrimitiveCompareFix implements LocalQuickFix {
private String myClassName;
public ReplaceWithPrimitiveCompareFix(String className) {
myClassName = className;
}
@Nls
@NotNull
@Override
public String getName() {
return "Replace with '" + StringUtil.getShortName(myClassName) + ".compare'";
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "Replace with static 'compare' method";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiMethodCallExpression.class);
if (call == null) return;
PsiClassType boxedType = getBoxedType(call);
if (boxedType == null) return;
PsiPrimitiveType primitiveType = PsiPrimitiveType.getUnboxedType(boxedType);
if (primitiveType == null) return;
PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
if (qualifier == null) return;
PsiExpression[] args = call.getArgumentList().getExpressions();
if (args.length != 1) return;
PsiExpression left = extractPrimitive(boxedType, primitiveType, qualifier);
if (left == null) return;
PsiExpression right = extractPrimitive(boxedType, primitiveType, args[0]);
if (right == null) return;
CommentTracker ct = new CommentTracker();
ct.replaceAndRestoreComments(call, boxedType.getCanonicalText() + ".compare(" + ct.text(left) + "," + ct.text(right) + ")");
}
}
}

View File

@@ -0,0 +1,380 @@
/*
* Copyright 2000-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.codeInspection;
import com.intellij.codeInsight.PsiEquivalenceUtil;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.*;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.psi.util.PsiUtil;
import com.siyeh.ig.psiutils.CommentTracker;
import com.siyeh.ig.psiutils.ControlFlowUtils;
import com.siyeh.ig.psiutils.ExpressionUtils;
import one.util.streamex.StreamEx;
import org.jetbrains.annotations.Contract;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static com.intellij.util.ObjectUtils.tryCast;
/**
* @author Tagir Valeev
*/
public class UseCompareMethodInspection extends BaseJavaBatchLocalInspectionTool {
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
if (!PsiUtil.getLanguageLevel(holder.getFile()).isAtLeast(LanguageLevel.JDK_1_4)) {
return PsiElementVisitor.EMPTY_VISITOR;
}
return new JavaElementVisitor() {
@Override
public void visitMethodCallExpression(PsiMethodCallExpression call) {
CompareInfo info = fromCall(call);
PsiElement nameElement = call.getMethodExpression().getReferenceNameElement();
if (info != null && nameElement != null) {
register(info, nameElement);
}
}
@Override
public void visitIfStatement(PsiIfStatement statement) {
CompareInfo info = fromIf(statement);
PsiElement keyword = statement.getFirstChild();
if (info != null && keyword != null) {
register(info, keyword);
}
}
@Override
public void visitConditionalExpression(PsiConditionalExpression expression) {
CompareInfo info = fromTernary(expression);
if (info != null) {
register(info, expression);
}
}
private void register(CompareInfo info, PsiElement nameElement) {
holder.registerProblem(nameElement, "Can be replaced with '" + info.myClass.getClassName() + ".compare'",
new ReplaceWithPrimitiveCompareFix(info.myClass.getCanonicalText()));
}
};
}
private static CompareInfo fromIf(PsiIfStatement ifStatement) {
PsiExpression firstCondition = ifStatement.getCondition();
if (firstCondition == null) return null;
PsiIfStatement elseIfStatement = tryCast(getElse(ifStatement), PsiIfStatement.class);
if (elseIfStatement == null) return null;
PsiExpression secondCondition = elseIfStatement.getCondition();
if (secondCondition == null) return null;
PsiStatement firstStatement = ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
if (firstStatement == null) return null;
PsiStatement secondStatement = ControlFlowUtils.stripBraces(elseIfStatement.getThenBranch());
if (secondStatement == null) return null;
PsiStatement thirdStatement = getElse(elseIfStatement);
if (thirdStatement == null) return null;
Map<Integer, PsiExpression> result = new HashMap<>(3);
// like if(...) return 1; else if(...) return -1; return 0;
if (firstStatement instanceof PsiReturnStatement) {
if (!(secondStatement instanceof PsiReturnStatement) || !(thirdStatement instanceof PsiReturnStatement)) return null;
PsiExpression firstValue = ((PsiReturnStatement)firstStatement).getReturnValue();
if (!storeCondition(result, firstCondition, firstValue)) return null;
if (!storeCondition(result, secondCondition, ((PsiReturnStatement)secondStatement).getReturnValue())) return null;
if (!storeCondition(result, null, ((PsiReturnStatement)thirdStatement).getReturnValue())) return null;
return fromMap(result, firstValue, firstStatement);
}
// like if(...) x = 1; else if(...) x = -1; else x = 0;
PsiAssignmentExpression assignment = ExpressionUtils.getAssignment(firstStatement);
if (assignment == null) return null;
PsiReferenceExpression ref = tryCast(assignment.getLExpression(), PsiReferenceExpression.class);
if (ref == null) return null;
PsiVariable variable = tryCast(ref.resolve(), PsiVariable.class);
if (variable == null) return null;
PsiExpression firstExpression = assignment.getRExpression();
if (!storeCondition(result, firstCondition, firstExpression)) return null;
if (!storeCondition(result, secondCondition, ExpressionUtils.getAssignmentTo(secondStatement, variable))) return null;
if (!storeCondition(result, null, ExpressionUtils.getAssignmentTo(thirdStatement, variable))) return null;
return fromMap(result, firstExpression, assignment);
}
private static PsiStatement getElse(PsiIfStatement ifStatement) {
PsiStatement branch = ControlFlowUtils.stripBraces(ifStatement.getElseBranch());
if (branch != null) return branch;
PsiStatement thenBranch = ControlFlowUtils.stripBraces(ifStatement.getThenBranch());
if (!(thenBranch instanceof PsiReturnStatement)) return null;
PsiElement next = PsiTreeUtil.skipSiblingsForward(ifStatement, PsiComment.class, PsiWhiteSpace.class);
return tryCast(next, PsiStatement.class);
}
@Nullable
private static Map<Integer, PsiExpression> extractConditions(PsiConditionalExpression ternary) {
Map<Integer, PsiExpression> result = new HashMap<>(3);
if (!storeCondition(result, ternary.getCondition(), ternary.getThenExpression())) return null;
PsiExpression elseExpression = PsiUtil.skipParenthesizedExprDown(ternary.getElseExpression());
if (elseExpression instanceof PsiConditionalExpression) {
Map<Integer, PsiExpression> m = extractConditions((PsiConditionalExpression)elseExpression);
if (m == null) return null;
result.putAll(m);
return result;
}
return storeCondition(result, null, elseExpression) ? result : null;
}
@Contract("_, _, null -> false")
private static boolean storeCondition(@NotNull Map<Integer, PsiExpression> result,
@Nullable PsiExpression condition,
@Nullable PsiExpression expression) {
if (expression == null) return false;
Object thenValue = ExpressionUtils.computeConstantExpression(expression);
if (!(thenValue instanceof Integer) || Math.abs((Integer)thenValue) > 1) return false;
result.put((Integer)thenValue, condition);
return true;
}
private static CompareInfo fromTernary(PsiConditionalExpression ternary) {
if (!PsiType.INT.equals(ternary.getType())) return null;
Map<Integer, PsiExpression> map = extractConditions(ternary);
return fromMap(map, ternary, ternary);
}
private static CompareInfo fromMap(@Nullable Map<Integer, PsiExpression> map,
@NotNull PsiExpression expression,
@NotNull PsiElement template) {
if (map == null || map.size() != 3) {
return null;
}
PsiExpression lt = map.get(-1);
Pair<PsiExpression, PsiExpression> ltPair = getOperands(lt, JavaTokenType.LT);
if (lt != null && ltPair == null) return null;
PsiExpression gt = map.get(1);
Pair<PsiExpression, PsiExpression> gtPair = getOperands(gt, JavaTokenType.GT);
if ((gt != null || ltPair == null) && gtPair == null) return null;
if (ltPair != null && gtPair != null) {
if (!PsiEquivalenceUtil.areElementsEquivalent(ltPair.getFirst(), gtPair.getFirst())) return null;
if (!PsiEquivalenceUtil.areElementsEquivalent(ltPair.getSecond(), gtPair.getSecond())) return null;
}
Pair<PsiExpression, PsiExpression> canonicalPair = ltPair == null ? gtPair : ltPair;
PsiType leftType = canonicalPair.getFirst().getType();
PsiType rightType = canonicalPair.getSecond().getType();
if (!isTypeConvertible(leftType, expression) || !leftType.equals(rightType)) return null;
PsiExpression eq = map.get(0);
Pair<PsiExpression, PsiExpression> eqPair = getOperands(eq, JavaTokenType.EQEQ);
if (eq != null && eqPair == null) return null;
if (eqPair != null) {
if ((!PsiEquivalenceUtil.areElementsEquivalent(canonicalPair.getFirst(), eqPair.getFirst()) ||
!PsiEquivalenceUtil.areElementsEquivalent(canonicalPair.getSecond(), eqPair.getSecond())) &&
(!PsiEquivalenceUtil.areElementsEquivalent(canonicalPair.getFirst(), eqPair.getSecond()) ||
!PsiEquivalenceUtil.areElementsEquivalent(canonicalPair.getSecond(), eqPair.getFirst()))) {
return null;
}
}
PsiClassType boxedType = ((PsiPrimitiveType)leftType).getBoxedType(expression);
return new CompareInfo(template, expression, canonicalPair.getFirst(), canonicalPair.getSecond(), boxedType);
}
private static Pair<PsiExpression, PsiExpression> getOperands(PsiExpression expression, IElementType expectedToken) {
expression = PsiUtil.skipParenthesizedExprDown(expression);
if (!(expression instanceof PsiBinaryExpression)) return null;
PsiBinaryExpression binOp = (PsiBinaryExpression)expression;
PsiExpression left = PsiUtil.skipParenthesizedExprDown(binOp.getLOperand());
PsiExpression right = PsiUtil.skipParenthesizedExprDown(binOp.getROperand());
if (left == null || right == null) return null;
if (binOp.getOperationTokenType().equals(expectedToken)) {
return Pair.create(left, right);
}
if (expectedToken.equals(JavaTokenType.GT) && binOp.getOperationTokenType().equals(JavaTokenType.LT) ||
expectedToken.equals(JavaTokenType.LT) && binOp.getOperationTokenType().equals(JavaTokenType.GT)) {
return Pair.create(right, left);
}
return null;
}
@Nullable
static PsiClassType getBoxedType(PsiMethodCallExpression call) {
PsiMethod method = call.resolveMethod();
if (method == null) return null;
PsiClass aClass = method.getContainingClass();
if (aClass == null) return null;
return JavaPsiFacade.getElementFactory(call.getProject()).createType(aClass);
}
@Nullable
static PsiExpression extractPrimitive(PsiClassType type, PsiPrimitiveType primitiveType, PsiExpression expression) {
expression = PsiUtil.skipParenthesizedExprDown(expression);
if (expression == null) return null;
if (primitiveType.equals(expression.getType())) {
return expression;
}
if (expression instanceof PsiMethodCallExpression) {
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
if (!"valueOf".equals(call.getMethodExpression().getReferenceName())) return null;
PsiExpression[] args = call.getArgumentList().getExpressions();
if (args.length != 1) return null;
PsiMethod method = call.resolveMethod();
if (method == null || type.resolve() != method.getContainingClass()) return null;
return checkPrimitive(args[0]);
}
if (expression instanceof PsiTypeCastExpression) {
PsiTypeCastExpression cast = (PsiTypeCastExpression)expression;
if (!type.equals(cast.getType())) return null;
return checkPrimitive(cast.getOperand());
}
if (expression instanceof PsiNewExpression) {
PsiNewExpression newExpression = (PsiNewExpression)expression;
if (!type.equals(newExpression.getType())) return null;
PsiExpressionList argumentList = newExpression.getArgumentList();
if (argumentList == null) return null;
PsiExpression[] args = argumentList.getExpressions();
if (args.length != 1) return null;
if (!(args[0].getType() instanceof PsiPrimitiveType)) return null;
return checkPrimitive(args[0]);
}
return null;
}
private static PsiExpression checkPrimitive(PsiExpression expression) {
return expression != null && expression.getType() instanceof PsiPrimitiveType ? expression : null;
}
static class CompareInfo {
final PsiElement myTemplate;
final PsiExpression myToReplace;
final PsiExpression myLeft;
final PsiExpression myRight;
final PsiClassType myClass;
CompareInfo(PsiElement template,
PsiExpression toReplace,
PsiExpression left,
PsiExpression right,
PsiClassType aClass) {
myTemplate = template;
myToReplace = toReplace;
myLeft = left;
myRight = right;
myClass = aClass;
}
private void replace(PsiElement toReplace, CommentTracker ct) {
String replacement = this.myClass.getCanonicalText() + ".compare(" + ct.text(this.myLeft) + "," + ct.text(this.myRight) + ")";
if(toReplace == myTemplate) {
ct.replaceAndRestoreComments(myToReplace, replacement);
} else {
ct.replace(myToReplace, replacement);
ct.replaceAndRestoreComments(toReplace, myTemplate);
}
}
}
@Contract("null -> null")
private static CompareInfo fromCall(PsiMethodCallExpression call) {
if (call == null) return null;
PsiElement nameElement = call.getMethodExpression().getReferenceNameElement();
if (nameElement == null) return null;
String name = nameElement.getText();
if (!"compareTo".equals(name)) return null;
PsiExpression[] args = call.getArgumentList().getExpressions();
if (args.length != 1) return null;
PsiExpression arg = args[0];
PsiExpression qualifier = call.getMethodExpression().getQualifierExpression();
if (qualifier == null) return null;
PsiClassType boxedType = getBoxedType(call);
if (boxedType == null) return null;
PsiPrimitiveType primitiveType = PsiPrimitiveType.getUnboxedType(boxedType);
if (!isTypeConvertible(primitiveType, call)) return null;
PsiExpression left = extractPrimitive(boxedType, primitiveType, qualifier);
if (left == null) return null;
PsiExpression right = extractPrimitive(boxedType, primitiveType, arg);
if (right == null) return null;
return new CompareInfo(call, call, left, right, boxedType);
}
@Contract("null, _ -> false")
private static boolean isTypeConvertible(PsiType type, PsiElement context) {
return type instanceof PsiPrimitiveType && (PsiType.DOUBLE.equals(type) ||
PsiType.FLOAT.equals(type) ||
PsiUtil.isLanguageLevel7OrHigher(context));
}
private static class ReplaceWithPrimitiveCompareFix implements LocalQuickFix {
private String myClassName;
public ReplaceWithPrimitiveCompareFix(String className) {
myClassName = className;
}
@Nls
@NotNull
@Override
public String getName() {
return "Replace with '" + StringUtil.getShortName(myClassName) + ".compare'";
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "Replace with static 'compare' method";
}
@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
PsiElement element = descriptor.getStartElement();
PsiElement toReplace;
List<PsiElement> toDelete = new ArrayList<>();
CompareInfo info;
if (element instanceof PsiConditionalExpression) {
toReplace = element;
info = fromTernary((PsiConditionalExpression)element);
}
else {
PsiElement parent = element.getParent();
if (parent instanceof PsiIfStatement) {
toReplace = parent;
info = fromIf((PsiIfStatement)parent);
PsiStatement elseIf = getElse((PsiIfStatement)parent);
toDelete.add(elseIf);
if(elseIf instanceof PsiIfStatement) {
toDelete.add(getElse((PsiIfStatement)elseIf));
}
} else {
PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(element, PsiMethodCallExpression.class);
info = fromCall(call);
toReplace = call;
}
}
if (info == null) return;
CommentTracker ct = new CommentTracker();
info.replace(toReplace, ct);
StreamEx.of(toDelete).nonNull().filter(PsiElement::isValid).forEach(e -> new CommentTracker().deleteAndRestoreComments(e));
}
}
}

View File

@@ -1,4 +1,4 @@
// "Fix all 'Unnecessary boxing to compare primitives' problems in file" "true"
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
public class Test {
public void test(int a, int b) {
if(Integer.compare(a, b) > 0) {

View File

@@ -1,4 +1,4 @@
// "Fix all 'Unnecessary boxing to compare primitives' problems in file" "true"
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
public class Test {
public int test(String s1, String s2) {
int res = Integer.compare(s1.length(), s2.length());

View File

@@ -0,0 +1,16 @@
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
class Test {
public void test(String s1, String s2) {
int res;
res = Integer.compare(s2.length(), s1.length())
System.out.println(res);
}
public void testMissingElse(String s1, String s2) {
int res;
if(s1.length() < s2.length()) res = 1;
else if(s1.length() > s2.length()) res = -1;
res = 0;
System.out.println(res);
}
}

View File

@@ -0,0 +1,17 @@
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
class Test {
public int test(String s1, String s2) {
return Integer.compare(s1.length(), s2.length());
/*otherwise bigger*/
}
public int test2(String s1, String s2) {
return Integer.compare(s2.length(), s1.length());
}
public int test3(String s1, String s2) {
if(s1.length() > s2.length()) return -1;
else if(s2.length() > s1.length()) return -1;
else return 0;
}
}

View File

@@ -0,0 +1,18 @@
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
public class Test {
public void test(String s1, String s2) {
System.out.println(Integer.compare(s1.length(), s2.length()));
System.out.println(Integer.compare(s2.length(), s1.length()));
/*greater!*/
/*less!*/
/*equal!*/
System.out.println(Integer.compare(s1.length(), s2.length()));
System.out.println(Integer.compare(s2.length(), s1.length()));
System.out.println(Integer.compare(s2.length(), s1.length()));
System.out.println(s1.length() < s2.length() ? -1 : s1.length() == s2.length() ? 0 : 2);
System.out.println(s1.length() < s2.length() ? 1 : s2.length() < s1.length() ? 0 : 1);
System.out.println(s1.length() == s2.length() ? 1 : s2.length() < s1.length() ? 0 : 1);
System.out.println(s1.length() == s2.length() ? 0 : s2.length() < s2.length() ? -1 : 1);
}
}

View File

@@ -1,4 +1,4 @@
// "Fix all 'Unnecessary boxing to compare primitives' problems in file" "true"
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
public class Test {
public void test(int a, int b) {
if(((Integer)a).compa<caret>reTo(b) > 0) {

View File

@@ -1,4 +1,4 @@
// "Fix all 'Unnecessary boxing to compare primitives' problems in file" "true"
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
public class Test {
public int test(String s1, String s2) {
int res = new Integer(s1.length()).co<caret>mpareTo(s2.length());

View File

@@ -0,0 +1,18 @@
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
class Test {
public void test(String s1, String s2) {
int res;
i<caret>f(s1.length() < s2.length()) res = 1;
else if(s1.length() > s2.length()) res = -1;
else res = 0;
System.out.println(res);
}
public void testMissingElse(String s1, String s2) {
int res;
if(s1.length() < s2.length()) res = 1;
else if(s1.length() > s2.length()) res = -1;
res = 0;
System.out.println(res);
}
}

View File

@@ -0,0 +1,22 @@
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
class Test {
public int test(String s1, String s2) {
if(s1.length() < s2.length()) {
return -1;
}
if((s1.length()) == s2.length()) return 0;
else /*otherwise bigger*/ return +1;
}
public int test2(String s1, String s2) {
i<caret>f(s1.length() > s2.length()) return -1;
else if(s2.length() > s1.length()) return 1;
else return 0;
}
public int test3(String s1, String s2) {
if(s1.length() > s2.length()) return -1;
else if(s2.length() > s1.length()) return -1;
else return 0;
}
}

View File

@@ -0,0 +1,15 @@
// "Fix all ''compare()' method can be used to compare primitives' problems in file" "true"
public class Test {
public void test(String s1, String s2) {
System.out.println(s1.<caret>length() < s2.length() ? -1 : s1.length() == s2.length() ? 0 : 1);
System.out.println((s1.length() > s2.length()) ? -1 : s1.length() == s2.length() ? 0 : 1);
System.out.println((s1.length() > s2.length()) ? /*greater!*/+1 : s1.length() < s2.length() ? /*less!*/-1 : /*equal!*/0);
System.out.println(s1.length() == s2.length() ? 0 : s2.length() < s1.length() ? -1 : 1);
System.out.println(s1.length() < s2.length() ? 1 : s2.length() < s1.length() ? -1 : 0);
System.out.println(s1.length() < s2.length() ? -1 : s1.length() == s2.length() ? 0 : 2);
System.out.println(s1.length() < s2.length() ? 1 : s2.length() < s1.length() ? 0 : 1);
System.out.println(s1.length() == s2.length() ? 1 : s2.length() < s1.length() ? 0 : 1);
System.out.println(s1.length() == s2.length() ? 0 : s2.length() < s2.length() ? -1 : 1);
}
}

View File

@@ -16,17 +16,17 @@
package com.intellij.java.codeInsight.daemon.quickFix;
import com.intellij.codeInsight.daemon.quickFix.LightQuickFixParameterizedTestCase;
import com.intellij.codeInspection.BoxForComparisonInspection;
import com.intellij.codeInspection.LocalInspectionTool;
import com.intellij.codeInspection.UseCompareMethodInspection;
import org.jetbrains.annotations.NotNull;
public class BoxForComparisonInspectionTest extends LightQuickFixParameterizedTestCase {
public class UseCompareMethodInspectionTest extends LightQuickFixParameterizedTestCase {
@NotNull
@Override
protected LocalInspectionTool[] configureLocalInspectionTools() {
return new LocalInspectionTool[]{
new BoxForComparisonInspection(),
new UseCompareMethodInspection(),
};
}
@@ -34,6 +34,6 @@ public class BoxForComparisonInspectionTest extends LightQuickFixParameterizedTe
@Override
protected String getBasePath() {
return "/codeInsight/daemonCodeAnalyzer/quickFix/boxForComparison";
return "/codeInsight/daemonCodeAnalyzer/quickFix/useCompareMethod";
}
}

View File

@@ -1,10 +0,0 @@
<html>
<body>
<p>This inspection suggests to use <code>Integer.compare()</code>, etc. static methods where
constructs involving boxing <code>Integer.valueOf(x).compareTo(y)</code> are used.</p>
<p><code>Double.compare</code> and <code>Float.compare</code> methods appeared in Java 1.4, methods for other boxed types
are available since Java 1.7</p>
<!-- tooltip end -->
<p><small>New in 2017.2</small></p>
</body>
</html>

View File

@@ -0,0 +1,11 @@
<html>
<body>
<p>This inspection suggests to use <code>Integer.compare()</code>, etc. static methods where more verbose or less efficient constructs are
used. For example, <code>x &gt; y ? 1 : x &lt; y ? -1 : 0</code> or <code>Integer.valueOf(x).compareTo(y)</code> could be
replaced with <code>Integer.compare(x, y)</code>.</p>
<p><code>Double.compare</code> and <code>Float.compare</code> methods appeared in Java 1.4, methods for other primitive types
are available since Java 1.7</p>
<!-- tooltip end -->
<p><small>New in 2017.2</small></p>
</body>
</html>

View File

@@ -769,9 +769,9 @@
<localInspection groupPath="Java" language="JAVA" shortName="UnknownGuard" displayName="Unknown @GuardedBy field" groupKey="group.names.concurrency.annotation.issues" groupBundle="messages.InspectionsBundle"
enabledByDefault="false" level="WARNING"
implementationClass="com.intellij.codeInspection.concurrencyAnnotations.UnknownGuardInspection" />
<localInspection groupPath="Java" language="JAVA" shortName="BoxForComparison" displayName="Unnecessary boxing to compare primitives"
<localInspection groupPath="Java" language="JAVA" shortName="UseCompareMethod" displayName="'compare()' method can be used to compare primitives"
groupKey="group.names.language.level.specific.issues.and.migration.aids" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
implementationClass="com.intellij.codeInspection.BoxForComparisonInspection" />
implementationClass="com.intellij.codeInspection.UseCompareMethodInspection" />
<localInspection groupPath="Java" language="JAVA" shortName="ComparatorResultComparison"
bundle="messages.InspectionsBundle" key="inspection.comparator.result.comparison.display.name"
groupKey="group.names.probable.bugs" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"