Skip to content

feat(#20): --@swell.<attr> comment hints on analyzed-single-truth - #34

Open
wokalski wants to merge 1 commit into
analyzed-single-truthfrom
fix/comment-hints-on-analyzed
Open

feat(#20): --@swell.<attr> comment hints on analyzed-single-truth#34
wokalski wants to merge 1 commit into
analyzed-single-truthfrom
fix/comment-hints-on-analyzed

Conversation

@wokalski

Copy link
Copy Markdown
Contributor

Summary

Closes #20 on top of #32 (analyzed-single-truth).

A clean reimplementation of #23 using the new internals — the AST-driven Analyzed pipeline + pg_util helpers already had everything we needed.

How it works

pg_query::scan returns every -- / /* */ as a token with byte positions; pg_query::parse exposes ResTarget.location per target-list entry. A comment attaches to the column whose ResTarget.location is the largest one less-or-equal to the comment's start. String literals + dollar-quoted bodies are naturally excluded by the scanner.

Attributes

  • nullable — force nullable: true
  • nonnullable / nonnull / notnull — force nullable: false
  • type=T or type: T — verbatim TS type

Multiple comments stack on the same column. Works on SELECT target lists and DML RETURNING lists. The existing alias-suffix form (col! / col?) still parses for back-compat; comment hints take precedence.

Wired in

When any hint applies the analyzer drops the base-column table_ref for that column, so the override surfaces verbatim in the emitted .d.ts instead of being masked by an indexed-access (Table[\"col\"]) lookup.

SELECT email --@swell.nullable
FROM billing.users WHERE id = \$1;
-- → { email: string | null }   (instead of BillingUsers[\"email\"] | null)

SELECT metadata /*@swell.type=UserMeta*/ AS meta
FROM billing.users WHERE id = \$1;
-- → { meta: UserMeta }

Test plan

  • 11 unit tests in comment_hints.rs covering line/block forms, the type= and type: separators, stacked + comma-separated attrs, attribution to the preceding column, RETURNING lists, parse-failure tolerance, and string-literal isolation.
  • 7 corpus tests in billing.md exercising the same matrix end-to-end against live Postgres.

🤖 Generated with Claude Code

Closes #20 on top of analyzed-single-truth.

`pg_query::scan` exposes every `--` / `/* */` as a token with byte
positions; `pg_query::parse` exposes `ResTarget.location` per
target-list entry. A comment attaches to the column whose
`ResTarget.location` is the largest one less-or-equal to the
comment's start. String literals + dollar-quoted bodies are
naturally excluded by the scanner.

Attributes supported (case-insensitive):
- `nullable` — force `nullable: true`
- `nonnullable` / `nonnull` / `notnull` — force `nullable: false`
- `type=T` or `type: T` — verbatim TS type

Stacking is allowed (multiple comments on one column, or
comma-separated attrs in a single comment). Works on SELECT
target lists and DML RETURNING lists.

Hints take precedence over the SQLx-style `col!` / `col?` markers
and over the inferred verdict. When any hint applies the analyzer
drops the base-column `table_ref`, so the override shows verbatim
in the emitted TS instead of being masked by an indexed-access
(`Table["col"]`) lookup.

11 unit tests in `comment_hints.rs` and 7 corpus tests in
`billing.md` covering both forms, attribution to the preceding
column, stacking, RETURNING, and string-literal isolation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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