mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-13 09:19:13 +07:00
IDEA-170885 Simplify action for Optional
This commit is contained in:
+157
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* 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.codeInspection.util.OptionalUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiDiamondTypeUtil;
|
||||
import com.intellij.psi.util.PsiExpressionTrimRenderer;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.refactoring.util.LambdaRefactoringUtil;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import org.jetbrains.annotations.Nls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
*/
|
||||
public class SimplifyOptionalCallChainsInspection extends BaseJavaBatchLocalInspectionTool {
|
||||
private static final CallMatcher OPTIONAL_OR_ELSE =
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "orElse").parameterCount(1);
|
||||
private static final CallMatcher OPTIONAL_OR_ELSE_GET =
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "orElseGet").parameterCount(1);
|
||||
private static final CallMatcher OPTIONAL_MAP =
|
||||
CallMatcher.instanceCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "map").parameterCount(1);
|
||||
|
||||
|
||||
@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 visitMethodCallExpression(PsiMethodCallExpression call) {
|
||||
PsiExpression falseArg = null;
|
||||
boolean useOrElseGet = false;
|
||||
if (OPTIONAL_OR_ELSE.test(call)) {
|
||||
falseArg = call.getArgumentList().getExpressions()[0];
|
||||
}
|
||||
else if (OPTIONAL_OR_ELSE_GET.test(call)) {
|
||||
useOrElseGet = true;
|
||||
PsiLambdaExpression lambda = getLambda(call.getArgumentList().getExpressions()[0]);
|
||||
if (lambda == null || lambda.getParameterList().getParametersCount() != 0) return;
|
||||
falseArg = LambdaUtil.extractSingleExpressionFromBody(lambda.getBody());
|
||||
}
|
||||
if (falseArg == null) return;
|
||||
PsiMethodCallExpression qualifierCall = MethodCallUtils.getQualifierMethodCall(call);
|
||||
if (!OPTIONAL_MAP.test(qualifierCall)) return;
|
||||
PsiLambdaExpression lambda = getLambda(qualifierCall.getArgumentList().getExpressions()[0]);
|
||||
if (lambda == null) return;
|
||||
PsiExpression trueArg = LambdaUtil.extractSingleExpressionFromBody(lambda.getBody());
|
||||
if (trueArg == null) return;
|
||||
PsiParameter[] parameters = lambda.getParameterList().getParameters();
|
||||
if (parameters.length != 1) return;
|
||||
PsiExpression qualifier = qualifierCall.getMethodExpression().getQualifierExpression();
|
||||
if (qualifier == null) return;
|
||||
String opt = qualifier.getText();
|
||||
PsiParameter parameter = parameters[0];
|
||||
String proposed = OptionalUtil.generateOptionalUnwrap(opt, parameter, trueArg, falseArg, call.getType(), useOrElseGet);
|
||||
String canonicalOrElse;
|
||||
if (useOrElseGet && !ExpressionUtils.isSimpleExpression(falseArg)) {
|
||||
canonicalOrElse = ".orElseGet(() -> " + falseArg.getText() + ")";
|
||||
}
|
||||
else {
|
||||
canonicalOrElse = ".orElse(" + falseArg.getText() + ")";
|
||||
}
|
||||
String canonical = opt + ".map(" + LambdaUtil.createLambda(parameter, trueArg) + ")" + canonicalOrElse;
|
||||
if (proposed.length() < canonical.length()) {
|
||||
String displayCode;
|
||||
if(proposed.equals(opt)) {
|
||||
displayCode = "";
|
||||
} else if(opt.length() > 10) {
|
||||
// should be a parseable expression
|
||||
opt = "(($))";
|
||||
String template = OptionalUtil.generateOptionalUnwrap(opt, parameter, trueArg, falseArg, call.getType(), useOrElseGet);
|
||||
displayCode =
|
||||
PsiExpressionTrimRenderer.render(JavaPsiFacade.getElementFactory(holder.getProject()).createExpressionFromText(template, call));
|
||||
displayCode = displayCode.replaceFirst(Pattern.quote(opt), "..");
|
||||
} else {
|
||||
displayCode =
|
||||
PsiExpressionTrimRenderer.render(JavaPsiFacade.getElementFactory(holder.getProject()).createExpressionFromText(proposed, call));
|
||||
}
|
||||
holder.registerProblem(Objects.requireNonNull(call.getMethodExpression().getReferenceNameElement()),
|
||||
"Optional chain can be simplified",
|
||||
new SimplifyOptionalChainFix(proposed, displayCode));
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static PsiLambdaExpression getLambda(PsiExpression initializer) {
|
||||
PsiExpression expression = PsiUtil.skipParenthesizedExprDown(initializer);
|
||||
if (expression instanceof PsiLambdaExpression) {
|
||||
return (PsiLambdaExpression)expression;
|
||||
}
|
||||
if (expression instanceof PsiMethodReferenceExpression) {
|
||||
return LambdaRefactoringUtil.createLambda((PsiMethodReferenceExpression)expression, true);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static class SimplifyOptionalChainFix implements LocalQuickFix {
|
||||
private final String myReplacement;
|
||||
private final String myDisplayCode;
|
||||
|
||||
public SimplifyOptionalChainFix(String replacement, String displayCode) {
|
||||
myReplacement = replacement;
|
||||
myDisplayCode = displayCode;
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getName() {
|
||||
return myDisplayCode.isEmpty() ? "Remove redundant steps from optional chain" :
|
||||
"Simplify optional chain to '"+myDisplayCode+"'";
|
||||
}
|
||||
|
||||
@Nls
|
||||
@NotNull
|
||||
@Override
|
||||
public String getFamilyName() {
|
||||
return "Simplify optional call chain";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
|
||||
PsiMethodCallExpression call = PsiTreeUtil.getParentOfType(descriptor.getStartElement(), PsiMethodCallExpression.class);
|
||||
if (call == null) return;
|
||||
PsiExpression replacementExpression = JavaPsiFacade.getElementFactory(project).createExpressionFromText(myReplacement, call);
|
||||
PsiElement result = call.replace(replacementExpression);
|
||||
LambdaCanBeMethodReferenceInspection.replaceAllLambdasWithMethodReferences(result);
|
||||
PsiDiamondTypeUtil.removeRedundantTypeArguments(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,9 +17,12 @@ package com.intellij.codeInspection.util;
|
||||
|
||||
import com.intellij.codeInsight.PsiEquivalenceUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import com.intellij.refactoring.util.RefactoringUtil;
|
||||
import com.siyeh.ig.callMatcher.CallMatcher;
|
||||
import com.siyeh.ig.psiutils.BoolUtils;
|
||||
import com.siyeh.ig.psiutils.ExpressionUtils;
|
||||
import com.siyeh.ig.psiutils.MethodCallUtils;
|
||||
import org.jetbrains.annotations.Contract;
|
||||
@@ -33,6 +36,9 @@ public class OptionalUtil {
|
||||
private static final String OPTIONAL_LONG = "java.util.OptionalLong";
|
||||
private static final String OPTIONAL_DOUBLE = "java.util.OptionalDouble";
|
||||
|
||||
private static final CallMatcher OPTIONAL_OF =
|
||||
CallMatcher.staticCall(CommonClassNames.JAVA_UTIL_OPTIONAL, "of", "ofNullable").parameterCount(1);
|
||||
|
||||
@NotNull
|
||||
@Contract(pure = true)
|
||||
public static String getOptionalClass(String type) {
|
||||
@@ -102,37 +108,59 @@ public class OptionalUtil {
|
||||
PsiExpression trueExpression, PsiExpression falseExpression,
|
||||
PsiType targetType, boolean useOrElseGet) {
|
||||
if (!ExpressionUtils.isReferenceTo(trueExpression, var)) {
|
||||
if(trueExpression instanceof PsiTypeCastExpression && ExpressionUtils.isNullLiteral(falseExpression)) {
|
||||
if (trueExpression instanceof PsiTypeCastExpression && ExpressionUtils.isNullLiteral(falseExpression)) {
|
||||
PsiTypeCastExpression castExpression = (PsiTypeCastExpression)trueExpression;
|
||||
PsiTypeElement castType = castExpression.getCastType();
|
||||
// pull cast outside to avoid the .map() step
|
||||
if(castType != null && ExpressionUtils.isReferenceTo(castExpression.getOperand(), var)) {
|
||||
if (castType != null && ExpressionUtils.isReferenceTo(castExpression.getOperand(), var)) {
|
||||
return "(" + castType.getText() + ")" + qualifier + ".orElse(null)";
|
||||
}
|
||||
}
|
||||
if(ExpressionUtils.isLiteral(falseExpression, Boolean.FALSE) && PsiType.BOOLEAN.equals(trueExpression.getType())) {
|
||||
if (ExpressionUtils.isLiteral(falseExpression, Boolean.FALSE) && PsiType.BOOLEAN.equals(trueExpression.getType())) {
|
||||
if (ExpressionUtils.isLiteral(trueExpression, Boolean.TRUE)) {
|
||||
return qualifier + ".isPresent()";
|
||||
}
|
||||
return qualifier + ".filter(" + LambdaUtil.createLambda(var, trueExpression) + ").isPresent()";
|
||||
}
|
||||
if(trueExpression instanceof PsiConditionalExpression) {
|
||||
if (ExpressionUtils.isLiteral(falseExpression, Boolean.TRUE) && ExpressionUtils.isLiteral(trueExpression, Boolean.FALSE)) {
|
||||
return "!" + qualifier + ".isPresent()";
|
||||
}
|
||||
if (trueExpression instanceof PsiConditionalExpression) {
|
||||
PsiConditionalExpression condition = (PsiConditionalExpression)trueExpression;
|
||||
PsiExpression thenExpression = condition.getThenExpression();
|
||||
PsiExpression elseExpression = condition.getElseExpression();
|
||||
if(elseExpression != null && PsiEquivalenceUtil.areElementsEquivalent(falseExpression, elseExpression)) {
|
||||
if (elseExpression != null && PsiEquivalenceUtil.areElementsEquivalent(falseExpression, elseExpression)) {
|
||||
return generateOptionalUnwrap(
|
||||
qualifier + ".filter(" + LambdaUtil.createLambda(var, condition.getCondition()) + ")", var,
|
||||
condition.getThenExpression(), falseExpression, targetType, useOrElseGet);
|
||||
}
|
||||
if (thenExpression != null && PsiEquivalenceUtil.areElementsEquivalent(falseExpression, thenExpression)) {
|
||||
return generateOptionalUnwrap(
|
||||
qualifier + ".filter(" + var.getName() + " -> " + BoolUtils.getNegatedExpressionText(condition.getCondition()) + ")", var,
|
||||
condition.getElseExpression(), falseExpression, targetType, useOrElseGet);
|
||||
}
|
||||
}
|
||||
if(isOptionalEmptyCall(falseExpression)) {
|
||||
String suffix = null;
|
||||
if (isOptionalEmptyCall(falseExpression)) {
|
||||
suffix = "";
|
||||
}
|
||||
else if (PsiUtil.isLanguageLevel9OrHigher(trueExpression) &&
|
||||
InheritanceUtil.isInheritor(falseExpression.getType(), CommonClassNames.JAVA_UTIL_OPTIONAL) &&
|
||||
LambdaGenerationUtil.canBeUncheckedLambda(falseExpression)) {
|
||||
suffix = ".or(() -> " + falseExpression.getText() + ")";
|
||||
}
|
||||
if (suffix != null) {
|
||||
// simplify "qualifier.map(x -> Optional.of(x)).orElse(Optional.empty())" to "qualifier"
|
||||
if (trueExpression instanceof PsiMethodCallExpression &&
|
||||
MethodCallUtils.isCallToStaticMethod((PsiMethodCallExpression)trueExpression, CommonClassNames.JAVA_UTIL_OPTIONAL, "of", 1)) {
|
||||
if (trueExpression instanceof PsiMethodCallExpression && OPTIONAL_OF.test((PsiMethodCallExpression)trueExpression)) {
|
||||
PsiExpression arg = ((PsiMethodCallExpression)trueExpression).getArgumentList().getExpressions()[0];
|
||||
if(ExpressionUtils.isReferenceTo(arg, var)) {
|
||||
return qualifier;
|
||||
if (ExpressionUtils.isReferenceTo(arg, var)) {
|
||||
return qualifier + suffix;
|
||||
}
|
||||
return qualifier + ".map(" + LambdaUtil.createLambda(var, arg) + ")";
|
||||
return qualifier + ".map(" + LambdaUtil.createLambda(var, arg) + ")" + suffix;
|
||||
}
|
||||
if (suffix.isEmpty()) {
|
||||
return qualifier + ".flatMap(" + LambdaUtil.createLambda(var, trueExpression) + ")";
|
||||
}
|
||||
return qualifier + ".flatMap(" + LambdaUtil.createLambda(var, trueExpression) + ")";
|
||||
}
|
||||
trueExpression =
|
||||
targetType == null ? trueExpression : RefactoringUtil.convertInitializerToNormalExpression(trueExpression, targetType);
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Simplify optional chain to '(String)...orElse(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public void test(Optional<Object> opt) {
|
||||
String result = (String) opt.filter(opt -> opt instanceof String).orElse(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to 'opt.filter(...).map(...).orElseGet(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public String getDefaultValue() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public void test(Optional<String> opt) {
|
||||
String result = opt.filter(obj -> !obj.isEmpty()).map(String::trim).orElseGet(this::getDefaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to '!...isPresent()'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
interface Dto {
|
||||
int getId();
|
||||
}
|
||||
|
||||
public void test(Dto dto) {
|
||||
boolean present = !Optional.ofNullable(dto).map(Dto::getId).isPresent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Remove redundant steps from optional chain" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
return getOpt();
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to 'getOpt().map(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
return getOpt().map(String::trim);
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// "Simplify optional chain to 'getOpt().or(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
return getOpt().or(this::getOpt2);
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
|
||||
private Optional<String> getOpt2() {
|
||||
return Optional.of("bar");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to '...isPresent()'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
interface Dto {
|
||||
int getId();
|
||||
}
|
||||
|
||||
public void test(Dto dto) {
|
||||
boolean present = Optional.ofNullable(dto).map(Dto::getId).isPresent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// "Simplify optional chain to '(String)...orElse(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public void test(Optional<Object> opt) {
|
||||
String result = opt.filter(opt -> opt instanceof String).map(opt -> (String) opt).or<caret>Else(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to 'opt.filter(...).map(...).orElseGet(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public String getDefaultValue() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public void test(Optional<String> opt) {
|
||||
String result = opt.map(obj -> obj.isEmpty() ? getDefaultValue() : obj.trim()).orEl<caret>seGet(this::getDefaultValue);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Fix all 'Simplify Optional call chains' problems in file" "false"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public String getDefaultValue() {
|
||||
return "foo";
|
||||
}
|
||||
|
||||
public void test(Optional<String> opt) {
|
||||
// proposed change is longer:
|
||||
// opt.filter(obj -> !obj.isEmpty()).map(obj -> obj.trim()).orElse(null);
|
||||
String result = opt.map(obj -> obj.isEmpty() ? null : obj.trim()).orEl<caret>se(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// "Simplify optional chain to '!...isPresent()'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
interface Dto {
|
||||
int getId();
|
||||
}
|
||||
|
||||
public void test(Dto dto) {
|
||||
boolean present = Optional.ofNullable(dto).map(Dto::getId).map(obj -> {
|
||||
return false;
|
||||
}).or<caret>ElseGet(() -> true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Remove redundant steps from optional chain" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
return getOpt().map(Optional::of).orEl<caret>se(Optional.empty());
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to 'getOpt().map(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
return getOpt().map(x -> Optional.ofNullable(x.trim())).orEl<caret>seGet(Optional::empty);
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// "Simplify optional chain to 'getOpt().or(...)'" "false"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
// no simpler alternative in Java 8
|
||||
return getOpt().map(Optional::of).orEl<caret>seGet(this::getOpt2);
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
|
||||
private Optional<String> getOpt2() {
|
||||
return Optional.of("bar");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
// "Simplify optional chain to 'getOpt().or(...)'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
public Optional<String> test() {
|
||||
return getOpt().map(Optional::of).orEl<caret>seGet(this::getOpt2);
|
||||
}
|
||||
|
||||
private Optional<String> getOpt() {
|
||||
return Optional.of("foo");
|
||||
}
|
||||
|
||||
private Optional<String> getOpt2() {
|
||||
return Optional.of("bar");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
// "Simplify optional chain to '...isPresent()'" "true"
|
||||
import java.util.Optional;
|
||||
|
||||
public class Test {
|
||||
interface Dto {
|
||||
int getId();
|
||||
}
|
||||
|
||||
public void test(Dto dto) {
|
||||
boolean present = Optional.ofNullable(dto).map(Dto::getId).map(obj -> true).or<caret>Else(false);
|
||||
}
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.daemon.quickFix.LightQuickFixParameterizedTestCase;
|
||||
import com.intellij.openapi.projectRoots.Sdk;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.testFramework.IdeaTestUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Tagir Valeev
|
||||
*/
|
||||
public class SimplifyOptionalCallChainsInspectionTest extends LightQuickFixParameterizedTestCase {
|
||||
@Override
|
||||
protected LanguageLevel getLanguageLevel() {
|
||||
return getTestName(false).endsWith("Java9.java") ? LanguageLevel.JDK_1_9 : LanguageLevel.JDK_1_8;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Sdk getProjectJDK() {
|
||||
return getTestName(false).endsWith("Java9.java") ? IdeaTestUtil.getMockJdk9() : IdeaTestUtil.getMockJdk18();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected LocalInspectionTool[] configureLocalInspectionTools() {
|
||||
return new LocalInspectionTool[]{new SimplifyOptionalCallChainsInspection()};
|
||||
}
|
||||
|
||||
public void test() throws Exception {
|
||||
doAllTests();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBasePath() {
|
||||
return "/inspection/optionalChains";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
<html>
|
||||
<body>
|
||||
<p>This inspection warns about Optional call chains which could be simplified. Here are some examples of possible simplifications:</p>
|
||||
<ul>
|
||||
<li><code>optional.map(x -> true).orElse(false)</code> → <code>optional.isPresent()</code></li>
|
||||
<li><code>optional.map(x -> Optional.of(x.trim())).orElseGet(Optional::empty)</code> → <code>optional.map(String::trim)</code></li>
|
||||
<li><code>optional.map(x -> (String)x).orElse(null)</code> → <code>(String) optional.orElse(null)</code></li>
|
||||
</ul>
|
||||
<!-- tooltip end -->
|
||||
<p><small>New in 2017.2</small></p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -889,6 +889,11 @@
|
||||
groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.SimplifyStreamApiCallChainsInspection"
|
||||
displayName="Simplify stream API call chains"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="SimplifyOptionalCallChains"
|
||||
groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING"
|
||||
implementationClass="com.intellij.codeInspection.SimplifyOptionalCallChainsInspection"
|
||||
displayName="Simplify Optional call chains"/>
|
||||
<localInspection groupPath="Java" language="JAVA" shortName="SimplifyCollector"
|
||||
groupBundle="messages.InspectionsBundle"
|
||||
groupKey="group.names.declaration.redundancy" enabledByDefault="true" level="WARNING"
|
||||
|
||||
Reference in New Issue
Block a user