Skip to content

feat!: classify qualified generic operands as types - #29

Merged
exKAZUu merged 1 commit into
mainfrom
fix/qualified-generic-operands
Oct 19, 2026
Merged

exKAZUu merged 1 commit into
mainfrom
fix/qualified-generic-operands

Conversation

@exKAZUu

@exKAZUu exKAZUu commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

Why

Qualified arguments such as typing.List[numpy.ndarray] are parsed as ordinary attributes, so the shipped query misses ndarray as a type even though qualified generic bases and unpacked operands already expose structured type names.

Requirements

  • required: Improve the fork by reviewing our issues and eligible upstream issues, PRs and recent commits; create a dedicated nonduplicate PR for each item worth resolving, ignoring backward compatibility.

  • required: Run review-booster and complete-pr concurrently, then release the changes.

  • required: Preserve valid Python annotation and value-expression syntax, following declarations, existing type-name captures, and ordinary value/default-expression trees.

  • chosen: Resolve the remaining qualified generic-argument role gap through the existing structured type-parameter expression helper. Plain and unpacked operands should expose the same member_type names to the shipped type-highlighting query; the existing expression fallback must remain available for expression-valued annotations.

  • chosen: Keep module qualifiers outside type captures and preserve ordinary value/default subscripts as expressions, because their identical spelling does not make them type operands.

  • chosen: Verify the public syntax tree and shipped query together, plus a real incremental edit, because highlighting-only checks can conceal a wrong operand tree.

  • chosen: Publish changed public operand trees as a major release; consumers traversing qualified operands must adapt even though syntax remains accepted.

  • chosen: Keep bare contextual-keyword generic bases and composite class-base unpacks as dedicated follow-ups. The broad improvement request still applies to them.

  • chosen: Retain the existing type alternative alongside the structured operand helper. The paired 315-case probe exposed five lost type-capture cases for valid slice/constrained operands when the old alternative was replaced; the helper supplements the current syntax instead of removing that fallback.

  • chosen: Keep three explicit GLR conflicts where ordinary and structured generic paths share a prefix: the generic base, a named expression, and completed argument brackets. The generator reports these three ambiguities; keep both paths until following syntax settles the role, because the earlier helper-only variant lost five existing constrained/slice type-capture cases. The bounded corpus/oracle and depth/union probes validate both alternatives.

Customer Summary

Qualified names inside generic type arguments expose member_type within their type operand. Type highlighting captures the terminal name and excludes module qualifiers. This changes public operand trees and requires a major release.

Technical Summary

grammar.js adds the existing structured operand helper beside the current type alternative. Three narrow GLR conflicts preserve both paths until the surrounding syntax establishes the role. Keeping the current alternative preserves valid slice/constrained annotation captures that a replacement-only implementation lost. The shipped query already handles the structured tree.

The highest-risk boundary is distinguishing annotation operands from identical value/default expressions while preserving nested unions and following declarations.

Testing

  • bun run build/ci, then 207 corpus cases through an explicitly built native library and the optimized Wasm artifact.
  • bun wb test across seven relevant files: 14 tests, including two new public API/query tests for operand ownership and incremental edits.
  • Paired published 3.0.0/current public API comparison: 315 CPython-checked sources, 245 valid; no introduced acceptance/rejection, lost existing type captures, changed ordinary value trees, missing qualified terminal captures, or lost following declarations.
  • Depths 10–160 and unions of 32–512 operands retain complete structure and type captures. All existing corpus source files are byte-identical.
  • bun run verify passes. CI runs the full suite.

Notes

Bare contextual-keyword generic bases and composite class-base unpacks remain dedicated follow-ups under the broader improvement request.

Verification reports seven existing code-gauge errors and 46 warnings, all outside changed code: GrammarTests.testFuncdef in the Python 2 LF/CRLF fixtures (159 NCSS each), the corresponding Python 3 fixtures (187 each), the Python 3.8 fixture (1,200 file NCSS and 232 NCSS in test_funcdef), and the external scanner (175 complexity/202 NCSS). Rewriting upstream language fixtures or the scanner would expand this operand-role change substantially. The LF/CRLF fixtures intentionally duplicate syntax; a future explicit code-gauge.config.json exclusion could document that duplication. This PR does not change that configuration.

Co-authored-by: WillBooster (Codex CLI) <agent@willbooster.com>
@exKAZUu exKAZUu self-assigned this Oct 19, 2026
@exKAZUu
exKAZUu merged commit 8fedc3e into main Oct 19, 2026
10 checks passed
@exKAZUu
exKAZUu deleted the fix/qualified-generic-operands branch October 19, 2026 10:43
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