Skip to content

feat(parsers): replace Swift regex parser with swift-symbolgraph-extract#38

Merged
grdsdev merged 14 commits into
mainfrom
claude/vigilant-wilson-62e91c
Jun 23, 2026
Merged

feat(parsers): replace Swift regex parser with swift-symbolgraph-extract#38
grdsdev merged 14 commits into
mainfrom
claude/vigilant-wilson-62e91c

Conversation

@grdsdev

@grdsdev grdsdev commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

Summary

Replaces the handrolled swift-parser.ts (a ~170-line regex scanner with brace-depth tracking) with swift package dump-symbol-graph — the Swift compiler's own tool for public API surface extraction — and a thin TypeScript normalizer.

Why

The regex parser had known blind spots: multi-line declarations, #if conditional compilation, attributes spanning lines, and could not model access control semantics (@_spi, @usableFromInline, re-exports). Root cause: regex cannot reliably parse Swift. swift package dump-symbol-graph uses the Swift compiler and gets it right by construction.

Approach

swift package dump-symbol-graph              # builds + extracts all library targets
  --minimum-access-level public              # filter at source — only public/open symbols
  --skip-synthesized-members                 # suppress _Concurrency actor conformance noise
  → <triple>/symbolgraph/*.symbols.json

jq -s '[.[] | .symbols[]]' *.symbols.json   # merge into flat array
  → merged-raw.json

normalize-symbolgraph <merged-raw.json> <root>   # thin TS normalizer (new)
  → ParseResult JSON
  → check-api-symbols  (unchanged)

Changes

Added

  • src/normalize-symbolgraph.ts — core normalizer: SymbolGraphSymbol[]ParseResult
  • src/normalize-symbolgraph-cli.ts — CLI entry point (npm run normalize-symbolgraph)
  • test/normalize-symbolgraph.test.ts — 103 tests (kind mapping, name construction, file path, fixture smoke tests)
  • test/fixtures/symbolgraph-sample.json — real dump-symbol-graph output (17 symbols, public/open only)

Removed

  • src/swift-parser.ts, src/parse-swift.ts — regex parser
  • test/swift-parser.test.ts — regex parser tests

Modified

Key decisions

  • --minimum-access-level public: filters at source, so the normalizer needs no access-level check of its own
  • --skip-synthesized-members: prevents _Concurrency protocol conformance methods (e.g. withSerialExecutor) from generating false-positive "new symbol" CI failures when a PR adds a new public actor
  • || true on extraction: dump-symbol-graph also tries test targets, which can fail to load on CI runners; library targets land before the test-target attempt, so || true + a file-count guard lets the step continue correctly
  • macos-latest runner: Swift is pre-installed; avoids swift-actions/setup-swift overhead on ubuntu

Test plan

  • 103 tests pass (npm test — 11 files)
  • TypeScript strict check clean (npm run typecheck)
  • Fixture is real dump-symbol-graph --minimum-access-level public output (not hand-authored)
  • E2E verified: full CI run on supabase-swift passed (both validate and check jobs)

@grdsdev grdsdev requested review from a team as code owners June 19, 2026 14:30
@grdsdev grdsdev force-pushed the claude/vigilant-wilson-62e91c branch from 7cb1a77 to 5f182e3 Compare June 19, 2026 14:33
@grdsdev grdsdev force-pushed the claude/vigilant-wilson-62e91c branch from ca944df to 4471c55 Compare June 23, 2026 09:05

@spydon spydon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use the swift package dump-symbol-graph instead of going as low-level as we do in this PR?

swift package dump-symbol-graph \
  --minimum-access-level public \
  --skip-synthesized-members \
  --output-directory ./symbolgraph

…raph

Replaces the manual swift build + module-discovery loop + swift-symbolgraph-extract
invocation with a single `swift package dump-symbol-graph` call, which handles
build, module discovery, and extraction internally.
@grdsdev

grdsdev commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

Good call — replaced the manual swift build + module-discovery loop + swift-symbolgraph-extract invocation with a single swift package dump-symbol-graph --minimum-access-level public --skip-synthesized-members call (commit 82af3bf). Drops ~30 lines and removes the need to resolve TRIPLE/SDK/-I flags manually.

🤖 Addressed by Claude Code

…e dump-symbol-graph)

swift package dump-symbol-graph always writes to .build/<triple>/symbolgraph.
Locate it with `find .build -maxdepth 3 -type d -name "symbolgraph"` instead.
swift package dump-symbol-graph tries all targets including test targets.
Test modules can't be loaded in CI SDK search paths. Library target files
land before the test-target attempt, so || true lets the step continue.
Guard ensures the step still fails if zero files were produced.

@spydon spydon left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The symbol graph should be regenerated with swift package dump-symbol-graph --minimum-access-level public --skip-synthesized-members I think?
If you do that the the access-filter assertions can be dropped.

…filter assertions

Regenerate symbolgraph-sample.json with swift package dump-symbol-graph
--minimum-access-level public --skip-synthesized-members. The fixture now
reflects actual CI output: only public/open symbols, no InternalClass.

Remove the access-filter test block and the "excludes InternalClass" smoke
test — with --minimum-access-level public enforced upstream, those inputs
can never arrive at the normalizer.
@grdsdev

grdsdev commented Jun 23, 2026

Copy link
Copy Markdown
Collaborator Author

Done in commit a88c801 — fixture regenerated with swift package dump-symbol-graph --minimum-access-level public --skip-synthesized-members (only public/open symbols, InternalClass absent from output), and the access-filter test block + the excludes InternalClass smoke assertion removed (5 tests dropped, 103 remain).

🤖 Addressed by Claude Code

--minimum-access-level public on dump-symbol-graph ensures only public/open
symbols reach the normalizer. Remove the accessLevel field from
SymbolGraphSymbol and the redundant filter loop in normalizeSymbolGraph.
@grdsdev grdsdev merged commit 80529a7 into main Jun 23, 2026
3 checks passed
@grdsdev grdsdev deleted the claude/vigilant-wilson-62e91c branch June 23, 2026 10:37
grdsdev added a commit that referenced this pull request Jun 23, 2026
…icts

Merge origin/main (PRs #37#40) into this branch:
- #37: sdk-parse-ignore → .sdk-parse-ignore (already synced)
- #38: Dart symbol extractor
- #39: Swift symbolgraph parser (replaces regex parser, deletes swift-parser.test.ts)
- #40: CODEOWNERS, README, CLAUDE.md updates

Conflict resolutions:
- package.json: keep both normalize-griffe (ours) and normalize-symbolgraph (main)
- validate-sdk-compliance.yml: add Python steps alongside Dart/Swift symbolgraph steps;
  conditions on Resolve/Parse steps now exclude python, swift, and dart
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.

2 participants