public static PredicateTreeAnnotations createPredicateTreeAnnotations(Predicate predicate) {
        PredicateTreeAnalyzerResult analyzerResult = PredicateTreeAnalyzer.analyzePredicateTree(predicate);
        // The tree size is used as the interval range.
        int intervalEnd = analyzerResult.treeSize;
        AnnotatorContext context = new AnnotatorContext(intervalEnd, analyzerResult.sizeMap);
        assignIntervalLabels(predicate, Interval.INTERVAL_BEGIN, intervalEnd, false, context);
        return new PredicateTreeAnnotations(
                analyzerResult.minFeature, intervalEnd, context.intervals, context.intervalsWithBounds,
                context.featureConjunctions);
    }
@Test
    void require_that_featureconjunctions_are_registered_and_given_an_interval() {
        Predicate p =
                and(
                        or(
                                range("key",
                                        partition("key=10-19"),
                                        partition("key=20-29"),
                                        edgePartition("key=0", 5, 10, 20),
                                        edgePartition("key=30", 0, 0, 3)),
                                conj(
                                        not(feature("keyA").inSet("C")),
                                        feature("keyB").inSet("D"))),
                        feature("foo").inSet("bar"));
        PredicateTreeAnnotations r = PredicateTreeAnnotator.createPredicateTreeAnnotations(p);
        assertEquals(2, r.minFeature);
        assertEquals(3, r.intervalEnd);
        assertEquals(3, r.intervalMap.size());
        assertEquals(2, r.boundsMap.size());
        assertEquals(1, r.featureConjunctions.size());

        Map.Entry<IndexableFeatureConjunction, List<Integer>> entry = r.featureConjunctions.entrySet().iterator().next();
        assertEquals(1, entry.getValue().size());
        assertEquals(0b1_0000000000000010, entry.getValue().get(0).longValue());
    }