private static void createValueRootNode( NullAnalysisResult result, SliceRootNode oldRoot, final Map<SliceNode, NullAnalysisResult> map, SliceRootNode root, SliceNode oldRootStart, String nodeName, final int group) { Collection<PsiElement> groupedByValue = result.groupedByValue[group]; if (groupedByValue.isEmpty()) { return; } SliceLeafValueClassNode valueRoot = new SliceLeafValueClassNode(root.getProject(), root, nodeName); root.myCachedChildren.add(valueRoot); Set<PsiElement> uniqueValues = new THashSet<PsiElement>(groupedByValue, SliceLeafAnalyzer.LEAF_ELEMENT_EQUALITY); for (final PsiElement expression : uniqueValues) { SliceNode newRoot = SliceLeafAnalyzer.filterTree( oldRootStart, new NullableFunction<SliceNode, SliceNode>() { @Override public SliceNode fun(SliceNode oldNode) { if (oldNode.getDuplicate() != null) { return null; } for (PsiElement nullSuspect : group(oldNode, map, group)) { if (PsiEquivalenceUtil.areElementsEquivalent(nullSuspect, expression)) { return oldNode.copy(); } } return null; } }, new PairProcessor<SliceNode, List<SliceNode>>() { @Override public boolean process(SliceNode node, List<SliceNode> children) { if (!children.isEmpty()) return true; PsiElement element = node.getValue().getElement(); if (element == null) return false; return PsiEquivalenceUtil.areElementsEquivalent( element, expression); // leaf can be there only if it's filtering expression } }); valueRoot.myCachedChildren.add( new SliceLeafValueRootNode( root.getProject(), expression, valueRoot, Collections.singletonList(newRoot), oldRoot.getValue().params)); } }
private static void groupByNullness( NullAnalysisResult result, SliceRootNode oldRoot, final Map<SliceNode, NullAnalysisResult> map) { SliceRootNode root = createNewTree(result, oldRoot, map); SliceUsage rootUsage = oldRoot.myCachedChildren.get(0).getValue(); SliceManager.getInstance(root.getProject()) .createToolWindow( true, root, true, SliceManager.getElementDescription( null, rootUsage.getElement(), " Grouped by Nullness")); }
public static SliceRootNode createNewTree( NullAnalysisResult result, SliceRootNode oldRoot, final Map<SliceNode, NullAnalysisResult> map) { SliceRootNode root = oldRoot.copy(); assert oldRoot.myCachedChildren.size() == 1; SliceNode oldRootStart = oldRoot.myCachedChildren.get(0); root.setChanged(); root.targetEqualUsages.clear(); root.myCachedChildren = new ArrayList<SliceNode>(); createValueRootNode( result, oldRoot, map, root, oldRootStart, "Null Values", NullAnalysisResult.NULLS); createValueRootNode( result, oldRoot, map, root, oldRootStart, "NotNull Values", NullAnalysisResult.NOT_NULLS); createValueRootNode( result, oldRoot, map, root, oldRootStart, "Other Values", NullAnalysisResult.UNKNOWNS); return root; }
public void testGroupByValuesCorrectLeaves() throws Exception { SliceTreeStructure treeStructure = configureTree("DuplicateLeaves"); SliceRootNode root = (SliceRootNode) treeStructure.getRootElement(); Map<SliceNode, Collection<PsiElement>> map = SliceLeafAnalyzer.createMap(); Collection<PsiElement> leaves = SliceLeafAnalyzer.calcLeafExpressions(root, treeStructure, map); assertNotNull(leaves); assertEquals(1, leaves.size()); PsiElement leaf = leaves.iterator().next(); assertTrue(leaf instanceof PsiLiteralExpression); assertEquals("\"oo\"", leaf.getText()); SliceRootNode newRoot = SliceLeafAnalyzer.createTreeGroupedByValues(leaves, root, map); Collection<? extends AbstractTreeNode> children = newRoot.getChildren(); assertEquals(1, children.size()); SliceNode child = (SliceNode) children.iterator().next(); assertTrue(child instanceof SliceLeafValueRootNode); children = child.getChildren(); assertEquals(1, children.size()); child = (SliceNode) children.iterator().next(); assertTrue(child.getValue().getElement() instanceof PsiField); children = child.getChildren(); assertEquals(1, children.size()); child = (SliceNode) children.iterator().next(); assertTrue(child.getValue().getElement() instanceof PsiReferenceExpression); children = child.getChildren(); assertEquals(1, children.size()); child = (SliceNode) children.iterator().next(); assertTrue(child.getValue().getElement() instanceof PsiReferenceExpression); children = child.getChildren(); assertEquals(1, children.size()); child = (SliceNode) children.iterator().next(); assertTrue(child.getValue().getElement() instanceof PsiLiteralExpression); assertEquals(child.getValue().getElement(), leaf); }
private static boolean processValuesFlownTo( @NotNull final PsiExpression argument, PsiElement scope, @NotNull final Processor<PsiExpression> processor) { SliceAnalysisParams params = new SliceAnalysisParams(); params.dataFlowToThis = true; params.scope = new AnalysisScope(new LocalSearchScope(scope), argument.getProject()); SliceRootNode rootNode = new SliceRootNode( scope.getProject(), new DuplicateMap(), SliceManager.createRootUsage(argument, params)); Collection<? extends AbstractTreeNode> children = rootNode.getChildren().iterator().next().getChildren(); for (AbstractTreeNode child : children) { SliceUsage usage = (SliceUsage) child.getValue(); PsiElement element = usage.getElement(); if (element instanceof PsiExpression && !processor.process((PsiExpression) element)) return false; } return !children.isEmpty(); }
public static void startAnalyzeNullness( final AbstractTreeStructure treeStructure, final Runnable finish) { final SliceRootNode root = (SliceRootNode) treeStructure.getRootElement(); final Ref<NullAnalysisResult> leafExpressions = Ref.create(null); final Map<SliceNode, NullAnalysisResult> map = createMap(); ProgressManager.getInstance() .run( new Task.Backgroundable( root.getProject(), "Expanding all nodes... (may very well take the whole day)", true) { @Override public void run(@NotNull final ProgressIndicator indicator) { NullAnalysisResult l = calcNullableLeaves(root, treeStructure, map); leafExpressions.set(l); } @Override public void onCancel() { finish.run(); } @Override public void onSuccess() { try { NullAnalysisResult leaves = leafExpressions.get(); if (leaves == null) return; // cancelled groupByNullness(leaves, root, map); } finally { finish.run(); } } }); }