Skip to content

unified: Declare exposed fields on supertypes - #22536

Draft
asgerf wants to merge 3 commits into
github:mainfrom
asgerf:unified/supertype-fields
Draft

asgerf wants to merge 3 commits into
github:mainfrom
asgerf:unified/supertype-fields

Conversation

@asgerf

@asgerf asgerf commented Sep 9, 2026 •

Copy link
Copy Markdown
Contributor

Supertypes in ast_nodes.yml can now have a list of fields to expose in the generated QL class. This replaces the previous rule from #22507 where fields that were common among all subtypes were automatically hoisted to supertypes.

Compared to automatic hoisting, manually-declared supertype fields work better in a few scenarios:

  • There are some subtypes where the field has a more precise type thus failing an exact signature match
  • Adding a new subtype that lacks a previously-common field can cause a breaking AST change.
  • Sometimes it's just nice to have getters for fields that are present in the common case, but some subtypes are lacking it.

This PR uses the feature for the callable supertype:

  callable:
    subtypes:
      - top_level
      - function_expr
      - function_declaration
      - constructor_declaration
      - destructor_declaration
      - accessor_declaration
      - initializer_declaration
    fields:
      parameter*: parameter
      body?: block

Previously the body field was hoisted automatically, but not parameter, because some callables can't have parameters (like top-level).

@asgerf asgerf added the no-change-note-required This PR does not need a change note label Sep 9, 2026
@asgerf
asgerf requested a balanced review from Copilot September 9, 2026 19:06

/** Gets the node corresponding to the field `parameter`. */
final F::Parameter getParameter(int i) {
final override F::Parameter getParameter(int i) {
Comment thread unified/ql/lib/codeql/unified/internal/Ast.qll Fixed

/** Gets the node corresponding to the field `parameter`. */
final F::Parameter getParameter(int i) {
final override F::Parameter getParameter(int i) {

/** Gets the node corresponding to the field `parameter`. */
final F::Parameter getParameter(int i) {
final override F::Parameter getParameter(int i) {

/** Gets the node corresponding to the field `parameter`. */
final F::Parameter getParameter(int i) { unified_function_expr_parameter(this, i, result) }
final override F::Parameter getParameter(int i) {

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

The generated unified Callable now declares abstract parameter accessors, but some concrete Callable subtypes don’t implement them, and the generator change likely breaks supertypes that have subtypes but no declared fields.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Review tier: Lite
Findings: 1 High severity · 1 Medium severity

New issues introduced by this change (2)
Severity Finding
High severity unified/​ql/​lib/​codeql/​unified/​internal/​Ast.qll — Callable now declares getParameter/getAParameter as abstract, but several concrete…
Medium severity shared/​tree-sitter-extractor/​src/​generator/​ql_gen.rs — compute_exposed_predicates now makes union (supertype) classes expose only the predicates derived…
What changed in this PR

This PR extends the Yeast/unified AST schema format so supertypes can explicitly declare a set of exposed fields, and updates the tree-sitter QL generator and unified AST output to surface those fields (notably callable.parameter) on the generated supertype class.

Changes:

  • Add a “detailed” supertypes YAML form supporting subtypes + fields, with JSON round-tripping and tests.
  • Update tree-sitter extractor data structures and QL generator to carry/emit supertype-declared field predicates.
  • Regenerate unified Ast.qll so Callable exposes parameter accessors and members override them.
File Description
unified/​ql/​lib/​codeql/​unified/​internal/​Ast.qll Regenerated unified AST QL classes; adds Callable.getParameter/getAParameter and marks member implementations as override.
unified/​extractor/​tests/​corpus_tests.rs Minor Rust formatting cleanup for Bazel RUNFILES_DIR handling.
unified/​extractor/​ast_types.yml Switch callable supertype to detailed form and declare exposed parameter* and body? fields.
shared/​yeast/​doc/​node-types-yaml.md Document the new detailed supertype syntax and field semantics.
shared/​yeast-schema/​src/​schema.rs Formatting-only refactor of field_types accessor signature.
shared/​yeast-schema/​src/​node_types_yaml.rs Parse/convert detailed supertypes, factor field conversion, add YAML↔JSON round-trip tests for supertype fields.
shared/​tree-sitter-extractor/​src/​node_types.rs Extend union (supertype) entries to retain declared fields/children for codegen.
shared/​tree-sitter-extractor/​src/​generator/​ql_gen.rs Change how exposed predicates are computed/hoisted, and add tests for “expose only declared supertype fields”.
shared/​tree-sitter-extractor/​src/​generator/​mod.rs Update pattern matches for the expanded EntryKind::Union shape.
shared/​tree-sitter-extractor/​src/​extractor/​mod.rs Update pattern matches for the expanded EntryKind::Union shape in type matching.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread unified/ql/lib/codeql/unified/internal/Ast.qll Outdated
Comment thread shared/tree-sitter-extractor/src/generator/ql_gen.rs
F::Block getBody() { none() }

/** Gets the node corresponding to the field `parameter`. */
F::Parameter getParameter(int i) { none() }
Supertypes in ast_nodes.yml can now have a list of fields to expose in the generated QL class. Callable.parameter is then exposed, which was previously not exposed because some callables cannot have parameters, but it's useful to have the getter available anyway.
@asgerf
asgerf force-pushed the unified/supertype-fields branch from 2d3cecb to 218aa65 Compare September 24, 2026 13:03

Copilot AI 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.

Copilot review overview

🟡 Changes recommended

Nested inheritance, refined return overrides, and in-memory schema registration are currently incomplete.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
Resolved since last review (2)

Comment on lines +869 to +870
Some(node_types::EntryKind::Union { .. }) => {
field_predicates.get(type_name).cloned().unwrap_or_default()
Comment on lines 1055 to +1057
// A field getter that's identically defined (in signature) by
// every member of one of this node's direct supertypes is an
// override of the corresponding `abstract` predicate declared
// there.
// override of the corresponding predicate declared there.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation no-change-note-required This PR does not need a change note

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants