Skip to content

feat(ast): resolve C-family Doxygen documentation owners #1671

Open

Description

@dekobon

Objective

Turn existing C-family Doxygen recognition into useful owner associations without overstating macro, conditional or named-target resolution.

Umbrella: #1654 · Planning ID: D14
Completion prerequisites: D25: #1662, D26: #1663

LANG coverage: C, Cpp, Mozcpp, Objc.

Development can start after D05/D06 interfaces exist. Completion is blocked by D25/D26 infrastructure and requires this adapter's own conformance cases, scaling probes for new work and fuzz seeds.

Shared architecture and constraints

Follow the umbrella's shared contracts. AST recognition serves two consumers: exact legacy convention/coverage streaming for root LOC, and richer source documentation for owner lookup and local text. Source attachment, profile eligibility and physical metric ownership are separate. Preserve the legacy candidate view before run selection, original emission timing, and metrics-only early exits.

Documentation fragments, logical documents and convention-qualified owner edges have separate identities. Source offsets refer to the actual parsed buffer and included ranges. The index is caller-owned, immutable and source-bound; lookup validates tree/index identity. Complete text means local decoded/cleaned content with forward source mapping, not inherited or generator-expanded documentation.

Implementation touchpoints

  • big-code-analysis-ast/src/roles/c.rs, big-code-analysis-ast/src/roles/cpp.rs, big-code-analysis-ast/src/roles/mozcpp.rs, big-code-analysis-ast/src/roles/objc.rs: current shared role recognition; read the contributor reference in roles/mod.rs.

  • big-code-analysis-ast/src/roles/doc_tests/: existing per-language recognition fixtures; add independent owner/text expectations.

  • big-code-analysis-ast/src/lang_helpers/doxygen.rs

  • big-code-analysis-ast/src/checker/doxygen_doc_binding.rs

  • big-code-analysis-ast/src/checker/{c,cpp,mozcpp,objc}.rs

  • big-code-analysis-ast/src/documentation C-family adapter

  • big-code-analysis-ast/src/c_macro.rs

Implementation steps

  • Build owner resolution on DoxygenRow/id-keyed candidate fragments with explicit context requirements and existing no-reentry memo protocol.

  • Support leading/all-kept blocks, trailing member docs, in-body descriptions, declaration-signature docs, standalone file/page/group/explicit-target blocks and gathering.

  • Resolve previous-member and individual declarator/slot owners, preserving wrapper evidence and shared-document edges.

  • Record conditional/recovery targets as candidates until source proves a concrete owner; current contains-any-declaration boolean is insufficient to select a branch.

  • Extract only structural naming metadata needed for association. Queue forward names and finalize with adapter-defined same-file scope/kind/signature keys; unresolved overloads/missing/ambiguous targets remain explicit.

  • Unify gathered and unbound evidence without losing the gatherer or duplicating text/coverage; keep legacy emissions in their physical spaces.

  • Resolve parsed-source names after masking; comments retain raw text. Do not infer name_masked from dollar bytes or invent original names. Retain positional records even when a named link cannot resolve.

  • Preserve per-question memoization for nested preprocessor checks and separate source/legacy view answers. Recheck relevant fix(loc): tool-vs-bca doc-comment attachment divergences left by #1613 #1646 cases, keeping any changed policy explicit.

Tests and edge cases

  • Conditional per struct depth and nested conditional chains, ERROR wrappers, aliases, member-pointer data versus method templates, and current continuation/preprocessor masking distinctions in all four grammars.

  • All four grammars: leading docs on functions/types, trailing docs on members/parameters, in-body description and signature placements.

  • Multi-declarator ownership, anonymous/slot forms and Objective-C methods/properties/protocols.

  • @file gathers older blocks, line gatherer joins, multiple structural blocks and EOF gatherer.

  • Forward explicit name, duplicate/overloaded names, missing symbol and conditional alternatives; no first-wins or all-candidates-as-resolved behavior.

  • Source with preproc masking versus caller-written dollar spelling: positional association survives; unavailable original-name link stays unresolved.

  • Deep nested #ifdef with source/legacy queries in both orders, plus included-range gaps and local recovery.

  • Exact selected source spans and physical DLOC row identities; Cpp/Mozcpp parity for constructs their grammars share.

Use independently specified expected owners, fragment counts/order, byte ranges, text and availability. Pair them with separate legacy metric assertions where relevant. Do not sort/trim observed results, rely only on facade/delegate equality, or accept generated snapshots without an expected-value anchor. Use verbatim source for EOF/CRLF cases. Perturb the decision-bearing expression and confirm the intended assertion fails; use the maintained utils/perturb.py only on tracked, clean targets, recording or stashing real work first. Multi-target cargo runs require --no-fail-fast; include the mutated crate and dependent crates before claiming a unique guard. Keep irreproducible fixtures/manifests in tests, maintained utils or an issue attachment, following .claude/rules/temp-files.md.

