From 7b3ce3097aa1ac1d08dd8408d20486bee975791c Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 15 May 2020 13:15:11 +0700 Subject: [PATCH] IDEA-240402 Dataflow to here: narrow filters during the dataflow GitOrigin-RevId: 3fb73062b31ec664aebe8bfe167726d421752cb2 --- .../slicer/JavaDfaSliceValueFilter.java | 30 ++++++++++++++----- .../com/intellij/slicer/JavaSliceBuilder.java | 25 +++++++++++----- .../slice/backward/NarrowFilter.java | 17 +++++++++++ .../java/slicer/SliceBackwardTest.java | 1 + 4 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/slice/backward/NarrowFilter.java diff --git a/java/java-impl/src/com/intellij/slicer/JavaDfaSliceValueFilter.java b/java/java-impl/src/com/intellij/slicer/JavaDfaSliceValueFilter.java index 0f71ccb0ebd6..566593d14810 100644 --- a/java/java-impl/src/com/intellij/slicer/JavaDfaSliceValueFilter.java +++ b/java/java-impl/src/com/intellij/slicer/JavaDfaSliceValueFilter.java @@ -42,18 +42,32 @@ public class JavaDfaSliceValueFilter implements SliceValueFilter { return Objects.equals(value, constValue); } } - if (!(element instanceof PsiExpression)) return true; + DfType dfType = getElementDfType(element); + return dfType.meet(myDfType) != DfTypes.BOTTOM; + } + + @Nullable JavaDfaSliceValueFilter mergeFilter(@NotNull PsiElement element) { + DfType type = getElementDfType(element); + if (type instanceof DfReferenceType) { + type = ((DfReferenceType)type).dropLocality().dropMutability(); + } + DfType meet = type.meet(myDfType); + if (meet == DfTypes.TOP && myNextFilter == null) return null; + if (meet == DfTypes.BOTTOM || meet.equals(myDfType)) return this; + return new JavaDfaSliceValueFilter(myNextFilter, meet); + } + + private @NotNull DfType getElementDfType(@NotNull PsiElement element) { + if (!(element instanceof PsiExpression)) return DfTypes.TOP; PsiExpression expression = (PsiExpression)element; - DfType dfType; PsiType expressionType = expression.getType(); if (TypeConversionUtil.isPrimitiveAndNotNull(expressionType) && myDfType instanceof DfReferenceType) { - dfType = DfTypes.typedObject(((PsiPrimitiveType)expressionType).getBoxedType(expression), Nullability.NOT_NULL); - } else if (!(expressionType instanceof PsiPrimitiveType) && myDfType instanceof DfPrimitiveType) { - dfType = DfTypes.typedObject(PsiPrimitiveType.getUnboxedType(expressionType), Nullability.NOT_NULL); - } else { - dfType = CommonDataflow.getDfType(expression); + return DfTypes.typedObject(((PsiPrimitiveType)expressionType).getBoxedType(expression), Nullability.NOT_NULL); } - return dfType.meet(myDfType) != DfTypes.BOTTOM; + if (!(expressionType instanceof PsiPrimitiveType) && myDfType instanceof DfPrimitiveType) { + return DfTypes.typedObject(PsiPrimitiveType.getUnboxedType(expressionType), Nullability.NOT_NULL); + } + return CommonDataflow.getDfType(expression); } @Override diff --git a/java/java-impl/src/com/intellij/slicer/JavaSliceBuilder.java b/java/java-impl/src/com/intellij/slicer/JavaSliceBuilder.java index 185a94f358aa..cd14f57c88ec 100644 --- a/java/java-impl/src/com/intellij/slicer/JavaSliceBuilder.java +++ b/java/java-impl/src/com/intellij/slicer/JavaSliceBuilder.java @@ -1,6 +1,7 @@ // Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file. package com.intellij.slicer; +import com.intellij.codeInspection.dataFlow.types.DfTypes; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Comparing; import com.intellij.psi.*; @@ -74,8 +75,16 @@ final class JavaSliceBuilder { final PsiElement realExpression = element.getParent() instanceof DummyHolder ? element.getParent().getContext() : element; assert realExpression != null; if (!(realExpression instanceof PsiCompiledElement)) { - return processor - .process(new JavaSliceUsage(realExpression, myParent, myAnalysisParams, mySubstitutor, myIndexNesting, mySyntheticField)); + JavaDfaSliceValueFilter curFilter = myAnalysisParams.valueFilter instanceof JavaDfaSliceValueFilter + ? (JavaDfaSliceValueFilter)myAnalysisParams.valueFilter + : new JavaDfaSliceValueFilter(DfTypes.TOP); + JavaDfaSliceValueFilter filter = curFilter.mergeFilter(realExpression); + SliceAnalysisParams params = myAnalysisParams; + if (filter != curFilter) { + params = new SliceAnalysisParams(params); + params.valueFilter = filter; + } + return processor.process(new JavaSliceUsage(realExpression, myParent, params, mySubstitutor, myIndexNesting, mySyntheticField)); } return true; } @@ -87,14 +96,14 @@ final class JavaSliceBuilder { */ @Contract(pure = true) @NotNull JavaSliceBuilder updateNesting(@NotNull Flow anno) { - int nestingDelta = (anno.sourceIsContainer() ? 1 : 0) - (anno.targetIsContainer() ? 1 : 0); - if (nestingDelta > 0) { - return incrementNesting(); + JavaSliceBuilder result = this; + if (anno.targetIsContainer()) { + result = result.decrementNesting(); } - if (nestingDelta < 0) { - return decrementNesting(); + if (anno.sourceIsContainer()) { + result = result.incrementNesting(); } - return this; + return result; } @Contract(pure = true) diff --git a/java/java-tests/testData/codeInsight/slice/backward/NarrowFilter.java b/java/java-tests/testData/codeInsight/slice/backward/NarrowFilter.java new file mode 100644 index 000000000000..98de89109de5 --- /dev/null +++ b/java/java-tests/testData/codeInsight/slice/backward/NarrowFilter.java @@ -0,0 +1,17 @@ +public class NarrowFilter { + void test(int x) { + if (x > 0) { + foo(x); + } else { + bar(x); + } + } + + void foo(int x) { } + void bar(int x) { } + + void call() { + test(1); + test(-1); + } +} \ 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 c3fd98ab0b77..59bff402a260 100644 --- a/java/java-tests/testSrc/com/intellij/java/slicer/SliceBackwardTest.java +++ b/java/java-tests/testSrc/com/intellij/java/slicer/SliceBackwardTest.java @@ -95,4 +95,5 @@ public class SliceBackwardTest extends SliceTestCase { public void testFilterIntRange() throws Exception { doTest(">=0");} public void testFilterIntRangeArray() throws Exception { doTest(">=0");} public void testFilterNull() throws Exception { doTest("null");} + public void testNarrowFilter() throws Exception { doTest();} }