Skip to content
CAI
Software that uses CAICheck a score

symfony/css-selector

52.2

Adequate · 26 September 2026

3.5k

lines of production code

PHP

primary language

4

measurements over time

CAI band scale
CAI trend line
CAI lens gauges

What this system is

This system is the Symfony CssSelector library, which converts CSS selector strings into XPath expressions for use in XML or HTML document processing. It features a modern, object-oriented API with an LRU cache for performance, supporting contemporary CSS pseudo-classes like :has(), :is(), and :where(), as well as CSS namespaces. The implementation relies on a modular parser and extension-based translation architecture to ensure accurate and efficient selector evaluation.

How it got here

2010–2011 — CssSelector modernization and PHP 8.4 upgrade

4 changes.

The CssSelector component underwent a comprehensive rewrite to adopt a non-static, object-oriented API with LRU caching and support for modern CSS pseudo-classes like :has() and :is(). This period also involved refactoring internal node classes for modern PHP features, reorganizing the exception hierarchy for better type safety, and establishing the initial composer.json configuration with a strict PHP 8.4 requirement.

2012–2015 — CSS Selector Component Rewrite

12 changes.

The CssSelector component underwent a comprehensive rewrite, replacing its monolithic parser and XPath translation logic with modular, typed, and high-performance implementations. This effort introduced support for modern CSS features such as :has(), :is(), :where(), and namespaces, while significantly improving parsing accuracy and efficiency. Extensive unit test suites were added to validate the new tokenizer, handlers, shortcut parsers, and the LRU caching mechanism.

Behavioural changes

CSS Selector Node classes rewritten for modern PHP and new pseudo-class support

The Node classes in the CssSelector component have been completely rewritten to extend a new AbstractNode base class and use modern PHP features like typed properties, constructor promotion, and the Stringable interface. This refactor removes the legacy toXpath() method in favor of a getSpecificity() method, standardizing how selector weight is calculated. Additionally, new node types have been introduced to support the :is() (MatchingNode), :where() (SpecificityAdjustmentNode), and :has() (RelationNode) pseudo-classes, while the old OrNode has been replaced by NegationNode to handle :not().

Node · high confidence

CSS selector parsing now supports namespaces

The CssSelector component has been rewritten to support CSS namespaces, allowing selectors like \test\|input.class\ or \test\|element\#id\ to be parsed correctly. This change introduces new shortcut parsers (ClassParser, ElementParser, HashParser, EmptyStringParser) that handle optional namespace prefixes alongside element, class, and ID selectors, ensuring compatibility with the Python cssselect library.

Parser/Shortcut · high confidence

CssSelector component rewritten with non-static API and LRU caching

The CssSelector component has been fully rewritten to replace the previous static \Parser\ class with a new, non-static \CssSelectorConverter\ class. This change introduces an object-oriented API where users instantiate the converter (optionally enabling HTML support) and call \toXPath()\ on the instance, rather than using static methods. The new implementation includes an LRU cache to improve performance for repeated selector conversions and adds support for modern CSS pseudo-classes including \:has()\, \:is()\, \:where()\, \:scope\, and \\*:only-of-type\. The old static API is deprecated, and the component now ships with a \CHANGELOG.md\ documenting these version-specific additions.

(repo-wide) · high confidence

New XPath translation component for CSS selectors

The CssSelector component now includes a new XPath sub-component (Translator, TranslatorInterface, and XPathExpr) that translates CSS selectors into XPath expressions. This new implementation replaces the previous logic, introducing a modular architecture with registered extensions for nodes, combinations, functions, pseudo-classes, and attribute matching, and supports modern PHP features such as constructor property promotion and union types.

XPath · high confidence

Refactored CSS selector-to-XPath translation into a modular extension system

The CSS Selector component's XPath translation logic has been restructured from a monolithic implementation into a modular extension system. The \XPath/Extension\ directory now contains distinct classes (\NodeExtension\, \AttributeMatchingExtension\, \CombinationExtension\, \FunctionExtension\, \PseudoClassExtension\, \HtmlExtension\, \RelationExtension\) that handle specific translation responsibilities. This change introduces support for the \:has()\ pseudo-class via the new \RelationExtension\ and \getRelativeCombinationTranslators\ interface, and adds support for the \:scope\ pseudo-class. It also corrects the translation of \:nth-last-child()\ and fixes the combination logic for \:is()\ and \:where()\ selectors when used with parent selectors.

XPath/Extension · high confidence

Reworked CSS Selector exception hierarchy and namespace

The CSS Selector component has reorganized its exception classes into a dedicated \Symfony\\Component\\CssSelector\\Exception\ namespace. The legacy \SyntaxError\ class has been replaced by a new \ExceptionInterface\ (which extends \\\Throwable\) and specific exception types such as \ParseException\, \ExpressionErrorException\, \InternalErrorException\, and \SyntaxErrorException\. This change improves type safety and provides more granular error handling for CSS selector parsing issues.

Exception · high confidence

Rewritten CSS Selector Tokenizer with Improved Identifier and Escape Handling

The CSS Selector component's tokenizer has been completely rewritten to improve parsing accuracy and performance. This change introduces a new modular architecture with dedicated classes for handling patterns, escaping, and tokenization. Key behavioral improvements include fixing escape pattern recognition and allowing CSS identifiers to start with a dash, aligning the parser more closely with CSS specifications. The new implementation also leverages native PHP features like typed properties and constructor property promotion for better efficiency.

