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