Skip to content

Track defined and used CSS names for custom properties and at-rules#611

Merged
bartveneman merged 5 commits into
mainfrom
claude/youthful-cray-qA5U6
Jun 2, 2026
Merged

Track defined and used CSS names for custom properties and at-rules#611
bartveneman merged 5 commits into
mainfrom
claude/youthful-cray-qA5U6

Conversation

@bartveneman
Copy link
Copy Markdown
Member

@bartveneman bartveneman commented Jun 2, 2026

Summary

This PR introduces a new DefinedUsed class to track which CSS names (custom properties, animation names, container names, layer names, and anchor names) are defined versus used in a stylesheet. This enables detection of unused declarations and references to undefined names.

Key Changes

  • New DefinedUsed class (src/defined-used.ts): A utility class that tracks defined and used names, computing four states:

    • defined: Names that are declared
    • used: Names that are referenced
    • unused: Defined but never used
    • unknown: Used but never defined
  • Custom properties tracking: Monitors --custom-property declarations and var() function usage, including nested fallbacks

  • Animation names tracking: Tracks @keyframes definitions and animation-name/animation property references

  • Container names tracking: Monitors container-name property declarations and @container query references

  • Layer names tracking: Distinguishes between @layer ordering statements (define) and @layer blocks/@import layer() (use)

  • Anchor names tracking: Tracks anchor-name declarations and usage in position-anchor, anchor(), and anchor-size() functions

  • Integration with analysis results: Each tracked category now includes defined, used, unused, and unknown arrays in the analysis output

  • Comprehensive test coverage (src/defined-used.test.ts): 50+ tests covering the DefinedUsed class and all tracked CSS name categories

Implementation Details

  • The DefinedUsed class uses Set internally for deduplication and efficient lookups
  • Integration points throughout the CSS parser capture definitions and usages at appropriate AST nodes
  • Existing tests updated to use toMatchObject() where new fields are added to maintain backward compatibility
  • Anchor names specifically track the -- prefix to distinguish from other identifiers

closes #553

claude added 2 commits June 2, 2026 19:40
…ames, container names, layer names, and anchor names

Introduces a reusable `DefinedUsed` class (src/defined-used.ts) that tracks
which names are declared versus referenced using O(1) Set lookups. The class is
exported from the public API so it can be reused by stylelint-plugin and
projectwallace.com.

For each entity type the semantics are:
- Custom properties: declared (`--foo: value`, `@property --foo`) vs used in `var(--foo)`
- Animation names: `@keyframes name` vs `animation-name`/`animation` shorthand
- Container names: `container-name`/`container` shorthand vs `@container name`
- Layer names: `@layer a, b;` ordering statements vs `@layer name { }` blocks and `@import layer(name)`
- Anchor names: `anchor-name: --foo` vs `position-anchor`, `anchor()`, `anchor-size()`

New fields added to:
- `properties.custom`: `defined`, `used`, `unused`, `unknown`
- `atrules.keyframes`: `defined`, `used`, `unused`, `unknown`
- `atrules.container.names`: `defined`, `used`, `unused`, `unknown`
- `atrules.layer`: `defined`, `used`, `unused`, `unknown`
- `properties.anchorNames` (new): `defined`, `used`, `unused`, `unknown`

Closes #553

https://claude.ai/code/session_013z1TNFDKSn5B5XsmKnWsGe
container-name supports multiple names (e.g. container-name: sidebar main).
The containerNames Collection was incorrectly storing the full value text
as a single entry; it now iterates identifiers the same way containerNamesTracking
already did. Also combine the DefinedUsed value and type exports into one statement.

https://claude.ai/code/session_013z1TNFDKSn5B5XsmKnWsGe
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jun 2, 2026

Codecov Report

❌ Patch coverage is 98.38710% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 94.76%. Comparing base (50fac71) to head (35df4d6).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
src/defined-used.ts 95.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #611      +/-   ##
==========================================
+ Coverage   94.25%   94.76%   +0.50%     
==========================================
  Files          18       19       +1     
  Lines        1027     1088      +61     
  Branches      325      349      +24     
==========================================
+ Hits          968     1031      +63     
+ Misses         48       47       -1     
+ Partials       11       10       -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Jun 2, 2026

Bundle Report

Changes will increase total bundle size by 3.73kB (4.64%) ⬆️. This is within the configured threshold ✅

Detailed changes
Bundle name Size Change
analyzeCss-esm 84.27kB 3.73kB (4.64%) ⬆️

Affected Assets, Files, and Routes:

view changes for bundle: analyzeCss-esm

Assets Changed:

Asset Name Size Change Total Size Change (%)
index.js 2.81kB 36.43kB 8.37% ⚠️
index.d.ts 921 bytes 15.59kB 6.28% ⚠️

Files in index.js:

  • ./src/defined-used.ts → Total Size: 713 bytes

  • ./src/index.ts → Total Size: 29.04kB

claude added 3 commits June 2, 2026 20:00
…-case tests

All atrules tests that were using toMatchObject are now toEqual with the
complete expected shape including defined/used/unused/unknown arrays.
Expected values were verified against actual analyzer output.

Also adds dedicated edge-case tests:
- container-name: none is not tracked as a defined container name
- animation-name: none is not tracked as a used animation name
- position-anchor with a non-anchor value does not track

https://claude.ai/code/session_013z1TNFDKSn5B5XsmKnWsGe
Previously spread both sets to arrays and then ran separate filter passes —
4 traversals and unnecessary intermediate work. Now builds defined+unused
in one pass over #defined and used+unknown in one pass over #used.

https://claude.ai/code/session_013z1TNFDKSn5B5XsmKnWsGe
…uting in analyze()

Each define()/use() call now updates all four sets with O(1) operations:
- define(): if already in used → remove from unknown; else add to unused
- use(): if already in defined → remove from unused; else add to unknown

analyze() becomes four spreads with no logic. The early-return guards on
duplicate calls also make repeated define/use calls cheaper than before.

https://claude.ai/code/session_013z1TNFDKSn5B5XsmKnWsGe
@bartveneman bartveneman merged commit c7937b9 into main Jun 2, 2026
5 checks passed
@bartveneman bartveneman deleted the claude/youthful-cray-qA5U6 branch June 2, 2026 20:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for analyzing undeclared/unused custom properties

3 participants