Skip to content

fix: export extraction misses/phantoms for TS unicode escapes, Erlang arity, GFM tables, NFC/NFD (closes #437, partial)#457

Open
0xLeif wants to merge 1 commit into
mainfrom
fix/437-export-extraction
Open

fix: export extraction misses/phantoms for TS unicode escapes, Erlang arity, GFM tables, NFC/NFD (closes #437, partial)#457
0xLeif wants to merge 1 commit into
mainfrom
fix/437-export-extraction

Conversation

@0xLeif

@0xLeif 0xLeif commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Problem (partial fix — see Deferred below)

Export-extraction mismatches that produce phantom "no matching export" errors or silently hidden exports:

  1. TS/JS \u escapes: export const caf\u0061 = 4 (the legal identifier cafa) was truncated at the backslash to a bogus caf export — an unfixable phantom.
  2. Erlang arity: exports were emitted as bare names, but Erlang identity is name/arityarea/1 and area/2 are different exports; one was always unmatchable and arity mismatches were invisible. Also % comments were only stripped on the file's last line ((?m) missing), so commented-out -export attributes on earlier lines leaked in.
  3. Indented GFM tables: a 2-space-indented Public API table (valid CommonMark, renders on GitHub) was silently ignored by symbol extraction; duplicate rows were deduped silently.
  4. NFC vs NFD Unicode: a spec documenting naïve (NFC) against source exporting nai\u{0308}ve (NFD) — glyph-identical — produced phantom errors.

Repro (fixture: /var/tmp/scratch/w2/437/)

src/geo.erl (-export([area/2]).), src/u.ts (export const caf\u00e9 = 1;), spec with an indented GFM table documenting area/2 and café.

  • Before: caf\u00e9 truncates to caf; Erlang export is bare area; indented table rows ignored.
  • After: café decodes correctly; Erlang export is area/2 (bare area in a spec still matches for back-compat, but area/1 is correctly a phantom); indented tables parse; duplicate rows warn; NFC spec matches NFD source.

Root cause / Fix

  • exports/typescript.rs: JS_IDENT accepts \uXXXX/\u{...} sequences; decode_js_identifier_escapes decodes them (malformed input passes through untouched).
  • exports/erlang.rs: emit name/arity; (?m) comment stripping; -compile(export_all) support (both atom and list forms).
  • parser.rs (ships in PR fix: frontmatter parsing leniency enables validation bypass (closes #436) #453): TABLE_ROW_RE tolerates 0–3 leading spaces; get_duplicate_spec_symbols warns on duplicate rows.
  • validator.rs (ships in PR fix: frontmatter parsing leniency enables validation bypass (closes #436) #453): symbol_key folds combining diacritics on both sides (with a dependency-free Latin decomposition table); symbols_match lets a bare spec name match an arity-qualified export (areaarea/2) while area/1area/2.

Tests (all in-file, all passing)

test_unicode_escape_identifiers_not_truncated (typescript.rs); test_erlang_commented_out_export_on_non_last_line_not_leaked, test_erlang_comment_with_dollar_dot_and_quotes_on_non_final_line, test_erlang_compile_export_all[_list_form], test_erlang_export_list_and_callback_in_behaviour_module, test_erlang_inline_trailing_comment_inside_multiline_export_list (erlang.rs); test_get_spec_symbols_indented_table, test_get_duplicate_spec_symbols (parser.rs, PR #453); test_unicode_nfc_nfd_export_matching, test_erlang_arity_export_matching (validator.rs, PR #453).

Deferred (remaining #437 bullets, NOT in this PR)

  • Lisp defpackage/defgeneric/defclass extraction
  • Scala 3 inline/given extraction
  • C header typedefs/externs
  • Perl @EXPORT_OK / case-insensitive matching

File overlap note

src/parser.rs and src/validator.rs ship in PR #453 (fix/436-frontmatter-validation); the whole current files there include the #437 table/NFC-NFD/arity-matching changes above. This PR ships src/exports/typescript.rs and src/exports/erlang.rs in full.

Full suite: 1743 passed, 1 pre-existing root-only failure (unrelated). clippy --all-targets -- -D warnings clean.

Closes #437 (partial — deferred bullets listed above)

…entity (closes #437, partial)

TS/JS: identifiers containing �/u{...} escapes are decoded
instead of truncated at the backslash. Erlang: -export identity is
name/arity (area/1 and area/2 are different exports); (?m) comment
stripping; -compile(export_all) support.
@0xLeif
0xLeif requested a review from a team as a code owner July 24, 2026 18:47
@0xLeif
0xLeif requested review from 0xGaspar, Kyntrin and tofu-ux July 24, 2026 18:47
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

❌ Corvin says...

      _
    <(;\  .oO(oh no...)
     |/(\
      \(\\
      " "\\

"I'm pecking through the errors..."

CI Summary

Check Status
Validate action.yml ✅ Passed
Packaged Action Consumer ✅ Passed
Dependency Audit ✅ Passed
Code Coverage ✅ Passed
Format Check ❌ failure
Docs Site ✅ Passed
Spec Validation ❌ failure
Tests (build, test, clippy) ✅ Passed
VS Code Extension ✅ Passed
📋 Spec Validation Details

❌ SpecSync: Failed

Metric Value
Specs checked 62
Passed 62
Errors 1
Warnings 0
File coverage 100% (105/105)
LOC coverage 100% (86936/86936)

Errors

.specsync/sdd.json

  • meaningful changed paths are not covered by an active change: src/exports/erlang.rs, src/exports/typescript.rs

Action Items

  • Review and fix -- meaningful changed paths are not covered by an active change: src/exports/erlang.rs, src/exports/typescript.rs

Generated by specsync · Run specsync check --format github to reproduce


Powered by corvid-pet

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.

Export extraction misses across backends — JS \u escapes, Unicode NFC/NFD, indented tables, Erlang/Lisp/Scala/C-header/Perl

1 participant