diff --git a/java/java-impl/src/com/intellij/codeInspection/optionalToIf/IntermediateOperation.java b/java/java-impl/src/com/intellij/codeInspection/optionalToIf/IntermediateOperation.java index dbe9e25a1216..dd8b06ce9987 100644 --- a/java/java-impl/src/com/intellij/codeInspection/optionalToIf/IntermediateOperation.java +++ b/java/java-impl/src/com/intellij/codeInspection/optionalToIf/IntermediateOperation.java @@ -6,13 +6,13 @@ import com.intellij.codeInspection.streamToLoop.ChainVariable; import com.intellij.codeInspection.streamToLoop.FunctionHelper; import com.intellij.psi.PsiExpression; import com.intellij.psi.PsiMethodCallExpression; +import com.intellij.util.containers.ContainerUtil; import one.util.streamex.StreamEx; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.stream.Collectors; import static com.intellij.util.ObjectUtils.tryCast; @@ -42,6 +42,32 @@ abstract class IntermediateOperation implements Operation { return null; } + private static @NotNull OperationRecord replaceFnVariable(@NotNull String oldName, + @NotNull OperationRecord record, + @NotNull ChainVariable outerVar, + @NotNull OptionalToIfContext context) { + ChainVariable inVar = replaceFnVariable(oldName, record.myInVar, outerVar); + ChainVariable outVar = replaceFnVariable(oldName, record.myOutVar, outerVar); + Operation operation = record.myOperation; + operation.rename(oldName, outerVar, context); + return new OperationRecord(inVar, outVar, operation); + } + + private static @NotNull ChainVariable replaceFnVariable(@NotNull String oldName, + @NotNull ChainVariable variable, + @NotNull ChainVariable replacement) { + return oldName.equals(variable.getName()) ? replacement : variable; + } + + + private static @Nullable List extractRecords(@NotNull FunctionHelper fn) { + PsiMethodCallExpression chainExpression = tryCast(fn.getExpression(), PsiMethodCallExpression.class); + if (chainExpression == null) return null; + List operations = OptionalToIfInspection.extractOperations(chainExpression, false); + if (operations == null || operations.isEmpty()) return null; + return OptionalToIfInspection.createRecords(operations); + } + static class Filter extends IntermediateOperation { private final FunctionHelper myFn; @@ -58,8 +84,8 @@ abstract class IntermediateOperation implements Operation { } @Override - public void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) { - myFn.rename(oldName, newName, context); + public void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) { + myFn.rename(oldName, newVar.getName(), context); } @Override @@ -94,8 +120,8 @@ abstract class IntermediateOperation implements Operation { } @Override - public void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) { - myFn.rename(oldName, newName, context); + public void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) { + myFn.rename(oldName, newVar.getName(), context); } @NotNull @@ -118,7 +144,7 @@ abstract class IntermediateOperation implements Operation { static class Or extends IntermediateOperation { - private final List myRecords; + private List myRecords; @Contract(pure = true) Or(List records) { @@ -132,8 +158,8 @@ abstract class IntermediateOperation implements Operation { } @Override - public void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) { - myRecords.forEach(r -> r.myOperation.rename(oldName, newName, context)); + public void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) { + myRecords = ContainerUtil.map(myRecords, r -> replaceFnVariable(oldName, r, newVar, context)); } @NotNull @@ -142,12 +168,6 @@ abstract class IntermediateOperation implements Operation { return StreamEx.of(myRecords).flatMap(or -> StreamEx.of(or).append(or.myOperation.nestedOperations())); } - @Nullable - static Or create(@NotNull FunctionHelper fn) { - List records = extractRecords(fn); - return records == null ? null : new Or(records); - } - @Nullable @Override public String generate(@NotNull ChainVariable inVar, @@ -162,6 +182,11 @@ abstract class IntermediateOperation implements Operation { "\n}" + context.generateNotNullCondition(outVar.getName(), code); } + + static @Nullable Or create(@NotNull FunctionHelper fn) { + List records = extractRecords(fn); + return records == null ? null : new Or(records); + } } static class FlatMap extends IntermediateOperation { @@ -184,14 +209,6 @@ abstract class IntermediateOperation implements Operation { return myVarName.equals(outVar.getName()) ? inVar : outVar; } - @Nullable - static FlatMap create(@NotNull FunctionHelper fn) { - String varName = fn.tryLightTransform(); - if (varName == null) return null; - List records = extractRecords(fn); - return records == null ? null : new FlatMap(records, varName, fn); - } - @NotNull @Override public StreamEx nestedOperations() { @@ -205,31 +222,15 @@ abstract class IntermediateOperation implements Operation { @NotNull String code, @NotNull OptionalToIfContext context) { String elseBranch = context.getElseBranch(); - List records = StreamEx.of(myRecords).map(r -> replaceFnVariable(r, inVar, context)).collect(Collectors.toList()); + List records = ContainerUtil.map(myRecords, r -> replaceFnVariable(myVarName, r, inVar, context)); String wrapped = OptionalToIfInspection.wrapCode(context, records, code); context.setElseBranch(elseBranch); return wrapped; } - @NotNull - @Contract("_, _, _ -> new") - private OperationRecord replaceFnVariable(@NotNull OperationRecord record, - @NotNull ChainVariable outerVar, - @NotNull OptionalToIfContext context) { - ChainVariable inVar = replaceFnVariable(record.myInVar, outerVar); - ChainVariable outVar = replaceFnVariable(record.myOutVar, outerVar); - Operation operation = record.myOperation; - operation.rename(myVarName, outerVar.getName(), context); - return new OperationRecord(inVar, outVar, operation); - } - - private ChainVariable replaceFnVariable(@NotNull ChainVariable variable, @NotNull ChainVariable replacement) { - return myVarName.equals(variable.getName()) ? replacement : variable; - } - @Override - public void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) { - myRecords.forEach(r -> r.myOperation.rename(oldName, newName, context)); + public void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) { + myRecords.forEach(r -> r.myOperation.rename(oldName, newVar, context)); } @Override @@ -240,14 +241,12 @@ abstract class IntermediateOperation implements Operation { context.addLambdaVarName(name); } } - } - @Nullable - private static List extractRecords(@NotNull FunctionHelper fn) { - PsiMethodCallExpression chainExpression = tryCast(fn.getExpression(), PsiMethodCallExpression.class); - if (chainExpression == null) return null; - List operations = OptionalToIfInspection.extractOperations(chainExpression, false); - if (operations == null || operations.isEmpty()) return null; - return OptionalToIfInspection.createRecords(operations); + static @Nullable FlatMap create(@NotNull FunctionHelper fn) { + String varName = fn.tryLightTransform(); + if (varName == null) return null; + List records = extractRecords(fn); + return records == null ? null : new FlatMap(records, varName, fn); + } } } diff --git a/java/java-impl/src/com/intellij/codeInspection/optionalToIf/Operation.java b/java/java-impl/src/com/intellij/codeInspection/optionalToIf/Operation.java index 198aafa610a6..0056aae05796 100644 --- a/java/java-impl/src/com/intellij/codeInspection/optionalToIf/Operation.java +++ b/java/java-impl/src/com/intellij/codeInspection/optionalToIf/Operation.java @@ -15,7 +15,7 @@ interface Operation { @Nullable String generate(@NotNull ChainVariable inVar, @NotNull ChainVariable outVar, @NotNull String code, @NotNull OptionalToIfContext context); - default void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) {} + default void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) {} default void preprocessVariables(@NotNull ChainVariable inVar, @NotNull ChainVariable outVar, @NotNull OptionalToIfContext context) {} diff --git a/java/java-impl/src/com/intellij/codeInspection/optionalToIf/SourceOperation.java b/java/java-impl/src/com/intellij/codeInspection/optionalToIf/SourceOperation.java index f908de731e4a..b96f3fb5dfdd 100644 --- a/java/java-impl/src/com/intellij/codeInspection/optionalToIf/SourceOperation.java +++ b/java/java-impl/src/com/intellij/codeInspection/optionalToIf/SourceOperation.java @@ -57,8 +57,8 @@ abstract class SourceOperation implements Operation { } @Override - public void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) { - myArg = FunctionHelper.replaceVarReference(myArg, oldName, newName, context); + public void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) { + myArg = FunctionHelper.replaceVarReference(myArg, oldName, newVar.getName(), context); } @Nullable @@ -101,8 +101,8 @@ abstract class SourceOperation implements Operation { } @Override - public void rename(@NotNull String oldName, @NotNull String newName, @NotNull OptionalToIfContext context) { - myArg = FunctionHelper.replaceVarReference(myArg, oldName, newName, context); + public void rename(@NotNull String oldName, @NotNull ChainVariable newVar, @NotNull OptionalToIfContext context) { + myArg = FunctionHelper.replaceVarReference(myArg, oldName, newVar.getName(), context); } @Nullable diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/afterFlatMap.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/afterFlatMap.java index 20a7081a1543..a765cd18cc92 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/afterFlatMap.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/afterFlatMap.java @@ -58,6 +58,16 @@ class Test { } } + void nestedOr(String param0) { + boolean result; + result = true; + String s = null; + if (param0 == null) throw new NullPointerException(); + String empty = null; + s = param0; + result = false; + } + void flatMapsWithSameParamName(String param0) { if (param0 == null) throw new NullPointerException(); String s = "foo"; diff --git a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/beforeFlatMap.java b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/beforeFlatMap.java index e714ca2255c1..893606ccd6ae 100644 --- a/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/beforeFlatMap.java +++ b/java/java-tests/testData/codeInsight/daemonCodeAnalyzer/quickFix/optionalToIf/beforeFlatMap.java @@ -40,6 +40,13 @@ class Test { .isPresent(); } + void nestedOr(String param0) { + boolean result; + result = Optional.of(param0) + .flatMap(var0 -> Optional.empty().or(() -> Optional.of(var0))) + .isEmpty(); + } + void flatMapsWithSameParamName(String param0) { Optional.of(param0) .flatMap(var0 -> Optional.of("foo").map(s -> ("foo").toLowerCase()))