Skip to content

Commit c3f49e2

Browse files
committed
[TASK] Implement Positionable
Closes #1207.
1 parent 8ea11a4 commit c3f49e2

File tree

18 files changed

+523
-173
lines changed

18 files changed

+523
-173
lines changed

CHANGELOG.md

+16
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ Please also have a look at our
1010

1111
### Added
1212

13+
- Methods `getLineNumber` and `getColumnNumber` which return a nullable `int`
14+
for the following classes:
15+
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,
16+
`Rule`, `DeclarationBlock, `RuleSet`, `CSSFunction`, `Value` (#1225)
17+
- `Positionable` interface for CSS items that may have an original position
18+
(line and perhaps column number) in the parsed CSS (#1221)
1319
- Partial support for CSS Color Module Level 4:
1420
- `rgb` and `rgba`, and `hsl` and `hsla` are now aliases (#797}
1521
- Parse color functions that use the "modern" syntax (#800)
@@ -20,6 +26,9 @@ Please also have a look at our
2026

2127
### Changed
2228

29+
- Implement `Positionable` in the following CSS item classes:
30+
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,
31+
`Rule`, `DeclarationBlock, `RuleSet`, `CSSFunction`, `Value` (#1225)
2332
- Initialize `KeyFrame` properties to sensible defaults (#1146)
2433
- Make `OutputFormat` `final` (#1128)
2534
- Make `Selector` a `Renderable` (#1017)
@@ -33,6 +42,13 @@ Please also have a look at our
3342

3443
### Deprecated
3544

45+
- `getLineNo()` is deprecated in these classes (use `getLineNumber()` instead):
46+
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,
47+
`Rule`, `DeclarationBlock, `RuleSet`, `CSSFunction`, `Value` (#1225)
48+
- `Rule::getColNo()` is deprecated (use `getColumnNumber()` instead) (#1225)
49+
- Providing zero as the line number argument to `Rule::setPosition()` is
50+
deprecated (pass `null` instead if there is no line number) (#1225)
51+
3652
### Removed
3753

3854
- Remove `__toString()` (#1046)

src/CSSList/CSSList.php

+5-17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
use Sabberworm\CSS\Parsing\SourceException;
1111
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
1212
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
13+
use Sabberworm\CSS\Position\Position;
14+
use Sabberworm\CSS\Position\Positionable;
1315
use Sabberworm\CSS\Property\AtRule;
1416
use Sabberworm\CSS\Property\Charset;
1517
use Sabberworm\CSS\Property\CSSNamespace;
@@ -33,9 +35,10 @@
3335
* Note that `CSSListItem` extends both `Commentable` and `Renderable`,
3436
* so those interfaces must also be implemented by concrete subclasses.
3537
*/
36-
abstract class CSSList implements CSSListItem
38+
abstract class CSSList implements CSSListItem, Positionable
3739
{
3840
use CommentContainer;
41+
use Position;
3942

4043
/**
4144
* @var array<int<0, max>, CSSListItem>
@@ -44,19 +47,12 @@ abstract class CSSList implements CSSListItem
4447
*/
4548
protected $contents = [];
4649

47-
/**
48-
* @var int<0, max>
49-
*
50-
* @internal since 8.8.0
51-
*/
52-
protected $lineNumber;
53-
5450
/**
5551
* @param int<0, max> $lineNumber
5652
*/
5753
public function __construct(int $lineNumber = 0)
5854
{
59-
$this->lineNumber = $lineNumber;
55+
$this->setPosition($lineNumber);
6056
}
6157

6258
/**
@@ -250,14 +246,6 @@ private static function identifierIs(string $identifier, string $match): bool
250246
?: \preg_match("/^(-\\w+-)?$match$/i", $identifier) === 1;
251247
}
252248

253-
/**
254-
* @return int<0, max>
255-
*/
256-
public function getLineNo(): int
257-
{
258-
return $this->lineNumber;
259-
}
260-
261249
/**
262250
* Prepends an item to the list of contents.
263251
*/

src/Comment/Comment.php

+5-16
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,12 @@
66

77
use Sabberworm\CSS\OutputFormat;
88
use Sabberworm\CSS\Renderable;
9+
use Sabberworm\CSS\Position\Position;
10+
use Sabberworm\CSS\Position\Positionable;
911

10-
class Comment implements Renderable
12+
class Comment implements Positionable, Renderable
1113
{
12-
/**
13-
* @var int<0, max>
14-
*
15-
* @internal since 8.8.0
16-
*/
17-
protected $lineNumber;
14+
use Position;
1815

1916
/**
2017
* @var string
@@ -29,22 +26,14 @@ class Comment implements Renderable
2926
public function __construct(string $commentText = '', int $lineNumber = 0)
3027
{
3128
$this->commentText = $commentText;
32-
$this->lineNumber = $lineNumber;
29+
$this->setPosition($lineNumber);
3330
}
3431

3532
public function getComment(): string
3633
{
3734
return $this->commentText;
3835
}
3936

40-
/**
41-
* @return int<0, max>
42-
*/
43-
public function getLineNo(): int
44-
{
45-
return $this->lineNumber;
46-
}
47-
4837
public function setComment(string $commentText): void
4938
{
5039
$this->commentText = $commentText;

src/Parsing/SourceException.php

+6-14
Original file line numberDiff line numberDiff line change
@@ -4,30 +4,22 @@
44

55
namespace Sabberworm\CSS\Parsing;
66

7-
class SourceException extends \Exception
7+
use Sabberworm\CSS\Position\Position;
8+
use Sabberworm\CSS\Position\Positionable;
9+
10+
class SourceException extends \Exception implements Positionable
811
{
9-
/**
10-
* @var int<0, max>
11-
*/
12-
private $lineNumber;
12+
use Position;
1313

1414
/**
1515
* @param int<0, max> $lineNumber
1616
*/
1717
public function __construct(string $message, int $lineNumber = 0)
1818
{
19-
$this->lineNumber = $lineNumber;
19+
$this->setPosition($lineNumber);
2020
if ($lineNumber !== 0) {
2121
$message .= " [line no: $lineNumber]";
2222
}
2323
parent::__construct($message);
2424
}
25-
26-
/**
27-
* @return int<0, max>
28-
*/
29-
public function getLineNo(): int
30-
{
31-
return $this->lineNumber;
32-
}
3325
}

src/Position/Position.php

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Position;
6+
7+
/**
8+
* Provides a standard reusable implementation of `Positionable`.
9+
*
10+
* @internal
11+
*
12+
* @phpstan-require-implements Positionable
13+
*/
14+
trait Position
15+
{
16+
/**
17+
* @var int<1, max>|null
18+
*/
19+
protected $lineNumber;
20+
21+
/**
22+
* @var int<0, max>|null
23+
*/
24+
protected $columnNumber;
25+
26+
/**
27+
* @return int<1, max>|null
28+
*/
29+
public function getLineNumber(): ?int
30+
{
31+
return $this->lineNumber;
32+
}
33+
34+
/**
35+
* @return int<0, max>
36+
*/
37+
public function getLineNo(): int
38+
{
39+
return $this->getLineNumber() ?? 0;
40+
}
41+
42+
/**
43+
* @return int<0, max>|null
44+
*/
45+
public function getColumnNumber(): ?int
46+
{
47+
return $this->columnNumber;
48+
}
49+
50+
/**
51+
* @return int<0, max>
52+
*/
53+
public function getColNo(): int
54+
{
55+
return $this->getColumnNumber() ?? 0;
56+
}
57+
58+
/**
59+
* @param int<0, max>|null $lineNumber
60+
* @param int<0, max>|null $columnNumber
61+
*/
62+
public function setPosition(?int $lineNumber, ?int $columnNumber = null): void
63+
{
64+
// The conditional is for backwards compatibility (backcompat); `0` will not be allowed in future.
65+
$this->lineNumber = $lineNumber !== 0 ? $lineNumber : null;
66+
$this->columnNumber = $columnNumber;
67+
}
68+
}

src/Position/Positionable.php

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Sabberworm\CSS\Position;
6+
7+
/**
8+
* Represents a CSS item that may have a position in the source CSS document (line number and possibly column number).
9+
*
10+
* A standard implementation of this interface is available in the `Position` trait.
11+
*/
12+
interface Positionable
13+
{
14+
/**
15+
* @return int<1, max>|null
16+
*/
17+
public function getLineNumber(): ?int;
18+
19+
/**
20+
* @deprecated in version 9.0.0, will be removed in v10.0. Use `getLineNumber()` instead.
21+
*
22+
* @return int<0, max>
23+
*/
24+
public function getLineNo(): int;
25+
26+
/**
27+
* @return int<0, max>|null
28+
*/
29+
public function getColumnNumber(): ?int;
30+
31+
/**
32+
* @deprecated in version 9.0.0, will be removed in v10.0. Use `getColumnNumber()` instead.
33+
*
34+
* @return int<0, max>
35+
*/
36+
public function getColNo(): int;
37+
38+
/**
39+
* @param int<0, max>|null $lineNumber
40+
* Providing zero for this parameter is deprecated in version 9.0.0, and will not be supported from v10.0.
41+
* Use `null` instead when no line number is available.
42+
* @param int<0, max>|null $columnNumber
43+
*/
44+
public function setPosition(?int $lineNumber, ?int $columnNumber = null): void;
45+
}

src/Property/CSSNamespace.php

+5-15
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@
66

77
use Sabberworm\CSS\Comment\CommentContainer;
88
use Sabberworm\CSS\OutputFormat;
9+
use Sabberworm\CSS\Position\Position;
10+
use Sabberworm\CSS\Position\Positionable;
911
use Sabberworm\CSS\Value\CSSString;
1012
use Sabberworm\CSS\Value\URL;
1113

1214
/**
1315
* `CSSNamespace` represents an `@namespace` rule.
1416
*/
15-
class CSSNamespace implements AtRule
17+
class CSSNamespace implements AtRule, Positionable
1618
{
1719
use CommentContainer;
20+
use Position;
1821

1922
/**
2023
* @var CSSString|URL
@@ -26,11 +29,6 @@ class CSSNamespace implements AtRule
2629
*/
2730
private $prefix;
2831

29-
/**
30-
* @var int<0, max> $lineNumber
31-
*/
32-
private $lineNumber;
33-
3432
/**
3533
* @param CSSString|URL $url
3634
* @param int<0, max> $lineNumber
@@ -39,15 +37,7 @@ public function __construct($url, ?string $prefix = null, int $lineNumber = 0)
3937
{
4038
$this->url = $url;
4139
$this->prefix = $prefix;
42-
$this->lineNumber = $lineNumber;
43-
}
44-
45-
/**
46-
* @return int<0, max>
47-
*/
48-
public function getLineNo(): int
49-
{
50-
return $this->lineNumber;
40+
$this->setPosition($lineNumber);
5141
}
5242

5343
/**

src/Property/Charset.php

+5-17
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66

77
use Sabberworm\CSS\Comment\CommentContainer;
88
use Sabberworm\CSS\OutputFormat;
9+
use Sabberworm\CSS\Position\Position;
10+
use Sabberworm\CSS\Position\Positionable;
911
use Sabberworm\CSS\Value\CSSString;
1012

1113
/**
@@ -16,37 +18,23 @@
1618
* - May only appear at the very top of a Document’s contents.
1719
* - Must not appear more than once.
1820
*/
19-
class Charset implements AtRule
21+
class Charset implements AtRule, Positionable
2022
{
2123
use CommentContainer;
24+
use Position;
2225

2326
/**
2427
* @var CSSString
2528
*/
2629
private $charset;
2730

28-
/**
29-
* @var int<0, max>
30-
*
31-
* @internal since 8.8.0
32-
*/
33-
protected $lineNumber;
34-
3531
/**
3632
* @param int<0, max> $lineNumber
3733
*/
3834
public function __construct(CSSString $charset, int $lineNumber = 0)
3935
{
4036
$this->charset = $charset;
41-
$this->lineNumber = $lineNumber;
42-
}
43-
44-
/**
45-
* @return int<0, max>
46-
*/
47-
public function getLineNo(): int
48-
{
49-
return $this->lineNumber;
37+
$this->setPosition($lineNumber);
5038
}
5139

5240
/**

0 commit comments

Comments
 (0)