Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
2 / 2
CRAP
100.00% covered (success)
100.00%
1 / 1
WhitespaceMatcher
100.00% covered (success)
100.00%
16 / 16
100.00% covered (success)
100.00%
2 / 2
11
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 generateMatches
100.00% covered (success)
100.00%
15 / 15
100.00% covered (success)
100.00%
1 / 1
10
1<?php
2declare( strict_types = 1 );
3
4/**
5 * @file
6 * @license https://opensource.org/licenses/Apache-2.0 Apache-2.0
7 */
8
9namespace Wikimedia\CSS\Grammar;
10
11use Wikimedia\CSS\Objects\ComponentValueList;
12use Wikimedia\CSS\Objects\Token;
13
14/**
15 * Matcher that matches runs of whitespace.
16 */
17class WhitespaceMatcher extends Matcher {
18
19    /** @var bool */
20    protected $significant;
21
22    /**
23     * @param array $options
24     *  - significant: (bool) Whether the whitespace being matched is significant.
25     *    This also controls whether it behaves as `<ws>*` (false) or `<ws>+` (true).
26     */
27    public function __construct( array $options = [] ) {
28        $this->significant = !empty( $options['significant'] );
29    }
30
31    /** @inheritDoc */
32    protected function generateMatches( ComponentValueList $values, $start, array $options ) {
33        $end = $start;
34        while ( isset( $values[$end] ) &&
35            // @phan-suppress-next-line PhanUndeclaredMethod False positive
36            $values[$end] instanceof Token && $values[$end]->type() === Token::T_WHITESPACE
37        ) {
38            $end++;
39        }
40
41        // If it's not significant, return whatever we found.
42        if ( !$this->significant ) {
43            yield $this->makeMatch( $values, $start, $end );
44            return;
45        }
46
47        // If we found zero whitespace, $options says we're skipping
48        // whitespace, and whitespace was actually skipped, rewind one token.
49        // Otherwise, return no match.
50        if ( $end === $start ) {
51            $start--;
52            if ( !$options['skip-whitespace'] || !isset( $values[$start] ) ||
53                // @phan-suppress-next-line PhanUndeclaredMethod False positive
54                !$values[$start] instanceof Token || $values[$start]->type() !== Token::T_WHITESPACE
55            ) {
56                return;
57            }
58        }
59
60        // Return the match. Include a 'significantWhitespace' capture.
61        yield $this->makeMatch( $values, $start, $end,
62            new GrammarMatch( $values, $start, 1, 'significantWhitespace' )
63        );
64    }
65}