Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
83.33% covered (warning)
83.33%
15 / 18
57.14% covered (warning)
57.14%
4 / 7
CRAP
0.00% covered (danger)
0.00%
0 / 1
LeafVisitor
83.33% covered (warning)
83.33%
15 / 18
57.14% covered (warning)
57.14%
4 / 7
10.46
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
1
 visitParsedBooleanNode
100.00% covered (success)
100.00%
2 / 2
100.00% covered (success)
100.00%
1 / 1
2
 visitNegatedNode
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitNamespaceHeader
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 visitBooleanClause
100.00% covered (success)
100.00%
10 / 10
100.00% covered (success)
100.00%
1 / 1
3
 negated
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCurrentBooleanClause
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
1<?php declare( strict_types=1 );
2
3namespace CirrusSearch\Parser\AST\Visitor;
4
5use CirrusSearch\Parser\AST\BooleanClause;
6use CirrusSearch\Parser\AST\NamespaceHeaderNode;
7use CirrusSearch\Parser\AST\NegatedNode;
8use CirrusSearch\Parser\AST\ParsedBooleanNode;
9use Wikimedia\Assert\Assert;
10
11/**
12 * Visit leaves only
13 */
14abstract class LeafVisitor implements Visitor {
15    /**
16     * @var string[]
17     */
18    private array $excludeOccurs;
19
20    /**
21     * @var bool true when this branch is "negated".
22     */
23    private bool $inNegation = false;
24    private ?BooleanClause $currentClause = null;
25
26    /**
27     * @param string[] $excludeOccurs
28     */
29    public function __construct( array $excludeOccurs = [] ) {
30        array_walk( $excludeOccurs, static fn ( $x ) => BooleanClause::validateOccur( $x ) );
31        $this->excludeOccurs = $excludeOccurs;
32    }
33
34    final public function visitParsedBooleanNode( ParsedBooleanNode $node ): void {
35        foreach ( $node->getClauses() as $clause ) {
36            $clause->accept( $this );
37        }
38    }
39
40    final public function visitNegatedNode( NegatedNode $node ): void {
41        /** @phan-suppress-next-line PhanImpossibleCondition I agree, this is impossible. */
42        Assert::invariant( false, 'NegatedNode should be optimized at parse time' );
43    }
44
45    final public function visitNamespaceHeader( NamespaceHeaderNode $node ): void {
46        /** @phan-suppress-next-line PhanImpossibleCondition I agree, this is impossible. */
47        Assert::invariant( false, 'Not yet part of the AST, should not be visited.' );
48    }
49
50    final public function visitBooleanClause( BooleanClause $clause ): void {
51        if ( in_array( $clause->getOccur(), $this->excludeOccurs ) ) {
52            return;
53        }
54
55        $oldNegated = $this->inNegation;
56        $oldClause = $this->currentClause;
57        if ( $clause->getOccur() === BooleanClause::MUST_NOT ) {
58            $this->inNegation = !$this->inNegation;
59        }
60        $this->currentClause = $clause;
61
62        $clause->getNode()->accept( $this );
63        $this->inNegation = $oldNegated;
64        $this->currentClause = $oldClause;
65    }
66
67    /**
68     * @return bool true if this node is in a negation
69     */
70    final public function negated(): bool {
71        return $this->inNegation;
72    }
73
74    /**
75     * @return BooleanClause|null the boolean clause the visited node is in or null if top-level
76     */
77    final public function getCurrentBooleanClause(): ?BooleanClause {
78        return $this->currentClause;
79    }
80}