Skip to content

[TASK] Add and implement Positionable interface #1232

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Apr 7, 2025
19 changes: 19 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,29 @@ This project adheres to [Semantic Versioning](https://semver.org/).

### Added

- Methods `getLineNumber` and `getColumnNumber` which return a nullable `int`
for the following classes:
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,
`Rule`, `DeclarationBlock`, `RuleSet`, `CSSFunction`, `Value` (#1225)
- `Positionable` interface for CSS items that may have a position
(line and perhaps column number) in the parsed CSS (#1221)

### Changed

- Implement `Positionable` in the following CSS item classes:
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,
`Rule`, `DeclarationBlock`, `RuleSet`, `CSSFunction`, `Value` (#1225)

### Deprecated

- `getLineNo()` is deprecated in these classes (use `getLineNumber()` instead):
`Comment`, `CSSList`, `SourceException`, `Charset`, `CSSNamespace`, `Import`,
`Rule`, `DeclarationBlock`, `RuleSet`, `CSSFunction`, `Value` (#1225, #1233)
- `Rule::getColNo()` is deprecated (use `getColumnNumber()` instead)
(#1225, #1233)
- Providing zero as the line number argument to `Rule::setPosition()` is
deprecated (pass `null` instead if there is no line number) (#1225, #1233)

### Removed

### Fixed
Expand Down
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"ext-iconv": "*"
},
"require-dev": {
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41"
"phpunit/phpunit": "5.7.27 || 6.5.14 || 7.5.20 || 8.5.41",
"rawr/cross-data-providers": "^2.0.0"
},
"suggest": {
"ext-mbstring": "for parsing UTF-8 CSS"
Expand Down
23 changes: 6 additions & 17 deletions src/CSSList/CSSList.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
use Sabberworm\CSS\Parsing\SourceException;
use Sabberworm\CSS\Parsing\UnexpectedEOFException;
use Sabberworm\CSS\Parsing\UnexpectedTokenException;
use Sabberworm\CSS\Position\Position;
use Sabberworm\CSS\Position\Positionable;
use Sabberworm\CSS\Property\AtRule;
use Sabberworm\CSS\Property\Charset;
use Sabberworm\CSS\Property\CSSNamespace;
Expand All @@ -29,8 +31,10 @@
*
* It can also contain `Import` and `Charset` objects stemming from at-rules.
*/
abstract class CSSList implements Renderable, Commentable
abstract class CSSList implements Commentable, Positionable, Renderable
{
use Position;

/**
* @var array<array-key, Comment>
*
Expand All @@ -45,21 +49,14 @@ abstract class CSSList implements Renderable, Commentable
*/
protected $aContents;

/**
* @var int
*
* @internal since 8.8.0
*/
protected $iLineNo;

/**
* @param int $iLineNo
*/
public function __construct($iLineNo = 0)
{
$this->aComments = [];
$this->aContents = [];
$this->iLineNo = $iLineNo;
$this->setPosition($iLineNo);
}

/**
Expand Down Expand Up @@ -258,14 +255,6 @@ private static function identifierIs($sIdentifier, $sMatch)
?: preg_match("/^(-\\w+-)?$sMatch$/i", $sIdentifier) === 1;
}

/**
* @return int
*/
public function getLineNo()
{
return $this->iLineNo;
}

/**
* Prepends an item to the list of contents.
*
Expand Down
21 changes: 5 additions & 16 deletions src/Comment/Comment.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,12 @@

use Sabberworm\CSS\OutputFormat;
use Sabberworm\CSS\Renderable;
use Sabberworm\CSS\Position\Position;
use Sabberworm\CSS\Position\Positionable;

class Comment implements Renderable
class Comment implements Positionable, Renderable
{
/**
* @var int
*
* @internal since 8.8.0
*/
protected $iLineNo;
use Position;

/**
* @var string
Expand All @@ -28,7 +25,7 @@ class Comment implements Renderable
public function __construct($sComment = '', $iLineNo = 0)
{
$this->sComment = $sComment;
$this->iLineNo = $iLineNo;
$this->setPosition($iLineNo);
}

/**
Expand All @@ -39,14 +36,6 @@ public function getComment()
return $this->sComment;
}

/**
* @return int
*/
public function getLineNo()
{
return $this->iLineNo;
}

/**
* @param string $sComment
*
Expand Down
20 changes: 6 additions & 14 deletions src/Parsing/SourceException.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,23 @@

namespace Sabberworm\CSS\Parsing;

class SourceException extends \Exception
use Sabberworm\CSS\Position\Position;
use Sabberworm\CSS\Position\Positionable;

class SourceException extends \Exception implements Positionable
{
/**
* @var int
*/
private $iLineNo;
use Position;

/**
* @param string $sMessage
* @param int $iLineNo
*/
public function __construct($sMessage, $iLineNo = 0)
{
$this->iLineNo = $iLineNo;
$this->setPosition($iLineNo);
if (!empty($iLineNo)) {
$sMessage .= " [line no: $iLineNo]";
}
parent::__construct($sMessage);
}

/**
* @return int
*/
public function getLineNo()
{
return $this->iLineNo;
}
}
72 changes: 72 additions & 0 deletions src/Position/Position.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Position;

/**
* Provides a standard reusable implementation of `Positionable`.
*
* @internal
*
* @phpstan-require-implements Positionable
*/
trait Position
{
/**
* @var int<1, max>|null
*/
protected $lineNumber;

/**
* @var int<0, max>|null
*/
protected $columnNumber;

/**
* @return int<1, max>|null
*/
public function getLineNumber()
{
return $this->lineNumber;
}

/**
* @return int<0, max>
*/
public function getLineNo()
{
$lineNumber = $this->getLineNumber();

return $lineNumber !== null ? $lineNumber : 0;
}

/**
* @return int<0, max>|null
*/
public function getColumnNumber()
{
return $this->columnNumber;
}

/**
* @return int<0, max>
*/
public function getColNo()
{
$columnNumber = $this->getColumnNumber();

return $columnNumber !== null ? $columnNumber : 0;
}

/**
* @param int<0, max>|null $lineNumber
* @param int<0, max>|null $columnNumber
*/
public function setPosition($lineNumber, $columnNumber = null)
{
// The conditional is for backwards compatibility (backcompat); `0` will not be allowed in future.
$this->lineNumber = $lineNumber !== 0 ? $lineNumber : null;
$this->columnNumber = $columnNumber;
}
}
45 changes: 45 additions & 0 deletions src/Position/Positionable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

declare(strict_types=1);

namespace Sabberworm\CSS\Position;

/**
* Represents a CSS item that may have a position in the source CSS document (line number and possibly column number).
*
* A standard implementation of this interface is available in the `Position` trait.
*/
interface Positionable
{
/**
* @return int<1, max>|null
*/
public function getLineNumber();

/**
* @return int<0, max>
*
* @deprecated in version 8.9.0, will be removed in v9.0. Use `getLineNumber()` instead.
*/
public function getLineNo();

/**
* @return int<0, max>|null
*/
public function getColumnNumber();

/**
* @return int<0, max>
*
* @deprecated in version 8.9.0, will be removed in v9.0. Use `getColumnNumber()` instead.
*/
public function getColNo();

/**
* @param int<0, max>|null $lineNumber
* Providing zero for this parameter is deprecated in version 8.9.0, and will not be supported from v9.0.
* Use `null` instead when no line number is available.
* @param int<0, max>|null $columnNumber
*/
public function setPosition($lineNumber, $columnNumber = null);
}
16 changes: 6 additions & 10 deletions src/Property/CSSNamespace.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,16 @@

use Sabberworm\CSS\Comment\Comment;
use Sabberworm\CSS\OutputFormat;
use Sabberworm\CSS\Position\Position;
use Sabberworm\CSS\Position\Positionable;

/**
* `CSSNamespace` represents an `@namespace` rule.
*/
class CSSNamespace implements AtRule
class CSSNamespace implements AtRule, Positionable
{
use Position;

/**
* @var string
*/
Expand Down Expand Up @@ -41,18 +45,10 @@ public function __construct($mUrl, $sPrefix = null, $iLineNo = 0)
{
$this->mUrl = $mUrl;
$this->sPrefix = $sPrefix;
$this->iLineNo = $iLineNo;
$this->setPosition($iLineNo);
$this->aComments = [];
}

/**
* @return int
*/
public function getLineNo()
{
return $this->iLineNo;
}

/**
* @return string
*
Expand Down
16 changes: 6 additions & 10 deletions src/Property/Charset.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

use Sabberworm\CSS\Comment\Comment;
use Sabberworm\CSS\OutputFormat;
use Sabberworm\CSS\Position\Position;
use Sabberworm\CSS\Position\Positionable;
use Sabberworm\CSS\Value\CSSString;

/**
Expand All @@ -14,8 +16,10 @@
* - May only appear at the very top of a Document’s contents.
* - Must not appear more than once.
*/
class Charset implements AtRule
class Charset implements AtRule, Positionable
{
use Position;

/**
* @var CSSString
*/
Expand All @@ -42,18 +46,10 @@ class Charset implements AtRule
public function __construct(CSSString $oCharset, $iLineNo = 0)
{
$this->oCharset = $oCharset;
$this->iLineNo = $iLineNo;
$this->setPosition($iLineNo);
$this->aComments = [];
}

/**
* @return int
*/
public function getLineNo()
{
return $this->iLineNo;
}

/**
* @param string|CSSString $oCharset
*
Expand Down
Loading