Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
10 / 10
CRAP
100.00% covered (success)
100.00%
1 / 1
GrammarMatch
100.00% covered (success)
100.00%
22 / 22
100.00% covered (success)
100.00%
10 / 10
14
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
6 / 6
100.00% covered (success)
100.00%
1 / 1
1
 getValues
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getStart
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getLength
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getNext
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getName
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getCapturedMatches
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 getUniqueID
100.00% covered (success)
100.00%
4 / 4
100.00% covered (success)
100.00%
1 / 1
2
 fixWhitespace
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
4
 __toString
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
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\ComponentValue;
10use Wikimedia\CSS\Objects\ComponentValueList;
11use Wikimedia\CSS\Objects\Token;
12use Wikimedia\CSS\Util;
13
14/**
15 * Represent a match from a Matcher.
16 */
17class GrammarMatch {
18
19    /** @var int */
20    protected $start;
21
22    /** @var int */
23    protected $length;
24
25    /** @var ComponentValue[] Matched ComponentValues */
26    protected $values;
27
28    /** @var string|null */
29    protected $name = null;
30
31    /** @var GrammarMatch[] Captured submatches */
32    protected $capturedMatches = [];
33
34    /**
35     * @param ComponentValueList $list List containing the match
36     * @param int $start Starting index of the match.
37     * @param int $length Number of tokens in the match.
38     * @param string|null $name Give a name to this match.
39     * @param GrammarMatch[] $capturedMatches Captured submatches of this match.
40     */
41    public function __construct(
42        ComponentValueList $list, $start, $length, $name = null, array $capturedMatches = []
43    ) {
44        Util::assertAllInstanceOf( $capturedMatches, self::class, '$capturedMatches' );
45
46        $this->values = $list->slice( $start, $length );
47        $this->start = $start;
48        $this->length = $length;
49        $this->name = $name;
50        $this->capturedMatches = $capturedMatches;
51    }
52
53    /**
54     * The matched values
55     * @return ComponentValue[]
56     */
57    public function getValues() {
58        return $this->values;
59    }
60
61    /**
62     * The starting position of this match within the original list of values.
63     * @return int
64     */
65    public function getStart() {
66        return $this->start;
67    }
68
69    /**
70     * The length of this match
71     * @return int
72     */
73    public function getLength() {
74        return $this->length;
75    }
76
77    /**
78     * The position after this match, as in index into the original list of values.
79     * @return int
80     */
81    public function getNext() {
82        return $this->start + $this->length;
83    }
84
85    /**
86     * The name of this match
87     * @return string|null
88     */
89    public function getName() {
90        return $this->name;
91    }
92
93    /**
94     * The captured submatches of this match
95     *
96     * This returns the matches from capturing submatchers (see
97     * Matcher::capture()) that matched during the matching of the top-level
98     * matcher that returned this match. If capturing submatchers were nested,
99     * the GrammarMatch objects returned here will themselves have captured sub-
100     * matches to return.
101     *
102     * To borrow PCRE regular expression syntax, if the "pattern" described by
103     * the Matchers resembled `www(?<A>xxx(?<B>yyy)xxx)(?<C>zzz)*` then the
104     * top-level GrammarMatch's getCapturedMatches() would return a GrammarMatch
105     * named "A" (containing the "xxxyyyxxx" bit) and zero or more matches named
106     * "C" (for each "zzz"), and that "A" GrammarMatch's getCapturedMatches()
107     * would return a GrammarMatch named "B" (containing just the "yyy").
108     *
109     * Note that the start and end positions reported by captured matches may be
110     * relative to a containing SimpleBlock or CSSFunction's value rather than
111     * to the ComponentValueList passed to the top-level Matcher.
112     *
113     * @return GrammarMatch[]
114     */
115    public function getCapturedMatches() {
116        return $this->capturedMatches;
117    }
118
119    /**
120     * Return a key for this matcher's state
121     * @return string
122     */
123    public function getUniqueID() {
124        $data = [ $this->start, $this->length, $this->name ];
125        foreach ( $this->capturedMatches as $m ) {
126            $data[] = $m->getUniqueId();
127        }
128        return md5( implode( "\n", $data ) );
129    }
130
131    /**
132     * Replace whitespace in the matched values
133     * @private For use by Matcher only
134     * @param Token $old
135     * @param Token $new
136     */
137    public function fixWhitespace( Token $old, Token $new ) {
138        foreach ( $this->values as $k => $v ) {
139            if ( $v === $old ) {
140                $this->values[$k] = $new;
141            }
142        }
143        foreach ( $this->capturedMatches as $m ) {
144            $m->fixWhitespace( $old, $new );
145        }
146    }
147
148    public function __toString() {
149        return Util::stringify( $this->getValues() );
150    }
151}