diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java b/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java index d72595d6dffa..0b73ee585d83 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/ComparatorCombinatorsInspection.java @@ -24,6 +24,7 @@ import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.codeStyle.SuggestedNameInfo; import com.intellij.psi.codeStyle.VariableKind; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiTypesUtil; import com.siyeh.ig.psiutils.EquivalenceChecker; import com.siyeh.ig.psiutils.MethodCallUtils; import one.util.streamex.StreamEx; @@ -82,18 +83,7 @@ public class ComparatorCombinatorsInspection extends BaseJavaBatchLocalInspectio if (args.length == 2 && method != null && method.getName().equals("compare")) { PsiClass compareClass = method.getContainingClass(); if (compareClass != null) { - if (CommonClassNames.JAVA_LANG_DOUBLE.equals(compareClass.getQualifiedName())) { - methodName = "comparingDouble"; - } - else if (CommonClassNames.JAVA_LANG_INTEGER.equals(compareClass.getQualifiedName())) { - methodName = "comparingInt"; - } - else if (CommonClassNames.JAVA_LANG_LONG.equals(compareClass.getQualifiedName())) { - methodName = "comparingLong"; - } - else { - return; - } + methodName = getComparingMethodName(compareClass.getQualifiedName()); if (!areEquivalent(parameters, args[0], args[1])) return; } } @@ -102,7 +92,9 @@ public class ComparatorCombinatorsInspection extends BaseJavaBatchLocalInspectio PsiBinaryExpression binOp = (PsiBinaryExpression)body; if (binOp.getOperationTokenType().equals(JavaTokenType.MINUS) && areEquivalent(parameters, binOp.getLOperand(), binOp.getROperand())) { - methodName = "comparingInt"; + PsiType opType = binOp.getLOperand().getType(); + if(opType == null) return; + methodName = getComparingMethodName(opType.getCanonicalText()); } } if (methodName != null) { @@ -114,6 +106,24 @@ public class ComparatorCombinatorsInspection extends BaseJavaBatchLocalInspectio }; } + @Contract(value = "null -> null", pure = true) + @Nullable + private static String getComparingMethodName(String type) { + if(type == null) return null; + switch(PsiTypesUtil.unboxIfPossible(type)) { + case "int": + case "short": + case "byte": + case "char": + return "comparingInt"; + case "long": + return "comparingLong"; + case "double": + return "comparingDouble"; + } + return null; + } + @Contract("_, null, _ -> false; _, !null, null -> false") private static boolean areEquivalent(@NotNull PsiParameter[] parameters, @Nullable PsiExpression left, @Nullable PsiExpression right) { if (left == null || right == null) return false; @@ -193,19 +203,7 @@ public class ComparatorCombinatorsInspection extends BaseJavaBatchLocalInspectio PsiExpression[] args = methodCall.getArgumentList().getExpressions(); if (args.length != 2) return; keyExtractor = args[0]; - switch (className) { - case CommonClassNames.JAVA_LANG_LONG: - methodName = "comparingLong"; - break; - case CommonClassNames.JAVA_LANG_INTEGER: - methodName = "comparingInt"; - break; - case CommonClassNames.JAVA_LANG_DOUBLE: - methodName = "comparingDouble"; - break; - default: - return; - } + methodName = getComparingMethodName(className); } } } @@ -213,8 +211,10 @@ public class ComparatorCombinatorsInspection extends BaseJavaBatchLocalInspectio } else if(body instanceof PsiBinaryExpression) { PsiBinaryExpression binOp = (PsiBinaryExpression)body; if(!binOp.getOperationTokenType().equals(JavaTokenType.MINUS)) return; - methodName = "comparingInt"; keyExtractor = binOp.getLOperand(); + PsiType type = keyExtractor.getType(); + if(type == null) return; + methodName = getComparingMethodName(type.getCanonicalText()); } if (methodName == null || keyExtractor == null) return; if (!FileModificationService.getInstance().preparePsiElementForWrite(element)) return; diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java index 52e19c965b16..1e5c492976ce 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiTypesUtil.java @@ -24,6 +24,7 @@ import com.intellij.psi.*; import com.intellij.psi.tree.IElementType; import com.intellij.util.ArrayUtil; import gnu.trove.THashMap; +import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -94,6 +95,7 @@ public class PsiTypesUtil { * @param type boxed java type name * @return unboxed type name if available; same value otherwise */ + @Contract("null -> null; !null -> !null") @Nullable public static String unboxIfPossible(final String type) { if (type == null) return null; @@ -106,6 +108,7 @@ public class PsiTypesUtil { * @param type primitive java type name * @return boxed type name if available; same value otherwise */ + @Contract("null -> null; !null -> !null") @Nullable public static String boxIfPossible(final String type) { if (type == null) return null; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterByte.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterByte.java new file mode 100644 index 000000000000..e6ea3a55b52b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterByte.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort(Comparator.comparingInt(d -> d.b)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterByteDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterByteDiff.java new file mode 100644 index 000000000000..e6ea3a55b52b --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterByteDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort(Comparator.comparingInt(d -> d.b)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterCharDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterCharDiff.java new file mode 100644 index 000000000000..b4156dbcfbf1 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterCharDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort(Comparator.comparingInt(d -> d.c)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterCharacterDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterCharacterDiff.java new file mode 100644 index 000000000000..5209fde258cf --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterCharacterDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + Short s; + Byte b; + Character c; + Integer i; + Long l; + Double d; + } + + void sort(List data) { + data.sort(Comparator.comparingInt(d -> d.c)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterDoubleDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterDoubleDiff.java new file mode 100644 index 000000000000..0af96afd3f09 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterDoubleDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingDouble" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort(Comparator.comparingDouble(d -> d.d)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterLongDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterLongDiff.java new file mode 100644 index 000000000000..739c87b63c4d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/afterLongDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingLong" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort(Comparator.comparingLong(d -> d.l)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeByte.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeByte.java new file mode 100644 index 000000000000..4f2a9cb5016d --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeByte.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort((d1, d2) -> Byte.compare(d1.b, d2.b)); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeByteDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeByteDiff.java new file mode 100644 index 000000000000..0f77c15895fd --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeByteDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort((d1, d2) -> d1.b - d2.b); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeCharDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeCharDiff.java new file mode 100644 index 000000000000..37a34d63ff11 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeCharDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort((d1, d2) -> d1.c - d2.c); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeCharacterDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeCharacterDiff.java new file mode 100644 index 000000000000..45e9e607be98 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeCharacterDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingInt" "true" + +import java.util.*; + +public class Main { + static class Data { + Short s; + Byte b; + Character c; + Integer i; + Long l; + Double d; + } + + void sort(List data) { + data.sort((d1, d2) -> d1.c - d2.c); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeDoubleDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeDoubleDiff.java new file mode 100644 index 000000000000..7f88cdab62a9 --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeDoubleDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingDouble" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort((d1, d2) -> d1.d - d2.d); + } +} diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeLongDiff.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeLongDiff.java new file mode 100644 index 000000000000..39e3faf7071a --- /dev/null +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/comparatorCombinators/beforeLongDiff.java @@ -0,0 +1,18 @@ +// "Replace with Comparator.comparingLong" "true" + +import java.util.*; + +public class Main { + static class Data { + short s; + byte b; + char c; + int i; + long l; + double d; + } + + void sort(List data) { + data.sort((d1, d2) -> d1.l - d2.l); + } +}