Acceptance criteria

  • C/Cpp/Mozcpp/Objc all provide useful declaration/text results with honest uncertainty.
  • No new symbol-table or macro-expansion promise; no metric owner reassignment.
  • Gathering, trailing resolution, many-owner output and conditional depth have discriminating tests/probes/seeds.

Verification and completion evidence

  • Follow current role-census/role-coverage/role-bypass requirements and applicable role-parity-corpus checks. Preserve independent semantic fixtures; refresh .role-coverage-observed.txt when any sampled corpus gitlink changes.

  • Put revisions, exact commands, tool versions and durable input links beside parity/coverage claims; host-local evidence paths are not citations.

  • Recheck current source and the prerequisite contracts/baseline applicable to this issue; record intentional changes to the premises.

  • Run focused production-path tests and affected language siblings. Use package-isolated -p big-code-analysis-ast / -p big-code-analysis feature builds; workspace feature unification is not isolation.

  • Run the repository's required checks for the touched surfaces. For implementation changes: make worktree-setup, make pre-commit read from its BCA_GATE: verdict, and relevant test-language membership comparison. Add scaling and chain-audit checks for traversal changes; run make fuzz-check and seed replay for fuzz changes.

  • Record exact test/perturbation/probe evidence in a completion comment and update this body. Review unexpected metric drift before snapshot acceptance; follow baseline and integration-submodule discipline if behavior deliberately changes.

  • Land public API documentation, re-export/stability review and changelog entries with the originating API change. Keep unrelated CLI/web/Python surfaces outside this issue unless explicitly listed.

Revalidation against main (2026-11-04)

Source baseline inspected: 07822c69211fe851c452ac6c0ebbd99cf92589a5. Relevant landed work: PR #1769, PR #1774, PR #1804. These are implementation updates to the existing acceptance criteria; this review does not mark extraction work complete.

  • Doxygen entry recognition is now id-keyed roles/c_family.rs fragments composed via DoxygenRow. Preserve old_names_are_the_row alias coverage and the ERROR/context logic around the row; do not reconstruct the old kind-name match.

  • conditional_declares uses MemoQuestion::ConditionalDeclares and a one-entry parent context. It is deliberately exact only for gates that inspect at most parent. A new depth-reading source-owner gate needs a separate appropriately scoped context; blindly copying the full chain per conditional was measured quadratic.

  • Preserve the two defenses against reentering conditional analysis and tests on both cached and uncached paths. Add independent conditionals at growing struct depth, not just a single nested #ifdef chain.

  • C++ member templates/member pointers changed in PRs fix(npa,getter,npm): batch fix for #1299, #1706 and #1401 #1721/fix: batch 2026-11-03-2 (8 issues) #1804. Reuse AST c_declarator facts where relevant to owner normalization; do not infer declaration ownership from old NPA/NPM outputs or duplicate metric policy.

  • fix(metrics/loc): C family, Ruby, Elixir lose a bare \ row #1801 continuation-row gap remains open for the C family. Source/legacy baseline and mapping behavior need explicit treatment; positional records must survive unresolved masked-name links.

Activity

  1. dekobon commented on Nov 4, 2026

    @dekobon
    OwnerAuthor

    Plan refreshed against current main

    Updated this issue body after reviewing changes since #1654 was filed, through 07822c69211fe851c452ac6c0ebbd99cf92589a5. Relevant PRs: PR #1769, PR #1774, PR #1804.

    • Doxygen entry recognition is now id-keyed roles/c_family.rs fragments composed via DoxygenRow. Preserve old_names_are_the_row alias coverage and the ERROR/context logic around the row; do not reconstruct the old kind-name match.
    • conditional_declares uses MemoQuestion::ConditionalDeclares and a one-entry parent context. It is deliberately exact only for gates that inspect at most parent. A new depth-reading source-owner gate needs a separate appropriately scoped context; blindly copying the full chain per conditional was measured quadratic.
    • Preserve the two defenses against reentering conditional analysis and tests on both cached and uncached paths. Add independent conditionals at growing struct depth, not just a single nested #ifdef chain.
    • C++ member templates/member pointers changed in PRs fix(npa,getter,npm): batch fix for #1299, #1706 and #1401 #1721/fix: batch 2026-11-03-2 (8 issues) #1804. Reuse AST c_declarator facts where relevant to owner normalization; do not infer declaration ownership from old NPA/NPM outputs or duplicate metric policy.
    • fix(metrics/loc): C family, Ruby, Elixir lose a bare \ row #1801 continuation-row gap remains open for the C family. Source/legacy baseline and mapping behavior need explicit treatment; positional records must survive unresolved masked-name links.

    The original source-documentation scope remains. New tests and current integration touchpoints are in the body; acceptance checkboxes remain open. This is source/history analysis, not a claim that the feature or new validation has run.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions