diff --git a/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java b/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java index 2a1db951c4fa..7ec0b9d54a16 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java +++ b/java/java-impl/src/com/intellij/slicer/SliceUsageCellRenderer.java @@ -118,6 +118,12 @@ class SliceUsageCellRenderer extends SliceUsageCellRendererBase { else if (element instanceof PsiReference) { name = ((PsiReference)element).getCanonicalText(); } + else if (element instanceof PsiExpression) { + PsiType type = ((PsiExpression)element).getType(); + if (type != null) { + name = type.getPresentableText(); + } + } prev = usage; usage = (JavaSliceUsage)usage.getParent(); } diff --git a/java/java-impl/src/com/intellij/slicer/SliceUtil.java b/java/java-impl/src/com/intellij/slicer/SliceUtil.java index 62dba5522157..e918c3c5f7f1 100644 --- a/java/java-impl/src/com/intellij/slicer/SliceUtil.java +++ b/java/java-impl/src/com/intellij/slicer/SliceUtil.java @@ -151,19 +151,20 @@ final class SliceUtil { } } if (expression instanceof PsiMethodCallExpression) { // ctr call can't return value or be container get, so don't use PsiCall here - PsiExpression returnedValue = JavaMethodContractUtil.findReturnedValue((PsiMethodCallExpression)expression); + PsiMethodCallExpression call = (PsiMethodCallExpression)expression; + PsiExpression returnedValue = JavaMethodContractUtil.findReturnedValue(call); if (returnedValue != null) { if (!builder.process(returnedValue, processor)) { return false; } } - PsiMethod method = ((PsiMethodCallExpression)expression).resolveMethod(); + PsiMethod method = call.resolveMethod(); Flow anno = method == null ? null : isMethodFlowAnnotated(method); if (anno != null) { String target = anno.target(); if (target.equals(Flow.DEFAULT_TARGET)) target = Flow.RETURN_METHOD_TARGET; if (target.equals(Flow.RETURN_METHOD_TARGET)) { - PsiExpression qualifier = ((PsiMethodCallExpression)expression).getMethodExpression().getQualifierExpression(); + PsiExpression qualifier = call.getMethodExpression().getQualifierExpression(); if (qualifier != null) { builder = builder.updateNesting(anno); String source = anno.source(); @@ -173,7 +174,25 @@ final class SliceUtil { } } } - return processMethodReturnValue((PsiMethodCallExpression)expression, processor, builder); + if (method != null && builder.hasNesting()) { + PsiParameter[] parameters = method.getParameterList().getParameters(); + boolean hasFlownParameter = false; + for (int i = 0; i < parameters.length; i++) { + Flow paramAnno = isParamFlowAnnotated(method, i); + if (paramAnno != null && !parameters[i].isVarArgs()) { + PsiExpression[] args = call.getArgumentList().getExpressions(); + if (args.length > i) { + JavaSliceBuilder argBuilder = builder.updateNesting(paramAnno); + if (!argBuilder.process(args[i], processor)) { + return false; + } + hasFlownParameter = true; + } + } + } + if (hasFlownParameter) return true; + } + return processMethodReturnValue(call, processor, builder); } if (expression instanceof PsiConditionalExpression) { PsiConditionalExpression conditional = (PsiConditionalExpression)expression; diff --git a/java/java-tests/testData/codeInsight/slice/backward/FinalVarAssignedBeforePassingToAnonymous.java b/java/java-tests/testData/codeInsight/slice/backward/FinalVarAssignedBeforePassingToAnonymous.java index e9212dd35437..7eccbb108081 100644 --- a/java/java-tests/testData/codeInsight/slice/backward/FinalVarAssignedBeforePassingToAnonymous.java +++ b/java/java-tests/testData/codeInsight/slice/backward/FinalVarAssignedBeforePassingToAnonymous.java @@ -1,5 +1,3 @@ -import javax.swing.*; - class Foo { void foo(String s) { } @@ -14,4 +12,7 @@ class Foo { } }); } +} +class SwingUtilities { + static void invokeLater(Runnable runnable) {} } \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/slice/backward/OptionalAsContainer.java b/java/java-tests/testData/codeInsight/slice/backward/OptionalAsContainer.java new file mode 100644 index 000000000000..611ea89ef97a --- /dev/null +++ b/java/java-tests/testData/codeInsight/slice/backward/OptionalAsContainer.java @@ -0,0 +1,14 @@ +import java.util.Optional; + +class MainTest { + public static void main(String[] args) { + Optional optional; + if (args.length > 0) { + optional = Optional.ofNullable(args[0]); + } else { + optional = Optional.of("foo"); + } + String val = optional.orElse("xyz"); + System.out.println(val); + } +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/slicer/SliceBackwardTest.java b/java/java-tests/testSrc/com/intellij/java/slicer/SliceBackwardTest.java index ed4d0daabaab..bffa82008522 100644 --- a/java/java-tests/testSrc/com/intellij/java/slicer/SliceBackwardTest.java +++ b/java/java-tests/testSrc/com/intellij/java/slicer/SliceBackwardTest.java @@ -19,10 +19,13 @@ import com.intellij.analysis.AnalysisScope; import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.execution.filters.ExceptionAnalysisProvider; import com.intellij.openapi.editor.RangeMarker; +import com.intellij.openapi.projectRoots.Sdk; import com.intellij.pom.java.LanguageLevel; import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.slicer.*; +import com.intellij.testFramework.IdeaTestUtil; +import com.intellij.testFramework.PsiTestUtil; import com.intellij.util.ArrayUtil; import one.util.streamex.StreamEx; import org.jetbrains.annotations.NotNull; @@ -32,6 +35,11 @@ import java.util.List; import java.util.Map; public class SliceBackwardTest extends SliceTestCase { + @Override + protected Sdk getTestProjectJdk() { + return PsiTestUtil.addJdkAnnotations(IdeaTestUtil.getMockJdk11()); + } + private void doTest() throws Exception { doTest(""); } @@ -110,7 +118,7 @@ public class SliceBackwardTest extends SliceTestCase { public void testAppend() throws Exception { doTest();} public void testRequireNonNull() throws Exception { doTest();} public void testBackAndForward() throws Exception { doTest();} - + public void testFilterIntRange() throws Exception { doTest(">=0");} public void testFilterIntRangeArray() throws Exception { doTest(">=0");} public void testFilterNull() throws Exception { doTest("null");} @@ -122,20 +130,21 @@ public class SliceBackwardTest extends SliceTestCase { public void testReturnParameter() throws Exception { doTest(); } public void testFilterLongByInt() throws Exception { doTest("<=0"); } public void testFilterDoubleByInt() throws Exception { doTest("0.0"); } - - public void testStackFilterSimple() throws Exception { + + public void testStackFilterSimple() throws Exception { doTest("null", "MainTest:test", "MainTest:foo", "MainTest:main"); } - + public void testStackFilterBridgeMethod() throws Exception { doTest("null", "MainTest$Bar:get", "MainTest$Bar:get", "MainTest:bar", "MainTest:main"); - } - + } + public void testStackFilterBridgeMethod2() throws Exception { doTest("null", "MainTest$Bar:get", "MainTest$Bar:get", "MainTest:bar", "MainTest:main"); } - + public void testRecordComponent() throws Exception { doTest();} public void testRecordComponent2() throws Exception { doTest();} public void testRecordComponent3() throws Exception { doTest();} + public void testOptionalAsContainer() throws Exception { doTest();} } diff --git a/java/jdkAnnotations/java/util/annotations.xml b/java/jdkAnnotations/java/util/annotations.xml index c02e8b0e5cbb..41187cdb6857 100644 --- a/java/jdkAnnotations/java/util/annotations.xml +++ b/java/jdkAnnotations/java/util/annotations.xml @@ -3311,17 +3311,38 @@ + + + + + + + + + + + + + + + + + + + + +