Skip to content

No body span in the JSON model, so a callable's body block cannot be sliced in either projection #203

Description

@rahlk

Is your feature request related to a problem? Please describe.

codeanalyzer-java is adding a body span to its graph in codellm-devkit/codeanalyzer-java#258 (for its issue #256), under a body_ property prefix:

body_start_line, body_end_line, body_start_column, body_end_column, body_start_byte, body_end_byte

with the intent recorded in the diff as: "The body block's own offsets, under a body_ prefix. span covers the whole declaration", filled from c.getBodySpan().

This analyzer has no body span in its JSON model at all, so there is nothing to project. TSCallable (src/schema/schema.ts:296, :321) carries:

  • span: TSSpan — the whole declaration, signature and decorators included
  • body: Record<string, TSBodyNode> — a map of body nodes, not an extent

So "give me this function's body text without its signature" is answerable on a java graph and not on this one, and unlike the other gaps in the parity sweep this one cannot be fixed in the projection — the fact does not exist upstream to project.

Filing this separately because it is a different kind of change from its neighbours: #201 and #202 move facts that analysis.json already carries onto the graph, whereas this one adds a fact to the canonical model first.

Describe the solution you'd like

  • decide the open question above, and record the answer either way
  • if a field is warranted: TSCallable carries a body span in analysis.json, level-free, alongside span
  • the projection carries it under java's body_ prefix — adopt those six spellings, do not coin new ones
  • byte offsets are UTF-8, the Neo4j projection writes :TSCallable.code one line short of the callable's span #179 meaning, Buffer-sliced
  • the checked-in graph schema snapshot is regenerated

Describe alternatives you've considered

Is a stored body span needed, or is it derivable? At L3 a callable's body{} carries @entry and @exit nodes, which may already bound the body block, in which case a consumer can compute the extent and a new field is redundant. At L1 there are only call nodes, so nothing bounds it there — which would make the field the only level-free answer. Settle this first: if L1 consumers need the body extent, the field earns its place; if only L3 consumers do, this may close as derivable.

Additional context

Scope boundary

The JSON model and, following it, the Neo4j projection. Filed out of the sweep that produced #201 and #202; it is not a prerequisite for either, and neither is a prerequisite for it.

Caveats

  • The body_ names are codeanalyzer-java's. #258 coins them; a term coined twice is permanently wrong under the cross-language parity clause. That PR is unmerged at time of filing, so the spellings are proposed rather than shipped — same sequencing hazard as Neo4j projection drops module source and span byte offsets, so no span narrower than a callable resolves to text #201, and the same answer: wait, then adopt verbatim.
  • Abstract, ambient and overload-only callables have no body, so the field must be genuinely absent for them rather than a zero-width span at the declaration start — otherwise a consumer cannot tell "no body" from "empty body".
  • Arrow-function and expression bodies have no block. const f = () => x has a body expression, not a body block; whether its span covers x or is absent needs deciding, and java's Java-shaped answer will not settle it. This is one place this analyzer has to think for itself rather than adopt.
  • schema_version does not move (Scope every destructive Neo4j statement on the can:// id prefix; retire _module .github#50), so the addition is presence-detectable only.

Definition of done

  • For a fixture callable with a block body, Buffer.from(source).subarray(body_start_byte, body_end_byte) is exactly the body block including its braces, and the declaration span slice strictly contains it.
  • For an abstract method, an ambient declaration and an overload signature, the field is absent rather than zero-width, asserted per node.
  • For an arrow function with an expression body, whatever was decided above is asserted, not left to chance.
  • At least one fixture callable follows a non-ASCII character in its file, so a char-offset regression fails the slice check.
  • Emitted schema matches the checked-in snapshot; bun test and bun run typecheck green.

Activity

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

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions