Skip to content

fix(schema): decorator qualified_name is the import-table resolution or absent; name is the written spelling #151

Description

@rahlk

Problem

TSDecorator.qualified_name is documented as "checker-resolved FQN when available". It is not
resolved by anything. It is ts-morph's Decorator.getFullName() — the written expression text —
and the builder never consults the checker (src/syntactic_analysis/builders.ts, decoratorsOf).

Measured with a decorator imported as import { Get as HttpGet } from "./decorators", where
resolution is trivial: the field emits HttpGet, the alias as typed. So the field is a second copy
of name with dots, and every consumer that trusted the comment — including #143 — was misled.

Consequence in #143 as shipped: :TSDecorator merges on qualified_name || name, so a project's
local @Get and NestJS's @Get collapse into one node. The "two spellings, one decorator"
behaviour that PR describes works in the opposite direction from python's.

Found while propagating python 1.4.1's entrypoint changes; this is unit 0 of
docs/design/specs/entrypoint-detection.md
(#150), and blocks the decorator matcher there.

Scope boundary

The two decorator identity fields only. No entrypoint detection, no rules file, no changes to
argument capture.

Goals

  • qualified_name is the import-table resolution of the written spelling, or absent when
    the decorator's head is not an imported binding — python's rule ("Jedi, else the import table,
    else None") minus the Jedi step TypeScript does not have
  • name is the decorator as written (http.route, not route), so an unresolved dotted
    decorator keeps its spelling in the output — python's name is the written spelling for the
    same reason
  • The resolver is reusable: the entrypoint pass (units 2-3) needs the same import table for base
    classes and the unresolved counter
  • Schema comments say what the fields actually hold

Caveats and known risks

This changes emitted values, so it is a fix with a visible effect rather than an invisible one:

decorator name before → after qualified_name before → after
@Get from @nestjs/common GetGet Get@nestjs/common.Get
@HttpGet via import { Get as HttpGet } HttpGetHttpGet HttpGet<module>.Get
@http.route via import * as http routehttp.route http.route<module>.route
@Local declared in the same file LocalLocal Localabsent

Neo4j :TSDecorator merge key (qualified_name || name) therefore becomes package-qualified for
imported decorators and stays the written spelling for local ones — which is what #143 meant.

Not a breaking change: the field was documented as resolved and never was. But anything that
matched on the old bare qualified_name sees different values.

Definition of done

  • The four rows above are asserted end-to-end, including the alias and namespace cases
  • A same-file decorator emits no qualified_name
  • bun test green; the feat(neo4j): project decorators, matching python #143 test still passes (its decorators are same-file, so the merge key is
    unchanged there)
  • Container tests run against live Neo4j

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