Parser/Tokenizer · high confidence

Rewritten CSS selector parser handlers with typed interfaces

The CSS selector parser's handler components have been completely rewritten to use a new \HandlerInterface\ with a \handle(Reader, TokenStream): bool\ signature, replacing the previous XPath expression classes. Specific handlers for comments, hashes, identifiers, numbers, strings, and whitespace now rely on injected \TokenizerPatterns\ and \TokenizerEscaping\ services, and all internal classes are marked as \@internal\ to signal that they are implementation details not intended for direct consumption.

Parser/Handler · high confidence

Rewritten CSS selector parser with improved performance and new selector support

The CSS selector parser has been completely rewritten to improve performance and add support for modern CSS selectors. The new implementation fixes a quadratic complexity issue in pattern matching, adds support for the :has(), :is(), :where(), and :scope pseudo-classes, and caps the nesting depth of :has() and :where() to prevent excessive resource usage. The parser now uses native PHP types, modern syntax features, and optimized token processing for faster selector evaluation.

Parser · high confidence

Test coverage

Added test coverage for CSS Selector XPath translation; Added tests for CssSelectorConverter caching behavior; Added unit tests for CSS Selector Shortcut Parsers; Added unit tests for CSS Selector parser handlers; Added unit tests for CssSelector Node classes; Added unit tests for the CSS Selector Parser components.

Dependencies

Initial composer.json for Symfony CssSelector with PHP 8.4 requirement

The package now includes a composer.json manifest defining the Symfony CssSelector library, which converts CSS selectors to XPath expressions. This configuration enforces a minimum PHP version of 8.4.1 and utilizes PSR-4 autoloading for the Symfony\\Component\\CssSelector namespace, while explicitly excluding the Tests directory from the classmap to optimize performance.

(dependencies) · high confidence

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

How this codebase got here

This is the PUBLIC form of this artifact. Findings are listed in full, but the details of SECURITY findings — which rule fired, in which file, on which line, and how to fix it — are deliberately withheld, and any secret-scanner results are excluded entirely. Where detail is absent here it was REMOVED FOR PUBLICATION; it is not missing from the analysis. The complete artifact is available from the repository owner.

Score

  • CAI 45 → 52 (+7.3)
  • Rubric changed (rubric-2026.08.15 → rubric-2026.09.15) — scores are not directly comparable.

Lenses

  • Code Health 96 → 95 (-0.8)
  • Architecture 94 → 100 (+5.4)
  • Maturity 34 → 32 (-1.4)
  • Readiness 24 → 43 (+18.6)
  • Security 91 → 99 (+7.9)

Resolved (11)

  • Coverage not measured — test suite did not build
  • Dimension evaluation failed
  • Duplicated block (11 lines × 5) (Tests/XPath/TranslatorTest.php)
  • Duplicated block (11 lines × 6) (Tests/Parser/ParserTest.php)
  • Duplicated block (6 lines × 2) (XPath/Extension/FunctionExtension.php)
  • Duplicated block (7 lines × 2) (Parser/Parser.php)
  • Duplicated block (7 lines × 2) (Tests/XPath/TranslatorTest.php)
  • High: security finding (details withheld)
  • No exposed public API
  • No tests found
  • Test reliability not included

New (11)

  • Documentation: no installation or build instructions (README.md)
  • Documentation: no usage examples (README.md)
  • Duplicated block (11 lines × 2) (XPath/Extension/FunctionExtension.php)
  • Duplicated block (7 lines × 2) (Parser/Parser.php)
  • Further sole-owners (lower concentration)
  • Off-boarding risk: anonymized user #1
  • Orphaned files with no living knowledge
  • Parser.parseAttributeNode (cognitive 16) (Parser/Parser.php)
  • Parser.parseSimpleSelector (cognitive 84) (Parser/Parser.php)
  • Parser.parseSimpleSelector (cyclomatic 42) (Parser/Parser.php)
  • TodoComment (XPath/Extension/FunctionExtension.php)

Changes since last survey

  • 7 commits — 5 feature/other, 2 fixes

By area

  • (repo) — 4 commits
  • Parser/Parser.php — 1 commit
  • Parser/Reader.php — 1 commit
  • Tests/XPath — 1 commit

Notable commits

  • fix: [CssSelector] Fix :disabled and :enabled inside nested fieldsets
  • fix: [CssSelector] Fix quadratic token probing in Reader::findPattern()
  • change: Merge branch '6.4' into 7.4
  • change: Merge branch '6.4' into 7.4
  • change: Merge branch '7.4' into 8.1
  • change: Merge branch '7.4' into 8.1
  • change: [CssSelector] Cap the nesting depth of :is() and :where()

Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.

Survey your own repository

symfony/css-selector was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.

About this page

  • The score is its most recent published measurement, taken on 26 September 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
  • Measured at commit 08e2905152a39cf3fd1745d83f8c483e258887d9 — the exact code this score is about.
  • Scored under rubric-2026.09.15 — the same rubric and the same method as every other entry in this index.
  • Measured by watchdog.canine.dev using codehealth-analyzer preprod-a15879f6f801.