From e14bc69538a67fa8855e5ab7a691441346eb1d64 Mon Sep 17 00:00:00 2001 From: Roman Ivanov Date: Fri, 24 Sep 2021 11:13:33 +0200 Subject: [PATCH] [java] suggest removing unnecessary wrapping in optional chains IDEA-225716 GitOrigin-RevId: 538bc7c7d357505d2e48bdd59c06bc0a707e07ec --- .../SimplifyOptionalCallChainsInspection.java | 49 ++++++++++++++++++- .../afterOptionalOfNullableOrElseNull.java | 14 ++++++ .../beforeOptionalOfNullableOrElseNull.java | 10 ++++ .../resources/messages/JavaBundle.properties | 2 + 4 files changed, 74 insertions(+), 1 deletion(-) create mode 100644 java/java-tests/testData/inspection/optionalChains/afterOptionalOfNullableOrElseNull.java create mode 100644 java/java-tests/testData/inspection/optionalChains/beforeOptionalOfNullableOrElseNull.java diff --git a/java/java-impl/src/com/intellij/codeInspection/SimplifyOptionalCallChainsInspection.java b/java/java-impl/src/com/intellij/codeInspection/SimplifyOptionalCallChainsInspection.java index 58387b259a75..0c8f9a47bf08 100644 --- a/java/java-impl/src/com/intellij/codeInspection/SimplifyOptionalCallChainsInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/SimplifyOptionalCallChainsInspection.java @@ -89,7 +89,8 @@ public class SimplifyOptionalCallChainsInspection extends AbstractBaseJavaLocalI new RewrappingCase(RewrappingCase.Type.OptionalGet), new RewrappingCase(RewrappingCase.Type.OrElseNull), new MapOrElseCase(OrElseType.OrElseGet), - new MapOrElseCase(OrElseType.OrElse) + new MapOrElseCase(OrElseType.OrElse), + new OptionalOfNullableOrElseNullCase() ); ourMapper = new CallMapper<>(); for (ChainSimplificationCase theCase : cases) { @@ -930,4 +931,50 @@ public class SimplifyOptionalCallChainsInspection extends AbstractBaseJavaLocalI } } } + + private static class OptionalOfNullableOrElseNullCase implements ChainSimplificationCase { + @Override + public @NotNull String getName(@NotNull Context context) { + return JavaBundle.message("simplify.optional.chain.inspection.fix.name.remove.redundant.optional.chain"); + } + + @Override + public @NotNull String getDescription(@NotNull Context context) { + return JavaBundle.message("simplify.optional.chain.inspection.fix.description.optional.chain.can.be.eliminated"); + } + + @Override + public @Nullable OptionalOfNullableOrElseNullCase.Context extractContext(@NotNull Project project, + @NotNull PsiMethodCallExpression call) { + PsiMethodCallExpression outerCall = ExpressionUtils.getCallForQualifier(call); + PsiExpression wrappingArgument = call.getArgumentList().getExpressions()[0]; + if (!OPTIONAL_OR_ELSE.test(outerCall)) return null; + PsiExpression argument = outerCall.getArgumentList().getExpressions()[0]; + if (!ExpressionUtils.isNullLiteral(argument)) return null; + return new Context(wrappingArgument, outerCall); + } + + @Override + public void apply(@NotNull Project project, + @NotNull PsiMethodCallExpression call, + @NotNull Context context) { + CommentTracker ct = new CommentTracker(); + ct.replaceAndRestoreComments(context.outerCall, context.wrappingArgument); + } + + @Override + public @NotNull CallMatcher getMatcher() { + return OPTIONAL_OF_NULLABLE; + } + + static class Context { + final PsiExpression wrappingArgument; + final PsiMethodCallExpression outerCall; + + Context(PsiExpression wrappingArgument, PsiMethodCallExpression outerCall) { + this.wrappingArgument = wrappingArgument; + this.outerCall = outerCall; + } + } + } } \ No newline at end of file diff --git a/java/java-tests/testData/inspection/optionalChains/afterOptionalOfNullableOrElseNull.java b/java/java-tests/testData/inspection/optionalChains/afterOptionalOfNullableOrElseNull.java new file mode 100644 index 000000000000..24973d626626 --- /dev/null +++ b/java/java-tests/testData/inspection/optionalChains/afterOptionalOfNullableOrElseNull.java @@ -0,0 +1,14 @@ +// "Remove redundant Optional chain" "true" +import java.util.Optional; + +class Test { + void execute(String s) { + /*1*/ + /*2*/ + /*4*/ + /*5*/ + System.out.println(someFunc(/*3*/)/*6*/); + } + + String someFunc() {throw new IllegalStateException();} +} \ No newline at end of file diff --git a/java/java-tests/testData/inspection/optionalChains/beforeOptionalOfNullableOrElseNull.java b/java/java-tests/testData/inspection/optionalChains/beforeOptionalOfNullableOrElseNull.java new file mode 100644 index 000000000000..72bd362c51c3 --- /dev/null +++ b/java/java-tests/testData/inspection/optionalChains/beforeOptionalOfNullableOrElseNull.java @@ -0,0 +1,10 @@ +// "Remove redundant Optional chain" "true" +import java.util.Optional; + +class Test { + void execute(String s) { + System.out.println(Optional./*1*/ofNullable(/*2*/someFunc(/*3*/)/*4*/).orElse(/*5*/null)/*6*/); + } + + String someFunc() {throw new IllegalStateException();} +} \ No newline at end of file diff --git a/java/openapi/resources/messages/JavaBundle.properties b/java/openapi/resources/messages/JavaBundle.properties index b92e2840ff4e..90516b031941 100644 --- a/java/openapi/resources/messages/JavaBundle.properties +++ b/java/openapi/resources/messages/JavaBundle.properties @@ -1421,6 +1421,8 @@ simplify.optional.chain.inspection.or.else.return.fix.name=Replace null check wi simplify.optional.chain.inspection.or.else.return.fix.description=Null check can be eliminated simplify.optional.chain.inspection.or.else.non.null.fix.name=Replace null check with ifPresent() simplify.optional.chain.inspection.or.else.non.null.fix.description=Null check can be eliminated with 'ifPresent' +simplify.optional.chain.inspection.fix.name.remove.redundant.optional.chain=Remove redundant Optional chain +simplify.optional.chain.inspection.fix.description.optional.chain.can.be.eliminated=Optional chain can be eliminated generate.test.support.method.error.no.template.found.for.framework=No template found for {0}:{1} generate.test.support.method.error.method.already.exists=Method {0} already exists generate.test.support.method.error.cannot.generate.method=Cannot generate method: {0}