mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-inspections] ComparatorCombinatorsInspection: add explicit lambda parameter type when necessary
Fixes IDEA-279693 Replace with Comparator.comparing leads to red code Also: improve RedundantLambdaParameterTypeInspection via isSafeLambdaReplacement GitOrigin-RevId: 8125436ff758fe3e4a770b33933a94e44be199fb
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bcb843dd8f
commit
ed28503329
+11
-8
@@ -1,6 +1,7 @@
|
||||
// Copyright 2000-2020 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.
|
||||
// Copyright 2000-2021 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.codeInspection;
|
||||
|
||||
import com.intellij.codeInspection.lambda.RedundantLambdaParameterTypeInspection;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -21,10 +22,7 @@ import com.siyeh.ig.psiutils.*;
|
||||
import one.util.streamex.StreamEx;
|
||||
import org.jetbrains.annotations.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
import static com.intellij.util.ObjectUtils.tryCast;
|
||||
|
||||
@@ -347,7 +345,8 @@ public class ComparatorCombinatorsInspection extends AbstractBaseJavaLocalInspec
|
||||
else {
|
||||
String parameterName = leftVar.getName();
|
||||
PsiTypeElement typeElement = leftVar.getTypeElement();
|
||||
String parameterDeclaration = typeElement == null ? parameterName : "(" + typeElement.getText() + " " + parameterName + ")";
|
||||
String typeText = typeElement == null ? leftVar.getType().getCanonicalText() : typeElement.getText();
|
||||
String parameterDeclaration = "(" + typeText + " " + parameterName + ")";
|
||||
text = "java.util.Comparator." + methodName + "(" +
|
||||
(parameterDeclaration + " -> " + left.getText()) + ")";
|
||||
}
|
||||
@@ -540,6 +539,7 @@ public class ComparatorCombinatorsInspection extends AbstractBaseJavaLocalInspec
|
||||
PsiLambdaExpression lambda = (PsiLambdaExpression)element;
|
||||
PsiParameter[] parameters = lambda.getParameterList().getParameters();
|
||||
if (parameters.length != 2) return;
|
||||
boolean keepParameterTypes = parameters[0].getTypeElement() != null;
|
||||
if (lambda.getBody() instanceof PsiCodeBlock) {
|
||||
PsiStatement[] statements = ((PsiCodeBlock)lambda.getBody()).getStatements();
|
||||
if(statements.length > 1) {
|
||||
@@ -559,11 +559,11 @@ public class ComparatorCombinatorsInspection extends AbstractBaseJavaLocalInspec
|
||||
PsiElementFactory factory = JavaPsiFacade.getElementFactory(project);
|
||||
PsiExpression replacement = factory.createExpressionFromText(text, element);
|
||||
PsiMethodCallExpression result = (PsiMethodCallExpression)lambda.replace(replacement);
|
||||
normalizeLambda(ArrayUtil.getFirstElement(result.getArgumentList().getExpressions()), factory);
|
||||
normalizeLambda(ArrayUtil.getFirstElement(result.getArgumentList().getExpressions()), factory, keepParameterTypes);
|
||||
CodeStyleManager.getInstance(project).reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(result));
|
||||
}
|
||||
|
||||
private static void normalizeLambda(PsiExpression expression, PsiElementFactory factory) {
|
||||
private static void normalizeLambda(PsiExpression expression, PsiElementFactory factory, boolean keepParameterTypes) {
|
||||
if (!(expression instanceof PsiLambdaExpression)) return;
|
||||
PsiLambdaExpression lambda = (PsiLambdaExpression)expression;
|
||||
PsiParameter[] parameters = lambda.getParameterList().getParameters();
|
||||
@@ -578,6 +578,9 @@ public class ComparatorCombinatorsInspection extends AbstractBaseJavaLocalInspec
|
||||
.nonNull().forEach(nameElement -> nameElement.replace(factory.createIdentifier(name)));
|
||||
parameter.setName(name);
|
||||
}
|
||||
if (!keepParameterTypes) {
|
||||
RedundantLambdaParameterTypeInspection.removeLambdaParameterTypesIfPossible(lambda);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
-25
@@ -8,12 +8,13 @@ import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Objects;
|
||||
|
||||
public class RedundantLambdaParameterTypeInspection extends AbstractBaseJavaLocalInspectionTool {
|
||||
public static final Logger LOG = Logger.getInstance(RedundantLambdaParameterTypeInspection.class);
|
||||
@@ -48,36 +49,34 @@ public class RedundantLambdaParameterTypeInspection extends AbstractBaseJavaLoca
|
||||
}
|
||||
if (parameters.length == 0) return false;
|
||||
final PsiType functionalInterfaceType = expression.getFunctionalInterfaceType();
|
||||
if (functionalInterfaceType != null) {
|
||||
final PsiElement lambdaParent = expression.getParent();
|
||||
if (lambdaParent instanceof PsiExpressionList) {
|
||||
final PsiElement gParent = lambdaParent.getParent();
|
||||
if (gParent instanceof PsiCallExpression && ((PsiCallExpression)gParent).getTypeArguments().length == 0) {
|
||||
final JavaResolveResult resolveResult = ((PsiCallExpression)gParent).resolveMethodGenerics();
|
||||
final PsiMethod method = (PsiMethod)resolveResult.getElement();
|
||||
if (method == null) return false;
|
||||
final int idx = LambdaUtil.getLambdaIdx((PsiExpressionList)lambdaParent, expression);
|
||||
if (idx < 0) return false;
|
||||
|
||||
PsiCallExpression copy = (PsiCallExpression)gParent.copy();
|
||||
PsiLambdaExpression lambdaToStripTypeParameters = (PsiLambdaExpression)copy.getArgumentList().getExpressions()[idx];
|
||||
for (PsiParameter parameter : lambdaToStripTypeParameters.getParameterList().getParameters()) {
|
||||
parameter.getTypeElement().delete();
|
||||
}
|
||||
|
||||
return functionalInterfaceType.equals(lambdaToStripTypeParameters.getFunctionalInterfaceType());
|
||||
}
|
||||
if (functionalInterfaceType == null) return false;
|
||||
return LambdaUtil.isSafeLambdaReplacement(expression, () -> {
|
||||
PsiLambdaExpression lambdaWithoutParameters = (PsiLambdaExpression)expression.copy();
|
||||
for (PsiParameter parameter : lambdaWithoutParameters.getParameterList().getParameters()) {
|
||||
PsiTypeElement typeElement = Objects.requireNonNull(parameter.getTypeElement());
|
||||
typeElement.delete();
|
||||
}
|
||||
return true;
|
||||
return lambdaWithoutParameters;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes lambda parameter types when possible
|
||||
*
|
||||
* @param lambdaExpression lambda expression to process
|
||||
*/
|
||||
public static void removeLambdaParameterTypesIfPossible(@NotNull PsiLambdaExpression lambdaExpression) {
|
||||
PsiParameterList list = lambdaExpression.getParameterList();
|
||||
if (isApplicable(list)) {
|
||||
removeTypes(lambdaExpression);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void removeTypes(PsiLambdaExpression lambdaExpression) {
|
||||
if (lambdaExpression != null) {
|
||||
final PsiParameter[] parameters = lambdaExpression.getParameterList().getParameters();
|
||||
if (PsiUtil.isLanguageLevel11OrHigher(lambdaExpression) &&
|
||||
Arrays.stream(parameters).anyMatch(parameter -> keepVarType(parameter))) {
|
||||
ContainerUtil.exists(parameters, parameter -> keepVarType(parameter))) {
|
||||
for (PsiParameter parameter : parameters) {
|
||||
PsiTypeElement element = parameter.getTypeElement();
|
||||
if (element != null) {
|
||||
@@ -101,8 +100,7 @@ public class RedundantLambdaParameterTypeInspection extends AbstractBaseJavaLoca
|
||||
}
|
||||
|
||||
private static boolean keepVarType(PsiParameter parameter) {
|
||||
return parameter.hasModifierProperty(PsiModifier.FINAL) ||
|
||||
parameter.getAnnotations().length > 0;
|
||||
return parameter.hasModifierProperty(PsiModifier.FINAL) || parameter.getAnnotations().length > 0;
|
||||
}
|
||||
|
||||
private static class LambdaParametersFix implements LocalQuickFix {
|
||||
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
// "Replace with 'Comparator.comparing'" "true"
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
class CodeSample {
|
||||
public void foo() {
|
||||
final Comparator CMP = (Comparator<Entity>) Comparator.comparing((Entity o) -> o.getUuid());
|
||||
}
|
||||
|
||||
private class Entity {
|
||||
public <T> Comparable getUuid() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace with 'Comparator.comparing'" "true"
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
class CodeSample {
|
||||
public void foo() {
|
||||
final Comparator CMP = (Comparator<Entity>) (o1,<caret> o2) -> o1.getUuid()
|
||||
.compareTo(o2.getUuid());
|
||||
}
|
||||
|
||||
private class Entity {
|
||||
public <T> Comparable getUuid() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
// "Remove redundant types" "false"
|
||||
// "Remove redundant types" "true"
|
||||
class Test2 {
|
||||
class Y<T>{
|
||||
T t;
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Remove redundant types" "true"
|
||||
class Test2 {
|
||||
class Y<T>{
|
||||
T t;
|
||||
}
|
||||
|
||||
interface I<X> {
|
||||
X foo(Y<X> list);
|
||||
}
|
||||
|
||||
static <T> I<T> bar(I<T> i){return i;}
|
||||
|
||||
{
|
||||
Test2.bar(y<caret> -> y.t);
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -61,7 +61,7 @@ public class RedundantLambdaParameterTypeInspectionTest extends LightJavaCodeIns
|
||||
}
|
||||
|
||||
public void testCallNoTypeArgs() {
|
||||
assertIntentionNotAvailable();
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testCallNoTypeArgs1() {
|
||||
|
||||
Reference in New Issue
Block a user