Skip to content

feat: IPv6 canonicalization to RFC 5952 behind the experimental flag#498

Open
SJrX wants to merge 1 commit into
grammar-value-coloringfrom
ipv6-canonicalization
Open

feat: IPv6 canonicalization to RFC 5952 behind the experimental flag#498
SJrX wants to merge 1 commit into
grammar-value-coloringfrom
ipv6-canonicalization

Conversation

@SJrX

@SJrX SJrX commented Jun 27, 2026

Copy link
Copy Markdown
Owner

What

A weak-warning inspection + quick-fix that offers to rewrite a non-canonical IPv6 address to its RFC 5952 form (e.g. 2001:DB8:0:0:0:0:0:12001:db8::1), anywhere an IPv6 address appears in a grammar-validated value.

  • Ipv6.kt — pure-Kotlin RFC 5952 canonicalization (lowercase hex, :: for the longest zero run, etc.).
  • Ipv6CanonicalFormInspection — walks the grammar's labeled regions (the Labeled spans from the value-coloring layer) and flags any IPv6-address span that isn't canonical.
  • CanonicalizeIpv6QuickFix — rewrites it.

Why it's a follow-up on #497

It reuses the value-coloring layer's labeledRegions — that's how it finds "the whole IPv6 address" as one span within a larger value (the "fix an IPv6 anywhere it shows up" mechanism). So it's stacked on #497 (grammar value coloring); retarget to 242.x once that merges.

Gating

The inspection returns EMPTY_VISITOR unless ExperimentalSettings.useGrammarParseEngine is on — off by default, consistent with the other grammar-engine features. It's a WEAK_WARNING (style, not error).

Tests

Ipv6Test (the canonicalization function across RFC 5952 cases) and Ipv6CanonicalFormInspectionTest (end-to-end inspection + fix).

Verification

./gradlew test and ./gradlew test -Dsystemd.unit.grammarParseEngine=true both pass.

🤖 Generated with Claude Code

Offers a quick-fix to rewrite a non-canonical IPv6 address to its recommended form.
Behind the experimental flag.

- canonicalizeIpv6 (pure, dependency-free): parses to 8 groups and reformats per RFC
  5952 §4 — lowercase hex, drop leading zeros, compress the longest zero run to "::"
  (leftmost on ties, only for runs of 2+, never a single zero group). Returns null for
  non-IPv6 input and, for now, for embedded-IPv4 (§5 mixed notation) addresses.
- Combinator.labeledRegions(value): the grammar's explicit Labeled spans (e.g. a whole
  IP address) from the first fully-valid parse — lets features act on semantic spans.
- Ipv6CanonicalFormInspection: flag-gated; for grammar-backed options it scans labeled
  spans and registers a WEAK_WARNING + CanonicalizeIpv6QuickFix on any IPv6 that isn't
  already canonical. Reuses the IPV4_ADDR/IPV6_ADDR Labeled(LITERAL) spans we added for
  coloring, so no IPv6-specific engine markers were needed.

Tests: canonicalizer cases incl. zero-run/tie/single-zero/idempotence/non-IPv6; e2e
warning + quick-fix rewriting 2001:DB8::1 -> 2001:db8::1, and nothing when canonical or
the flag is off.

Closes #363. Refs #467

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown

Unit Test Results (grammar engine true)

1 176 tests  +9   1 176 ✅ +9   48s ⏱️ ±0s
  308 suites +2       0 💤 ±0 
  308 files   +2       0 ❌ ±0 

Results for commit dda42cf. ± Comparison against base commit 6cd5561.

@github-actions

Copy link
Copy Markdown

Unit Test Results (grammar engine false)

1 176 tests  +9   1 176 ✅ +9   49s ⏱️ -1s
  308 suites +2       0 💤 ±0 
  308 files   +2       0 ❌ ±0 

Results for commit dda42cf. ± Comparison against base commit 6cd5561.

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.

1 participant