• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MyIntervals / PHP-CSS-Parser / 13921221957

18 Mar 2025 10:41AM UTC coverage: 51.499% (-5.3%) from 56.839%
13921221957

push

github

web-flow
[TASK] Reduce and finetune the scope of `@covers` annotations (#1188)

The legacy tests are not very focused. Until we have split them
up, try to avoid false positives for code coverage.

Also add `@covers` annotations for the parent classes of the
tested classes.

945 of 1835 relevant lines covered (51.5%)

6.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

44.78
/src/Value/Size.php
1
<?php
2

3
declare(strict_types=1);
4

5
namespace Sabberworm\CSS\Value;
6

7
use Sabberworm\CSS\OutputFormat;
8
use Sabberworm\CSS\Parsing\ParserState;
9
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
10
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
11

12
/**
13
 * A `Size` consists of a numeric `size` value and a unit.
14
 */
15
class Size extends PrimitiveValue
16
{
17
    /**
18
     * vh/vw/vm(ax)/vmin/rem are absolute insofar as they don’t scale to the immediate parent (only the viewport)
19
     *
20
     * @var list<non-empty-string>
21
     */
22
    private const ABSOLUTE_SIZE_UNITS = [
23
        'px',
24
        'pt',
25
        'pc',
26
        'cm',
27
        'mm',
28
        'mozmm',
29
        'in',
30
        'vh',
31
        'dvh',
32
        'svh',
33
        'lvh',
34
        'vw',
35
        'vmin',
36
        'vmax',
37
        'rem',
38
    ];
39

40
    /**
41
     * @var list<non-empty-string>
42
     */
43
    private const RELATIVE_SIZE_UNITS = ['%', 'em', 'ex', 'ch', 'fr'];
44

45
    /**
46
     * @var list<non-empty-string>
47
     */
48
    private const NON_SIZE_UNITS = ['deg', 'grad', 'rad', 's', 'ms', 'turn', 'Hz', 'kHz'];
49

50
    /**
51
     * @var array<int<1, max>, array<lowercase-string, non-empty-string>>|null
52
     */
53
    private static $SIZE_UNITS = null;
54

55
    /**
56
     * @var float
57
     */
58
    private $size;
59

60
    /**
61
     * @var string|null
62
     */
63
    private $unit;
64

65
    /**
66
     * @var bool
67
     */
68
    private $isColorComponent;
69

70
    /**
71
     * @param float|int|string $size
72
     * @param int<0, max> $lineNumber
73
     */
74
    public function __construct($size, ?string $unit = null, bool $isColorComponent = false, int $lineNumber = 0)
30✔
75
    {
76
        parent::__construct($lineNumber);
30✔
77
        $this->size = (float) $size;
30✔
78
        $this->unit = $unit;
30✔
79
        $this->isColorComponent = $isColorComponent;
30✔
80
    }
30✔
81

82
    /**
83
     * @throws UnexpectedEOFException
84
     * @throws UnexpectedTokenException
85
     *
86
     * @internal since V8.8.0
87
     */
88
    public static function parse(ParserState $parserState, bool $isColorComponent = false): Size
28✔
89
    {
90
        $size = '';
28✔
91
        if ($parserState->comes('-')) {
28✔
92
            $size .= $parserState->consume('-');
×
93
        }
94
        while (\is_numeric($parserState->peek()) || $parserState->comes('.') || $parserState->comes('e', true)) {
28✔
95
            if ($parserState->comes('.')) {
28✔
96
                $size .= $parserState->consume('.');
×
97
            } elseif ($parserState->comes('e', true)) {
28✔
98
                $lookahead = $parserState->peek(1, 1);
2✔
99
                if (\is_numeric($lookahead) || $lookahead === '+' || $lookahead === '-') {
2✔
100
                    $size .= $parserState->consume(2);
×
101
                } else {
102
                    break; // Reached the unit part of the number like "em" or "ex"
2✔
103
                }
104
            } else {
105
                $size .= $parserState->consume(1);
28✔
106
            }
107
        }
108

109
        $unit = null;
28✔
110
        $sizeUnits = self::getSizeUnits();
28✔
111
        foreach ($sizeUnits as $length => &$values) {
28✔
112
            $key = \strtolower($parserState->peek($length));
28✔
113
            if (\array_key_exists($key, $values)) {
28✔
114
                if (($unit = $values[$key]) !== null) {
28✔
115
                    $parserState->consume($length);
28✔
116
                    break;
28✔
117
                }
118
            }
119
        }
120
        return new Size((float) $size, $unit, $isColorComponent, $parserState->currentLine());
28✔
121
    }
122

123
    /**
124
     * @return array<int<1, max>, array<lowercase-string, non-empty-string>>
125
     */
126
    private static function getSizeUnits(): array
28✔
127
    {
128
        if (!\is_array(self::$SIZE_UNITS)) {
28✔
129
            self::$SIZE_UNITS = [];
×
130
            $sizeUnits = \array_merge(self::ABSOLUTE_SIZE_UNITS, self::RELATIVE_SIZE_UNITS, self::NON_SIZE_UNITS);
×
131
            foreach ($sizeUnits as $sizeUnit) {
×
132
                $tokenLength = \strlen($sizeUnit);
×
133
                if (!isset(self::$SIZE_UNITS[$tokenLength])) {
×
134
                    self::$SIZE_UNITS[$tokenLength] = [];
×
135
                }
136
                self::$SIZE_UNITS[$tokenLength][\strtolower($sizeUnit)] = $sizeUnit;
×
137
            }
138

139
            \krsort(self::$SIZE_UNITS, SORT_NUMERIC);
×
140
        }
141

142
        return self::$SIZE_UNITS;
28✔
143
    }
144

145
    public function setUnit(string $unit): void
×
146
    {
147
        $this->unit = $unit;
×
148
    }
×
149

150
    public function getUnit(): ?string
28✔
151
    {
152
        return $this->unit;
28✔
153
    }
154

155
    /**
156
     * @param float|int|string $size
157
     */
158
    public function setSize($size): void
×
159
    {
160
        $this->size = (float) $size;
×
161
    }
×
162

163
    public function getSize(): float
×
164
    {
165
        return $this->size;
×
166
    }
167

168
    public function isColorComponent(): bool
×
169
    {
170
        return $this->isColorComponent;
×
171
    }
172

173
    /**
174
     * Returns whether the number stored in this Size really represents a size (as in a length of something on screen).
175
     *
176
     * Returns `false` if the unit is an angle, a duration, a frequency, or the number is a component in a `Color`
177
     * object.
178
     */
179
    public function isSize(): bool
×
180
    {
181
        if (\in_array($this->unit, self::NON_SIZE_UNITS, true)) {
×
182
            return false;
×
183
        }
184
        return !$this->isColorComponent();
×
185
    }
186

187
    public function isRelative(): bool
×
188
    {
189
        if (\in_array($this->unit, self::RELATIVE_SIZE_UNITS, true)) {
×
190
            return true;
×
191
        }
192
        if ($this->unit === null && $this->size != 0) {
×
193
            return true;
×
194
        }
195
        return false;
×
196
    }
197

198
    public function render(OutputFormat $outputFormat): string
×
199
    {
200
        $locale = \localeconv();
×
201
        $decimalPoint = \preg_quote($locale['decimal_point'], '/');
×
202
        $size = \preg_match('/[\\d\\.]+e[+-]?\\d+/i', (string) $this->size)
×
203
            ? \preg_replace("/$decimalPoint?0+$/", '', \sprintf('%f', $this->size)) : (string) $this->size;
×
204

205
        return \preg_replace(["/$decimalPoint/", '/^(-?)0\\./'], ['.', '$1.'], $size) . ($this->unit ?? '');
×
206
    }
207
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc