mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-18 09:34:34 +07:00
IDEA-163062 [Java8][Feature] Function.identity() inspection
This commit is contained in:
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace lambda expression with 'Predicate.isEqual()'" "true"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(x -> x).filter(Predicate.isEqual(str))
|
||||
.filter(str -> pattern.matcher(str).find()).orElse("");
|
||||
UnaryOperator<T> op = x -> x;
|
||||
}
|
||||
}
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
// "Replace lambda expression with 'Function.identity()'" "true"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(Function.identity()).filter(x -> Objects.equals(x, str))
|
||||
.filter(str -> pattern.matcher(str).find()).orElse("");
|
||||
UnaryOperator<T> op = x -> x;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace lambda expression with 'Pattern.asPredicate()'" "true"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(x -> x).filter(x -> Objects.equals(x, str))
|
||||
.filter(pattern.asPredicate()).orElse("");
|
||||
UnaryOperator<T> op = x -> x;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace lambda expression with 'Predicate.isEqual()'" "true"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(x -> x).filter(x <caret>-> Objects.equals(x, str))
|
||||
.filter(str -> pattern.matcher(str).find()).orElse("");
|
||||
UnaryOperator<T> op = x -> x;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace lambda expression with 'Function.identity()'" "true"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(x <caret>-> x).filter(x -> Objects.equals(x, str))
|
||||
.filter(str -> pattern.matcher(str).find()).orElse("");
|
||||
UnaryOperator<T> op = x -> x;
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
// "Replace lambda expression with 'Function.identity()'" "false"
|
||||
import java.io.Serializable;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
Function<Object, Object> fn = (Function<Object, Object> & Serializable) x <caret>-> x;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace lambda expression with 'Function.identity()'" "false"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(x -> x).filter(x -> Objects.equals(x, str))
|
||||
.filter(str -> pattern.matcher(str).find()).orElse("");
|
||||
UnaryOperator<T> op = x <caret>-> x;
|
||||
}
|
||||
}
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
// "Replace lambda expression with 'Pattern.asPredicate()'" "true"
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class Main {
|
||||
private final Pattern pattern = Pattern.compile("[a-z]");
|
||||
|
||||
public <T extends CharSequence> void test() {
|
||||
Object str = "def";
|
||||
String xyz = Optional.of("xyz").map(x -> x).filter(x -> Objects.equals(x, str))
|
||||
.filter(str <caret>-> pattern.matcher(str).find()).orElse("");
|
||||
UnaryOperator<T> op = x -> x;
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.codeInsight.daemon.quickFix;
|
||||
|
||||
import com.intellij.codeInspection.LambdaCanBeMethodCallInspection;
|
||||
import com.intellij.codeInspection.LocalInspectionTool;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class LambdaCanBeMethodCallInspectionTest extends LightQuickFixParameterizedTestCase {
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{new LambdaCanBeMethodCallInspection()};
|
||||
}
|
||||
|
||||
public void test() throws Exception { doAllTests(); }
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/codeInsight/daemonCodeAnalyzer/quickFix/lambda2methodCall";
|
||||
}
|
||||
}
|
||||
@@ -745,6 +745,10 @@ inspection.excessive.lambda.message=Excessive lambda usage
|
||||
inspection.excessive.lambda.fix.family.name=Replace lambda with constant
|
||||
inspection.excessive.lambda.fix.name=Use ''{0}'' method without lambda
|
||||
|
||||
inspection.lambda.to.method.call.message=Can be replaced with ''{0}''
|
||||
inspection.lambda.to.method.call.fix.family.name=Replace lambda expression with method call
|
||||
inspection.lambda.to.method.call.fix.name=Replace lambda expression with ''{0}''
|
||||
|
||||
inspection.module.exports.package.to.itself.message=Module exports package to itself
|
||||
inspection.module.exports.package.to.itself.only.message=Module exports package only to itself
|
||||
exports.to.itself.delete.module.fix.name=Delete reference to module ''{0}''
|
||||
|
||||
+156
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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.psi.*;
|
||||
import com.intellij.psi.codeStyle.CodeStyleManager;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleManager;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.siyeh.ig.psiutils.CommentTracker;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import com.siyeh.ig.psiutils.ParenthesesUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
*/
|
||||
public class LambdaCanBeMethodCallInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
|
||||
if (!PsiUtil.isLanguageLevel8OrHigher(holder.getFile())) {
|
||||
return PsiElementVisitor.EMPTY_VISITOR;
|
||||
}
|
||||
return new JavaElementVisitor() {
|
||||
@Override
|
||||
public void visitLambdaExpression(PsiLambdaExpression lambda) {
|
||||
super.visitLambdaExpression(lambda);
|
||||
PsiElement body = lambda.getBody();
|
||||
if (body == null) return;
|
||||
PsiType type = lambda.getFunctionalInterfaceType();
|
||||
if (!(type instanceof PsiClassType)) return;
|
||||
PsiElement parent = PsiUtil.skipParenthesizedExprUp(lambda.getParent());
|
||||
if(parent instanceof PsiTypeCastExpression) {
|
||||
PsiType castType = ((PsiTypeCastExpression)parent).getType();
|
||||
if( castType instanceof PsiIntersectionType) {
|
||||
PsiType[] conjuncts = ((PsiIntersectionType)castType).getConjuncts();
|
||||
if(Arrays.stream(conjuncts).anyMatch(t -> t.equalsToText(CommonClassNames.JAVA_IO_SERIALIZABLE))) return;
|
||||
}
|
||||
}
|
||||
PsiExpression expression = PsiUtil.skipParenthesizedExprDown(LambdaUtil.extractSingleExpressionFromBody(body));
|
||||
if (expression == null) return;
|
||||
PsiParameter[] parameters = lambda.getParameterList().getParameters();
|
||||
if (parameters.length == 1 && ExpressionUtils.isReferenceTo(expression, parameters[0])) {
|
||||
PsiClass aClass = ((PsiClassType)type).resolve();
|
||||
if (aClass != null && CommonClassNames.JAVA_UTIL_FUNCTION_FUNCTION.equals(aClass.getQualifiedName())) {
|
||||
PsiType[] typeParameters = ((PsiClassType)type).getParameters();
|
||||
if (typeParameters.length == 2 && typeParameters[1].isAssignableFrom(typeParameters[0])) {
|
||||
registerProblem(lambda, "Function.identity()", CommonClassNames.JAVA_UTIL_FUNCTION_FUNCTION + ".identity()");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (parameters.length == 1 && expression instanceof PsiMethodCallExpression) {
|
||||
PsiMethodCallExpression call = (PsiMethodCallExpression)expression;
|
||||
PsiClass aClass = ((PsiClassType)type).resolve();
|
||||
if (aClass != null && CommonClassNames.JAVA_UTIL_FUNCTION_PREDICATE.equals(aClass.getQualifiedName())) {
|
||||
handlePredicate(lambda, parameters, call);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handlePredicate(PsiLambdaExpression lambda, PsiParameter[] parameters, PsiMethodCallExpression call) {
|
||||
if (MethodCallUtils.isCallToStaticMethod(call, "java.util.Objects", "equals", 2)) {
|
||||
PsiExpression[] args = call.getArgumentList().getExpressions();
|
||||
if (args.length == 2) {
|
||||
PsiExpression comparedWith;
|
||||
if (ExpressionUtils.isReferenceTo(args[0], parameters[0])) {
|
||||
comparedWith = args[1];
|
||||
}
|
||||
else if (ExpressionUtils.isReferenceTo(args[1], parameters[0])) {
|
||||
comparedWith = args[0];
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
if (LambdaCanBeMethodReferenceInspection.checkQualifier(comparedWith)) {
|
||||
registerProblem(lambda, "Predicate.isEqual()",
|
||||
CommonClassNames.JAVA_UTIL_FUNCTION_PREDICATE + ".isEqual(" + comparedWith.getText() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MethodCallUtils.isCallToMethod(call, "java.util.regex.Matcher", PsiType.BOOLEAN, "find")) {
|
||||
PsiExpression matcher = call.getMethodExpression().getQualifierExpression();
|
||||
if (matcher instanceof PsiMethodCallExpression) {
|
||||
PsiMethodCallExpression matcherCall = (PsiMethodCallExpression)matcher;
|
||||
if (MethodCallUtils.isCallToMethod(matcherCall, "java.util.regex.Pattern", null, "matcher",
|
||||
new PsiType[]{null})) {
|
||||
PsiExpression[] matcherArgs = matcherCall.getArgumentList().getExpressions();
|
||||
if (matcherArgs.length == 1 && ExpressionUtils.isReferenceTo(matcherArgs[0], parameters[0])) {
|
||||
PsiExpression pattern = matcherCall.getMethodExpression().getQualifierExpression();
|
||||
if (pattern != null && LambdaCanBeMethodReferenceInspection.checkQualifier(pattern)) {
|
||||
registerProblem(lambda, "Pattern.asPredicate()",
|
||||
ParenthesesUtils.getText(pattern, ParenthesesUtils.POSTFIX_PRECEDENCE) + ".asPredicate()");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerProblem(PsiLambdaExpression lambda, String displayReplacement, String replacement) {
|
||||
holder.registerProblem(lambda, InspectionsBundle.message("inspection.lambda.to.method.call.message", displayReplacement),
|
||||
new ReplaceWithFunctionCallFix(replacement, displayReplacement));
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static final class ReplaceWithFunctionCallFix implements LocalQuickFix {
|
||||
private final String myDisplayReplacement;
|
||||
private final String myReplacement;
|
||||
|
||||
public ReplaceWithFunctionCallFix(String replacement, String displayReplacement) {
|
||||
myReplacement = replacement;
|
||||
myDisplayReplacement = displayReplacement;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return InspectionsBundle.message("inspection.lambda.to.method.call.fix.name", myDisplayReplacement);
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return InspectionsBundle.message("inspection.lambda.to.method.call.fix.family.name");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiElement element = descriptor.getStartElement();
|
||||
if (!(element instanceof PsiLambdaExpression)) return;
|
||||
PsiElement result = new CommentTracker().replaceAndRestoreComments(element, myReplacement);
|
||||
CodeStyleManager.getInstance(project).reformat(JavaCodeStyleManager.getInstance(project).shortenClassReferences(result));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
<html>
|
||||
<body>
|
||||
Reports lambda expressions which could be replaced with JDK method call.
|
||||
<!-- tooltip end -->
|
||||
<p>For example, the expression <code>x -> x</code> of type <code>Function<T, T></code>
|
||||
could be replaced with <code>Function.identity()</code> call.</p>
|
||||
<small>New in 2017.1</small>
|
||||
</body>
|
||||
</html>
|
||||
@@ -780,6 +780,9 @@
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="Convert2MethodRef" displayName="Lambda can be replaced with method reference"
|
||||
groupKey="group.names.language.level.specific.issues.and.migration.aids" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.LambdaCanBeMethodReferenceInspection" />
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="LambdaCanBeMethodCall" displayName="Lambda can be replaced with method call"
|
||||
groupKey="group.names.language.level.specific.issues.and.migration.aids" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="INFORMATION"
|
||||
implementationClass="com.intellij.codeInspection.LambdaCanBeMethodCallInspection" />
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="InvalidComparatorMethodReference" displayName="Invalid method reference used for Comparator"
|
||||
groupKey="group.names.probable.bugs" groupBundle="messages.InspectionsBundle" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.InvalidComparatorMethodReferenceInspection"/>
|
||||
|
||||
Reference in New Issue
Block a user