gitnexus 1.6.9-rc.43 → 1.6.9-rc.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/dist/_shared/graph/types.d.ts +16 -0
  2. package/dist/_shared/graph/types.d.ts.map +1 -1
  3. package/dist/_shared/lbug/schema-constants.d.ts +1 -1
  4. package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
  5. package/dist/_shared/lbug/schema-constants.js +1 -0
  6. package/dist/_shared/lbug/schema-constants.js.map +1 -1
  7. package/dist/core/incremental/subgraph-extract.js +14 -1
  8. package/dist/core/ingestion/di-extractors/index.d.ts +47 -0
  9. package/dist/core/ingestion/di-extractors/index.js +35 -0
  10. package/dist/core/ingestion/di-extractors/spring.d.ts +82 -0
  11. package/dist/core/ingestion/di-extractors/spring.js +220 -0
  12. package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +12 -0
  13. package/dist/core/ingestion/field-extractors/configs/helpers.js +28 -0
  14. package/dist/core/ingestion/field-extractors/configs/jvm.js +13 -1
  15. package/dist/core/ingestion/field-extractors/generic.d.ts +13 -0
  16. package/dist/core/ingestion/field-extractors/generic.js +26 -0
  17. package/dist/core/ingestion/field-types.d.ts +13 -0
  18. package/dist/core/ingestion/languages/java/scope-resolver.js +1 -0
  19. package/dist/core/ingestion/method-extractors/configs/jvm.js +3 -18
  20. package/dist/core/ingestion/pipeline-phases/di.d.ts +47 -0
  21. package/dist/core/ingestion/pipeline-phases/di.js +217 -0
  22. package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
  23. package/dist/core/ingestion/pipeline-phases/index.js +1 -0
  24. package/dist/core/ingestion/pipeline.d.ts +1 -1
  25. package/dist/core/ingestion/pipeline.js +3 -2
  26. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +48 -5
  27. package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +11 -5
  28. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +43 -0
  29. package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +199 -9
  30. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +15 -8
  31. package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +15 -7
  32. package/dist/core/ingestion/workers/parse-worker.js +16 -0
  33. package/dist/core/lbug/lbug-adapter.d.ts +19 -0
  34. package/dist/core/lbug/lbug-adapter.js +59 -69
  35. package/dist/core/lbug/lbug-config.d.ts +21 -0
  36. package/dist/core/lbug/lbug-config.js +24 -0
  37. package/dist/core/run-analyze.js +14 -1
  38. package/dist/mcp/local/local-backend.js +8 -0
  39. package/dist/mcp/tools.js +6 -2
  40. package/dist/storage/parse-cache.js +1 -1
  41. package/package.json +1 -1
  42. package/web/assets/{agent-PekRmfZA.js → agent-Dli_x7bU.js} +1 -1
  43. package/web/assets/{architectureDiagram-UL44E2DR-BT7OtZ21.js → architectureDiagram-UL44E2DR-dEkqUZN9.js} +1 -1
  44. package/web/assets/{chunk-LCXTWHL2-BaR-mDRh.js → chunk-LCXTWHL2-CfLLCywY.js} +1 -1
  45. package/web/assets/{chunk-RG4AUYOV-C3Zi_WJJ.js → chunk-RG4AUYOV-CqWzWsV3.js} +1 -1
  46. package/web/assets/{classDiagram-KGZ6W3CR-DwCv2Ceh.js → classDiagram-KGZ6W3CR-CMne4tG9.js} +1 -1
  47. package/web/assets/{classDiagram-v2-72OJOZXJ-DwCv2Ceh.js → classDiagram-v2-72OJOZXJ-CMne4tG9.js} +1 -1
  48. package/web/assets/{dagre-ND4H6XIP-Bbr-DOod.js → dagre-ND4H6XIP-Co5rRx9X.js} +1 -1
  49. package/web/assets/{diagram-3NCE3AQN-t2SsI_89.js → diagram-3NCE3AQN-DBp4O00j.js} +1 -1
  50. package/web/assets/{diagram-GF46GFSD-DOPCRZb_.js → diagram-GF46GFSD-6N_8yS0i.js} +1 -1
  51. package/web/assets/{diagram-QXG6HAR7-C-ni48MX.js → diagram-QXG6HAR7-Di093rFg.js} +1 -1
  52. package/web/assets/{diagram-WEQXMOUZ-BhkxXWUs.js → diagram-WEQXMOUZ-DZWi4SUN.js} +1 -1
  53. package/web/assets/{erDiagram-L5TCEMPS-BgU0MxfG.js → erDiagram-L5TCEMPS-8X1y6R4Y.js} +1 -1
  54. package/web/assets/{flowDiagram-H6V6AXG4-aCbzaZWr.js → flowDiagram-H6V6AXG4-CMpY8Ufn.js} +1 -1
  55. package/web/assets/{index-CJuHkVdg.js → index-KctnI3Vq.js} +6 -6
  56. package/web/assets/{infoDiagram-3YFTVSEB-DVvyoVXw.js → infoDiagram-3YFTVSEB-BaLMZkUg.js} +1 -1
  57. package/web/assets/{ishikawaDiagram-BNXS4ZKH-hPZmDrPW.js → ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js} +1 -1
  58. package/web/assets/{kanban-definition-75IXJCU3-pU7f9k-3.js → kanban-definition-75IXJCU3-CpfVLLf9.js} +1 -1
  59. package/web/assets/{mindmap-definition-2TDM6QVE-Wq8ESINo.js → mindmap-definition-2TDM6QVE-DypvbOMQ.js} +1 -1
  60. package/web/assets/{pieDiagram-CU6KROY3-o1D7lwHW.js → pieDiagram-CU6KROY3-s27EFWgP.js} +1 -1
  61. package/web/assets/{requirementDiagram-JXO7QTGE-BDiLsn6Z.js → requirementDiagram-JXO7QTGE-CWhqInuf.js} +1 -1
  62. package/web/assets/{sequenceDiagram-VS2MUI6T-DRI70L3-.js → sequenceDiagram-VS2MUI6T-RyTlZ5cR.js} +1 -1
  63. package/web/assets/{stateDiagram-7D4R322I-BnkJ0BQS.js → stateDiagram-7D4R322I-DTjVfX4A.js} +1 -1
  64. package/web/assets/{stateDiagram-v2-36443NZ5-i2xSyyw9.js → stateDiagram-v2-36443NZ5-xY9_k9_Q.js} +1 -1
  65. package/web/assets/{timeline-definition-O6YCAMPW-DDbISsUy.js → timeline-definition-O6YCAMPW-DrrqLYAf.js} +1 -1
  66. package/web/assets/{vennDiagram-MWXL3ELB-CkSSCEqU.js → vennDiagram-MWXL3ELB-B0RkWAim.js} +1 -1
  67. package/web/assets/{wardleyDiagram-CUQ6CDDI-CVWX5pm-.js → wardleyDiagram-CUQ6CDDI-boUxiQ5F.js} +1 -1
  68. package/web/assets/{xychartDiagram-N2JHSOCM-dHr2kp24.js → xychartDiagram-N2JHSOCM-BOLm0eNm.js} +1 -1
  69. package/web/index.html +1 -1
@@ -32,6 +32,9 @@ export type NodeProperties = {
32
32
  level?: number;
33
33
  returnType?: string;
34
34
  declaredType?: string;
35
+ /** Verbatim declared-type source text with generics preserved
36
+ * (e.g. `List<Shape>` where `declaredType` is the stripped `List`). */
37
+ rawDeclaredType?: string;
35
38
  visibility?: string;
36
39
  isStatic?: boolean;
37
40
  isReadonly?: boolean;
@@ -52,6 +55,19 @@ export type NodeProperties = {
52
55
  [key: string]: unknown;
53
56
  };
54
57
  export type RelationshipType = 'CONTAINS' | 'CALLS' | 'INHERITS' | 'METHOD_OVERRIDES' | 'METHOD_IMPLEMENTS' | 'IMPORTS' | 'USES' | 'DEFINES' | 'DECORATES' | 'IMPLEMENTS' | 'EXTENDS' | 'HAS_METHOD' | 'HAS_PROPERTY' | 'ACCESSES' | 'MEMBER_OF' | 'STEP_IN_PROCESS' | 'HANDLES_ROUTE' | 'FETCHES' | 'HANDLES_TOOL' | 'ENTRY_POINT_OF' | 'WRAPS' | 'QUERIES'
58
+ /** Dependency-injection edge: a consumer class receives every implementer
59
+ * of interface `T` via a container-injected collection-typed field
60
+ * (`List<T>`, `Set<T>`, `Collection<T>`, or `Map<K,T>`). Precondition: the
61
+ * field carries an injection annotation recognized by a per-language
62
+ * matcher registered in `di-extractors/` (Java/Spring today: `@Autowired`
63
+ * or `@Inject`; `@Resource` is excluded — by-name-first semantics).
64
+ * Source = the consumer Class node (the one owning the field).
65
+ * Target = an implementing Class node.
66
+ * Framework specifics live in the `reason` payload (e.g.
67
+ * `Spring DI: @Autowired List<T>`), not in this type contract.
68
+ * Lets Cypher queries trace which beans the container injects into a given
69
+ * consumer, complementing the structural `IMPLEMENTS` heritage edges. */
70
+ | 'INJECTS'
55
71
  /** Vue component event system: a handler function in a parent component is
56
72
  * bound to an event emitted by a child component (`@event="handlerFn"`).
57
73
  * Source = handler Function/Method node in the parent.
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/graph/types.ts"],"names":[],"mappings":"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"}
@@ -10,7 +10,7 @@
10
10
  export declare const NODE_TABLES: readonly ["File", "Folder", "Function", "Class", "Interface", "Method", "CodeElement", "Community", "Process", "Section", "Struct", "Enum", "Macro", "Typedef", "Union", "Namespace", "Trait", "Impl", "TypeAlias", "Const", "Static", "Variable", "Property", "Record", "Delegate", "Annotation", "Constructor", "Template", "Module", "Route", "Tool", "BasicBlock"];
11
11
  export type NodeTableName = (typeof NODE_TABLES)[number];
12
12
  export declare const REL_TABLE_NAME = "CodeRelation";
13
- export declare const REL_TYPES: readonly ["CONTAINS", "DEFINES", "IMPORTS", "CALLS", "EXTENDS", "IMPLEMENTS", "HAS_METHOD", "HAS_PROPERTY", "ACCESSES", "METHOD_OVERRIDES", "OVERRIDES", "METHOD_IMPLEMENTS", "MEMBER_OF", "STEP_IN_PROCESS", "HANDLES_ROUTE", "FETCHES", "HANDLES_TOOL", "ENTRY_POINT_OF", "WRAPS", "QUERIES", "CFG", "REACHING_DEF", "TAINTED", "SANITIZES", "TAINT_PATH", "CDG", "POST_DOMINATE"];
13
+ export declare const REL_TYPES: readonly ["CONTAINS", "DEFINES", "IMPORTS", "CALLS", "EXTENDS", "IMPLEMENTS", "HAS_METHOD", "HAS_PROPERTY", "ACCESSES", "METHOD_OVERRIDES", "OVERRIDES", "METHOD_IMPLEMENTS", "MEMBER_OF", "STEP_IN_PROCESS", "HANDLES_ROUTE", "FETCHES", "HANDLES_TOOL", "ENTRY_POINT_OF", "WRAPS", "QUERIES", "INJECTS", "CFG", "REACHING_DEF", "TAINTED", "SANITIZES", "TAINT_PATH", "CDG", "POST_DOMINATE"];
14
14
  export type RelType = (typeof REL_TYPES)[number];
15
15
  export declare const EMBEDDING_TABLE_NAME = "CodeEmbedding";
16
16
  //# sourceMappingURL=schema-constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"schema-constants.d.ts","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,wWAkCd,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C,eAAO,MAAM,SAAS,sXAmCZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,eAAO,MAAM,oBAAoB,kBAAkB,CAAC"}
1
+ {"version":3,"file":"schema-constants.d.ts","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,WAAW,wWAkCd,CAAC;AAEX,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,WAAW,CAAC,CAAC,MAAM,CAAC,CAAC;AAEzD,eAAO,MAAM,cAAc,iBAAiB,CAAC;AAE7C,eAAO,MAAM,SAAS,iYAoCZ,CAAC;AAEX,MAAM,MAAM,OAAO,GAAG,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAEjD,eAAO,MAAM,oBAAoB,kBAAkB,CAAC"}
@@ -64,6 +64,7 @@ export const REL_TYPES = [
64
64
  'ENTRY_POINT_OF',
65
65
  'WRAPS',
66
66
  'QUERIES',
67
+ 'INJECTS',
67
68
  // Taint/PDG substrate (issue #2080) — reserved edge types, emitted by no
68
69
  // phase yet (CFG → M1, REACHING_DEF → M2, TAINTED/SANITIZES/TAINT_PATH →
69
70
  // M3/M4). REACHING_DEF's variable name rides the relation's `reason` column.
@@ -1 +1 @@
1
- {"version":3,"file":"schema-constants.js","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM;IACN,QAAQ;IACR,UAAU;IACV,OAAO;IACP,WAAW;IACX,QAAQ;IACR,aAAa;IACb,WAAW;IACX,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,WAAW;IACX,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,UAAU;IACV,UAAU;IACV,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,OAAO;IACP,MAAM;IACN,2EAA2E;IAC3E,YAAY;CACJ,CAAC;AAIX,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU;IACV,SAAS;IACT,SAAS;IACT,OAAO;IACP,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,UAAU;IACV,kBAAkB;IAClB,WAAW,EAAE,mEAAmE;IAChF,mBAAmB;IACnB,WAAW;IACX,iBAAiB;IACjB,eAAe;IACf,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,OAAO;IACP,SAAS;IACT,yEAAyE;IACzE,yEAAyE;IACzE,6EAA6E;IAC7E,KAAK;IACL,cAAc;IACd,SAAS;IACT,WAAW;IACX,YAAY;IACZ,4EAA4E;IAC5E,uEAAuE;IACvE,4EAA4E;IAC5E,8EAA8E;IAC9E,KAAK;IACL,eAAe;CACP,CAAC;AAIX,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC"}
1
+ {"version":3,"file":"schema-constants.js","sourceRoot":"","sources":["../../src/lbug/schema-constants.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,MAAM;IACN,QAAQ;IACR,UAAU;IACV,OAAO;IACP,WAAW;IACX,QAAQ;IACR,aAAa;IACb,WAAW;IACX,SAAS;IACT,SAAS;IACT,QAAQ;IACR,MAAM;IACN,OAAO;IACP,SAAS;IACT,OAAO;IACP,WAAW;IACX,OAAO;IACP,MAAM;IACN,WAAW;IACX,OAAO;IACP,QAAQ;IACR,UAAU;IACV,UAAU;IACV,QAAQ;IACR,UAAU;IACV,YAAY;IACZ,aAAa;IACb,UAAU;IACV,QAAQ;IACR,OAAO;IACP,MAAM;IACN,2EAA2E;IAC3E,YAAY;CACJ,CAAC;AAIX,MAAM,CAAC,MAAM,cAAc,GAAG,cAAc,CAAC;AAE7C,MAAM,CAAC,MAAM,SAAS,GAAG;IACvB,UAAU;IACV,SAAS;IACT,SAAS;IACT,OAAO;IACP,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,cAAc;IACd,UAAU;IACV,kBAAkB;IAClB,WAAW,EAAE,mEAAmE;IAChF,mBAAmB;IACnB,WAAW;IACX,iBAAiB;IACjB,eAAe;IACf,SAAS;IACT,cAAc;IACd,gBAAgB;IAChB,OAAO;IACP,SAAS;IACT,SAAS;IACT,yEAAyE;IACzE,yEAAyE;IACzE,6EAA6E;IAC7E,KAAK;IACL,cAAc;IACd,SAAS;IACT,WAAW;IACX,YAAY;IACZ,4EAA4E;IAC5E,uEAAuE;IACvE,4EAA4E;IAC5E,8EAA8E;IAC9E,KAAK;IACL,eAAe;CACP,CAAC;AAIX,MAAM,CAAC,MAAM,oBAAoB,GAAG,eAAe,CAAC"}
@@ -63,7 +63,20 @@ const isGraphWide = (label) => label === 'Community' || label === 'Process';
63
63
  // re-included from the FULL fresh graph (which the emit phase recomputes every
64
64
  // run) or an unchanged function's summary would be lost. Cheap: one self-loop
65
65
  // edge per return-flowing function.
66
- const isGraphWideRelType = (type) => type === 'TAINT_PATH' || type === 'CALL_SUMMARY';
66
+ //
67
+ // `INJECTS` (DI collection injection, #2200) is the same class as TAINT_PATH
68
+ // (the #2084 M4 U6 pattern above): its validity is a whole-program property —
69
+ // a change to a THIRD file (the interface itself, or a new/removed
70
+ // implementer) creates or invalidates edges between two files that were never
71
+ // touched, so the endpoint-writability rule would strand a stale
72
+ // consumer→implementer edge (or miss a new one). Always re-extracted from the
73
+ // fresh graph; the orchestrator unconditionally delete-alls the old rows
74
+ // first (`deleteAllInjects`). Crash-recovery: delete-then-COPY is not atomic
75
+ // by design — a crash between them loses INJECTS edges until the next
76
+ // analyze, and the `incrementalInProgress` dirty flag (saved before any
77
+ // delete) forces a full rebuild on the next run. Temporary absence is
78
+ // possible; duplicates are not.
79
+ const isGraphWideRelType = (type) => type === 'TAINT_PATH' || type === 'CALL_SUMMARY' || type === 'INJECTS';
67
80
  /**
68
81
  * Build a Map<nodeId, filePath> for every File-bound node in the graph.
69
82
  * Graph-wide nodes (Community/Process) have no filePath and are filtered.
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Per-language DI field-matcher registry — the lookup the generic `di`
3
+ * pipeline phase uses to decide whether a `Property` node is a
4
+ * dependency-injection fan-out candidate.
5
+ *
6
+ * Mirrors `scope-resolution/pipeline/registry.ts` (`SCOPE_RESOLVERS`): a
7
+ * single-valued `ReadonlyMap<SupportedLanguages, DiFieldMatcher>` consumed by
8
+ * a framework-neutral phase, so no language or framework names leak into
9
+ * shared pipeline code. Adding a framework is two lines: implement a
10
+ * `DiFieldMatcher` in `di-extractors/<framework>.ts` and register it here.
11
+ *
12
+ * Scope honesty: matchers are per-language *field-injection* matchers.
13
+ * Constructor injection (the dominant modern Spring idiom) lives on
14
+ * Method/parameter nodes and would require widening the phase's routing —
15
+ * deliberately out of scope (see the plan's Deferred work). The registry is
16
+ * single-valued per language, matching the `SCOPE_RESOLVERS` shape; widen the
17
+ * value type to arrays only when a second same-language framework actually
18
+ * lands (a one-line type change then).
19
+ */
20
+ import { SupportedLanguages } from '../../../_shared/index.js';
21
+ import type { GraphNode } from '../../../_shared/index.js';
22
+ /** A successful DI field match, produced by a per-language matcher. */
23
+ export interface DiFieldMatch {
24
+ /** The element type name `T` — the injected bean interface. */
25
+ elementTypeName: string;
26
+ /** Human-readable edge reason. Framework specifics (names, idioms,
27
+ * collection wrapper, gating annotation) live in this payload so the
28
+ * shared `di` phase stays framework-neutral. */
29
+ reason: string;
30
+ }
31
+ /**
32
+ * A per-language field-injection matcher: given a `Property` node, return the
33
+ * parsed DI match or `null` when the field is not container-injected. The
34
+ * matcher receives the whole node (not pre-plucked fields) so the shared
35
+ * phase stays ignorant of which properties matter.
36
+ */
37
+ export type DiFieldMatcher = (node: GraphNode) => DiFieldMatch | null;
38
+ /**
39
+ * Type guard narrowing an arbitrary graph `language` string to
40
+ * `SupportedLanguages`, so `DI_MATCHERS.get()` needs no cast.
41
+ */
42
+ export declare function isSupportedLanguage(value: string): value is SupportedLanguages;
43
+ /** Map of `SupportedLanguages` → `DiFieldMatcher`. The `di` phase routes each
44
+ * `Property` node here by `node.properties.language`; no entry ⇒ the node is
45
+ * skipped. This is the single source of truth for which languages (and,
46
+ * transitively, frameworks) produce INJECTS edges. */
47
+ export declare const DI_MATCHERS: ReadonlyMap<SupportedLanguages, DiFieldMatcher>;
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Per-language DI field-matcher registry — the lookup the generic `di`
3
+ * pipeline phase uses to decide whether a `Property` node is a
4
+ * dependency-injection fan-out candidate.
5
+ *
6
+ * Mirrors `scope-resolution/pipeline/registry.ts` (`SCOPE_RESOLVERS`): a
7
+ * single-valued `ReadonlyMap<SupportedLanguages, DiFieldMatcher>` consumed by
8
+ * a framework-neutral phase, so no language or framework names leak into
9
+ * shared pipeline code. Adding a framework is two lines: implement a
10
+ * `DiFieldMatcher` in `di-extractors/<framework>.ts` and register it here.
11
+ *
12
+ * Scope honesty: matchers are per-language *field-injection* matchers.
13
+ * Constructor injection (the dominant modern Spring idiom) lives on
14
+ * Method/parameter nodes and would require widening the phase's routing —
15
+ * deliberately out of scope (see the plan's Deferred work). The registry is
16
+ * single-valued per language, matching the `SCOPE_RESOLVERS` shape; widen the
17
+ * value type to arrays only when a second same-language framework actually
18
+ * lands (a one-line type change then).
19
+ */
20
+ import { SupportedLanguages } from '../../../_shared/index.js';
21
+ import { springDiFieldMatcher } from './spring.js';
22
+ /** All `SupportedLanguages` string values, for narrowing raw graph strings. */
23
+ const SUPPORTED_LANGUAGE_VALUES = new Set(Object.values(SupportedLanguages));
24
+ /**
25
+ * Type guard narrowing an arbitrary graph `language` string to
26
+ * `SupportedLanguages`, so `DI_MATCHERS.get()` needs no cast.
27
+ */
28
+ export function isSupportedLanguage(value) {
29
+ return SUPPORTED_LANGUAGE_VALUES.has(value);
30
+ }
31
+ /** Map of `SupportedLanguages` → `DiFieldMatcher`. The `di` phase routes each
32
+ * `Property` node here by `node.properties.language`; no entry ⇒ the node is
33
+ * skipped. This is the single source of truth for which languages (and,
34
+ * transitively, frameworks) produce INJECTS edges. */
35
+ export const DI_MATCHERS = new Map([[SupportedLanguages.Java, springDiFieldMatcher]]);
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Spring dependency-injection field matcher for the generic `di` phase.
3
+ *
4
+ * Recognizes the fields Spring's container fills via collect-all-implementers
5
+ * collection injection: when a Java class declares a field carrying an
6
+ * injection annotation (`@Autowired` or `@Inject`) typed as `List<T>`,
7
+ * `Set<T>`, `Collection<T>`, or `Map<K,T>`, the container injects EVERY bean
8
+ * implementing interface `T`. The matcher reports the element type name `T`
9
+ * plus a human-readable reason naming the collection wrapper and the
10
+ * annotation that gated the match; the shared `di` phase turns that into
11
+ * `INJECTS` edges.
12
+ *
13
+ * The injection annotation is a hard precondition: a plain (non-annotated)
14
+ * collection field is never injected by the container and produces no match.
15
+ * `@Resource` (JSR-250) is DELIBERATELY excluded: it resolves by bean NAME
16
+ * first (defaulting to the field name), which injects a single named
17
+ * collection bean — the opposite of the collect-all-implementers fan-out
18
+ * INJECTS models. Including it would emit false edges.
19
+ *
20
+ * Matching happens on `rawDeclaredType` (the verbatim type text, generics
21
+ * preserved) — NOT `declaredType`, which is generics-stripped by design
22
+ * (`List<Shape>` → `List`) and can never match the collection patterns.
23
+ *
24
+ * Accepted type shapes (after whitespace normalization — internal runs of
25
+ * whitespace, including newlines from multi-line declarations, collapse to a
26
+ * single space):
27
+ * - `List<T>` / `Set<T>` / `Collection<T>` — element `T`.
28
+ * - `Map<K, T>` — element is the VALUE type `T`; the key `K` is irrelevant
29
+ * for DI resolution and may itself be generic (`Map<Pair<A,B>, T>` — the
30
+ * top-level-comma split is bracket-depth-aware, so nested commas in the
31
+ * key never bleed into the element).
32
+ * - Bounded wildcards `List<? extends T>` / `List<? super T>` — element `T`
33
+ * (both are idiomatic Spring collection injection; the container still
34
+ * collects every implementer of `T`).
35
+ * - Package-qualified wrappers `java.util.List<T>` — the wrapper is
36
+ * recognized by its LAST dotted segment. The ELEMENT keeps its dots
37
+ * (`List<com.a.Shape>` → `com.a.Shape`): dotted element names resolve via
38
+ * `qualifiedName` downstream in the `di` phase.
39
+ *
40
+ * Documented REJECTIONS (parse returns `null` — no INJECTS edges):
41
+ * - `Map<String, List<IFoo>>` — the element itself is generic; a nested
42
+ * generic is not resolvable as a single interface.
43
+ * - `List<?>` — unbounded wildcard; there is no element type to fan out to.
44
+ * - Arrays: `IFoo[]`, `List<IFoo>[]`, `List<IFoo[]>` — array injection is
45
+ * not the collect-all-implementers shape INJECTS models.
46
+ * - Non-collection types (`IFoo`, `Optional<IFoo>`, …) and wrong generic
47
+ * arity (`Map<String>`, `List<A, B>`).
48
+ * - Anything whose element is not a plain (possibly dotted) Java type name —
49
+ * this makes the parser fail closed on unanticipated syntax. In particular
50
+ * Java block comments inside the generic arguments (a `/* ... ` comment
51
+ * between `<` and the element) are NOT stripped and fail closed —
52
+ * acceptable.
53
+ *
54
+ * Registered under `SupportedLanguages.Java` in `./index.ts` (`DI_MATCHERS`);
55
+ * language routing is the registry's job, so the matcher itself never reads
56
+ * `node.properties.language`.
57
+ */
58
+ import type { DiFieldMatcher } from './index.js';
59
+ /**
60
+ * Parse a Spring DI collection field's raw declared type (verbatim source
61
+ * text, generics preserved) and return the injected bean type name.
62
+ *
63
+ * Whitespace-normalizes first (raw tree-sitter `.text` can span lines), then
64
+ * recognizes the wrapper by the LAST dotted segment before the first `<`
65
+ * (so `java.util.List<IFoo>` works), depth-aware-splits the generic argument
66
+ * list, and validates the element position. See the module docstring for the
67
+ * full accepted/rejected shape inventory.
68
+ *
69
+ * @returns the collection wrapper name + element type name, or `null` when
70
+ * the raw declared type is not a recognized Spring collection shape.
71
+ */
72
+ export declare function parseSpringCollectionType(rawDeclaredType: string): {
73
+ collectionType: string;
74
+ elementTypeName: string;
75
+ } | null;
76
+ /**
77
+ * Match a `Property` node against Spring's collection-injection shape.
78
+ *
79
+ * Returns the parsed match (with a Spring-specific human-readable `reason`
80
+ * payload) or `null` when the field is not container-injected.
81
+ */
82
+ export declare const springDiFieldMatcher: DiFieldMatcher;
@@ -0,0 +1,220 @@
1
+ /**
2
+ * Spring dependency-injection field matcher for the generic `di` phase.
3
+ *
4
+ * Recognizes the fields Spring's container fills via collect-all-implementers
5
+ * collection injection: when a Java class declares a field carrying an
6
+ * injection annotation (`@Autowired` or `@Inject`) typed as `List<T>`,
7
+ * `Set<T>`, `Collection<T>`, or `Map<K,T>`, the container injects EVERY bean
8
+ * implementing interface `T`. The matcher reports the element type name `T`
9
+ * plus a human-readable reason naming the collection wrapper and the
10
+ * annotation that gated the match; the shared `di` phase turns that into
11
+ * `INJECTS` edges.
12
+ *
13
+ * The injection annotation is a hard precondition: a plain (non-annotated)
14
+ * collection field is never injected by the container and produces no match.
15
+ * `@Resource` (JSR-250) is DELIBERATELY excluded: it resolves by bean NAME
16
+ * first (defaulting to the field name), which injects a single named
17
+ * collection bean — the opposite of the collect-all-implementers fan-out
18
+ * INJECTS models. Including it would emit false edges.
19
+ *
20
+ * Matching happens on `rawDeclaredType` (the verbatim type text, generics
21
+ * preserved) — NOT `declaredType`, which is generics-stripped by design
22
+ * (`List<Shape>` → `List`) and can never match the collection patterns.
23
+ *
24
+ * Accepted type shapes (after whitespace normalization — internal runs of
25
+ * whitespace, including newlines from multi-line declarations, collapse to a
26
+ * single space):
27
+ * - `List<T>` / `Set<T>` / `Collection<T>` — element `T`.
28
+ * - `Map<K, T>` — element is the VALUE type `T`; the key `K` is irrelevant
29
+ * for DI resolution and may itself be generic (`Map<Pair<A,B>, T>` — the
30
+ * top-level-comma split is bracket-depth-aware, so nested commas in the
31
+ * key never bleed into the element).
32
+ * - Bounded wildcards `List<? extends T>` / `List<? super T>` — element `T`
33
+ * (both are idiomatic Spring collection injection; the container still
34
+ * collects every implementer of `T`).
35
+ * - Package-qualified wrappers `java.util.List<T>` — the wrapper is
36
+ * recognized by its LAST dotted segment. The ELEMENT keeps its dots
37
+ * (`List<com.a.Shape>` → `com.a.Shape`): dotted element names resolve via
38
+ * `qualifiedName` downstream in the `di` phase.
39
+ *
40
+ * Documented REJECTIONS (parse returns `null` — no INJECTS edges):
41
+ * - `Map<String, List<IFoo>>` — the element itself is generic; a nested
42
+ * generic is not resolvable as a single interface.
43
+ * - `List<?>` — unbounded wildcard; there is no element type to fan out to.
44
+ * - Arrays: `IFoo[]`, `List<IFoo>[]`, `List<IFoo[]>` — array injection is
45
+ * not the collect-all-implementers shape INJECTS models.
46
+ * - Non-collection types (`IFoo`, `Optional<IFoo>`, …) and wrong generic
47
+ * arity (`Map<String>`, `List<A, B>`).
48
+ * - Anything whose element is not a plain (possibly dotted) Java type name —
49
+ * this makes the parser fail closed on unanticipated syntax. In particular
50
+ * Java block comments inside the generic arguments (a `/* ... ` comment
51
+ * between `<` and the element) are NOT stripped and fail closed —
52
+ * acceptable.
53
+ *
54
+ * Registered under `SupportedLanguages.Java` in `./index.ts` (`DI_MATCHERS`);
55
+ * language routing is the registry's job, so the matcher itself never reads
56
+ * `node.properties.language`.
57
+ */
58
+ import { isDev } from '../utils/env.js';
59
+ import { logger } from '../../logger.js';
60
+ /**
61
+ * Annotations that trigger Spring's collect-all-implementers collection
62
+ * injection. `@Resource` is deliberately absent — JSR-250 resolves by bean
63
+ * NAME first (defaulting to the field name), injecting a single named
64
+ * collection bean rather than fanning out to every implementer, so an
65
+ * INJECTS fan-out for it would be a false edge.
66
+ */
67
+ const INJECTION_ANNOTATIONS = new Set(['@Autowired', '@Inject']);
68
+ /** Collection wrappers whose generic element Spring fans out to every
69
+ * implementer. `Map` is special-cased for arity (2 args, element = value). */
70
+ const COLLECTION_WRAPPERS = new Set(['List', 'Set', 'Collection', 'Map']);
71
+ /** Bounded-wildcard prefixes stripped from the element position (single-spaced
72
+ * — the input is whitespace-normalized before these are checked). */
73
+ const WILDCARD_EXTENDS_PREFIX = '? extends ';
74
+ const WILDCARD_SUPER_PREFIX = '? super ';
75
+ /** A plain (possibly dotted) Java type name — the only element shape the
76
+ * parser accepts. Everything else (wildcards, arrays, comments, stray
77
+ * punctuation) fails closed. */
78
+ const JAVA_TYPE_NAME_PATTERN = /^[A-Za-z_$][A-Za-z0-9_$]*(?:\.[A-Za-z_$][A-Za-z0-9_$]*)*$/;
79
+ /**
80
+ * Split a generic-argument list on TOP-LEVEL commas only, tracking `<`/`>`
81
+ * bracket depth so nested generics (e.g. the `Pair<A,B>` key in
82
+ * `Map<Pair<A,B>, IFoo>`) never split mid-argument.
83
+ *
84
+ * @returns the top-level argument segments (untrimmed), or `null` when the
85
+ * brackets are unbalanced (fail closed on malformed input).
86
+ */
87
+ function splitTopLevelGenericArgs(inner) {
88
+ const args = [];
89
+ let depth = 0;
90
+ let segmentStart = 0;
91
+ for (let i = 0; i < inner.length; i++) {
92
+ const ch = inner[i];
93
+ if (ch === '<') {
94
+ depth++;
95
+ }
96
+ else if (ch === '>') {
97
+ depth--;
98
+ if (depth < 0)
99
+ return null;
100
+ }
101
+ else if (ch === ',' && depth === 0) {
102
+ args.push(inner.slice(segmentStart, i));
103
+ segmentStart = i + 1;
104
+ }
105
+ }
106
+ if (depth !== 0)
107
+ return null;
108
+ args.push(inner.slice(segmentStart));
109
+ return args;
110
+ }
111
+ /**
112
+ * Extract the injected bean type name from one (whitespace-normalized)
113
+ * generic-argument segment: strip a bounded-wildcard prefix, then require a
114
+ * plain dotted Java type name.
115
+ *
116
+ * @returns the element type name, or `null` for unbounded wildcards, nested
117
+ * generics, arrays, and any other non-type-name shape (fail closed).
118
+ */
119
+ function parseElementTypeName(segment) {
120
+ let element = segment.trim();
121
+ // Bounded wildcards are idiomatic collection injection: the container
122
+ // still collects every implementer of the bound.
123
+ if (element.startsWith(WILDCARD_EXTENDS_PREFIX)) {
124
+ element = element.slice(WILDCARD_EXTENDS_PREFIX.length);
125
+ }
126
+ else if (element.startsWith(WILDCARD_SUPER_PREFIX)) {
127
+ element = element.slice(WILDCARD_SUPER_PREFIX.length);
128
+ }
129
+ // Final gate: a plain (possibly dotted) type name. Rejects nested generics
130
+ // (`Map<String, List<IFoo>>` — not resolvable as a single interface),
131
+ // arrays (`List<IFoo[]>` — not the fan-out shape INJECTS models), the
132
+ // unbounded wildcard `?`, un-stripped comments, and any other residue —
133
+ // all documented rejections; fail closed.
134
+ if (!JAVA_TYPE_NAME_PATTERN.test(element))
135
+ return null;
136
+ return element;
137
+ }
138
+ /**
139
+ * Parse a Spring DI collection field's raw declared type (verbatim source
140
+ * text, generics preserved) and return the injected bean type name.
141
+ *
142
+ * Whitespace-normalizes first (raw tree-sitter `.text` can span lines), then
143
+ * recognizes the wrapper by the LAST dotted segment before the first `<`
144
+ * (so `java.util.List<IFoo>` works), depth-aware-splits the generic argument
145
+ * list, and validates the element position. See the module docstring for the
146
+ * full accepted/rejected shape inventory.
147
+ *
148
+ * @returns the collection wrapper name + element type name, or `null` when
149
+ * the raw declared type is not a recognized Spring collection shape.
150
+ */
151
+ export function parseSpringCollectionType(rawDeclaredType) {
152
+ // Collapse ALL internal whitespace runs (spaces, tabs, newlines from
153
+ // multi-line declarations) to single spaces, then trim the ends.
154
+ const normalized = rawDeclaredType.replace(/\s+/g, ' ').trim();
155
+ const openIndex = normalized.indexOf('<');
156
+ // No generic argument list, or trailing residue after the closing `>`
157
+ // (e.g. the array suffix in `List<IFoo>[]`) — not a collection injection.
158
+ if (openIndex === -1 || !normalized.endsWith('>'))
159
+ return null;
160
+ // Wrapper = last dotted segment of the pre-`<` text: strips a package
161
+ // qualifier from the WRAPPER only (`java.util.List` → `List`).
162
+ const wrapperPath = normalized.slice(0, openIndex).trim();
163
+ const wrapperSegments = wrapperPath.split('.');
164
+ const wrapper = wrapperSegments[wrapperSegments.length - 1];
165
+ if (!COLLECTION_WRAPPERS.has(wrapper))
166
+ return null;
167
+ const inner = normalized.slice(openIndex + 1, normalized.length - 1);
168
+ const args = splitTopLevelGenericArgs(inner);
169
+ if (args === null)
170
+ return null;
171
+ // List/Set/Collection take exactly one type argument; Map exactly two,
172
+ // and the injected bean type is the VALUE (2nd argument) — the key is
173
+ // irrelevant for DI resolution.
174
+ const expectedArity = wrapper === 'Map' ? 2 : 1;
175
+ if (args.length !== expectedArity)
176
+ return null;
177
+ const elementTypeName = parseElementTypeName(args[expectedArity - 1]);
178
+ if (elementTypeName === null)
179
+ return null;
180
+ return { collectionType: wrapper, elementTypeName };
181
+ }
182
+ /**
183
+ * Match a `Property` node against Spring's collection-injection shape.
184
+ *
185
+ * Returns the parsed match (with a Spring-specific human-readable `reason`
186
+ * payload) or `null` when the field is not container-injected.
187
+ */
188
+ export const springDiFieldMatcher = (node) => {
189
+ // Injection-annotation gate: only fields the container actually
190
+ // injects (@Autowired / @Inject) are candidates. Plain collection
191
+ // fields are never injected; @Resource is deliberately excluded
192
+ // (by-name-first semantics — see INJECTION_ANNOTATIONS).
193
+ const matchedAnnotation = node.properties.annotations?.find((a) => INJECTION_ANNOTATIONS.has(a));
194
+ if (matchedAnnotation === undefined)
195
+ return null;
196
+ // Match on rawDeclaredType ONLY — no `?? declaredType` fallback:
197
+ // production `declaredType` is generics-stripped by design, so a
198
+ // fallback can never match real data and would only mask plumbing
199
+ // regressions as quiet no-ops.
200
+ const rawDeclaredType = node.properties.rawDeclaredType;
201
+ if (!rawDeclaredType) {
202
+ // An injection-annotated field with NO rawDeclaredType means the
203
+ // extraction plumbing broke its contract (U1 threads the raw type
204
+ // wherever annotations are threaded) — surface it, don't silently drop.
205
+ if (isDev) {
206
+ logger.warn(`Spring DI: annotated field '${node.properties.name}' (${node.properties.filePath}) has no rawDeclaredType — extraction plumbing contract breach; skipping`);
207
+ }
208
+ return null;
209
+ }
210
+ const parsed = parseSpringCollectionType(rawDeclaredType);
211
+ if (!parsed)
212
+ return null;
213
+ return {
214
+ elementTypeName: parsed.elementTypeName,
215
+ // Honest reason: states the annotation actually found on the field and
216
+ // the collection wrapper it gated. Framework specifics live HERE, in the
217
+ // payload — never in the phase.
218
+ reason: `Spring DI: ${matchedAnnotation} ${parsed.collectionType}<${parsed.elementTypeName}>`,
219
+ };
220
+ };
@@ -18,6 +18,18 @@ export declare function hasKeyword(node: SyntaxNode, keyword: string): boolean;
18
18
  * (e.g. Java 'modifiers', Kotlin 'modifiers').
19
19
  */
20
20
  export declare function hasModifier(node: SyntaxNode, modifierType: string, keyword: string): boolean;
21
+ /**
22
+ * Collect `'@Name'`-prefixed annotation names from a declaration node's
23
+ * modifier-wrapper children (e.g. Java `modifiers`). Handles both
24
+ * `marker_annotation` (`@Autowired`) and `annotation`
25
+ * (`@Autowired(required=false)`) node types. Node-type-agnostic: works for
26
+ * any declaration (method, field, ...) that groups annotations under a
27
+ * wrapper child of type `modifierType`.
28
+ *
29
+ * Shared by the JVM method- and field-extractor configs (moved verbatim from
30
+ * `method-extractors/configs/jvm.ts` in PR #2200 U2).
31
+ */
32
+ export declare function extractAnnotations(node: SyntaxNode, modifierType: string): string[];
21
33
  /**
22
34
  * Return the first matching visibility keyword found either as a direct keyword
23
35
  * child or inside a modifier wrapper node.
@@ -39,6 +39,34 @@ export function hasModifier(node, modifierType, keyword) {
39
39
  }
40
40
  return false;
41
41
  }
42
+ /**
43
+ * Collect `'@Name'`-prefixed annotation names from a declaration node's
44
+ * modifier-wrapper children (e.g. Java `modifiers`). Handles both
45
+ * `marker_annotation` (`@Autowired`) and `annotation`
46
+ * (`@Autowired(required=false)`) node types. Node-type-agnostic: works for
47
+ * any declaration (method, field, ...) that groups annotations under a
48
+ * wrapper child of type `modifierType`.
49
+ *
50
+ * Shared by the JVM method- and field-extractor configs (moved verbatim from
51
+ * `method-extractors/configs/jvm.ts` in PR #2200 U2).
52
+ */
53
+ export function extractAnnotations(node, modifierType) {
54
+ const annotations = [];
55
+ for (let i = 0; i < node.namedChildCount; i++) {
56
+ const child = node.namedChild(i);
57
+ if (child && child.type === modifierType) {
58
+ for (let j = 0; j < child.namedChildCount; j++) {
59
+ const mod = child.namedChild(j);
60
+ if (mod && (mod.type === 'marker_annotation' || mod.type === 'annotation')) {
61
+ const nameNode = mod.childForFieldName('name') ?? mod.firstNamedChild;
62
+ if (nameNode)
63
+ annotations.push('@' + nameNode.text);
64
+ }
65
+ }
66
+ }
67
+ }
68
+ return annotations;
69
+ }
42
70
  /**
43
71
  * Return the first matching visibility keyword found either as a direct keyword
44
72
  * child or inside a modifier wrapper node.
@@ -1,6 +1,6 @@
1
1
  // gitnexus/src/core/ingestion/field-extractors/configs/jvm.ts
2
2
  import { SupportedLanguages } from '../../../../_shared/index.js';
3
- import { findVisibility, hasKeyword, hasModifier, typeFromField } from './helpers.js';
3
+ import { extractAnnotations, findVisibility, hasKeyword, hasModifier, typeFromField, } from './helpers.js';
4
4
  import { extractSimpleTypeName } from '../../type-extractors/shared.js';
5
5
  // ---------------------------------------------------------------------------
6
6
  // Java
@@ -46,6 +46,18 @@ export const javaConfig = {
46
46
  }
47
47
  return undefined;
48
48
  },
49
+ extractRawType(node) {
50
+ // Verbatim type-node text — preserves generic arguments (`List<Shape>`)
51
+ // and qualifiers (`java.util.List<Shape>`) that extractType strips.
52
+ // Precedent: the JVM method extractor keeps raw `.text` for the same
53
+ // reason (method-extractors/configs/jvm.ts).
54
+ return node.childForFieldName('type')?.text?.trim();
55
+ },
56
+ extractAnnotations(node) {
57
+ // Same walk the JVM method extractor uses — field annotations live under
58
+ // the `modifiers` child of a `field_declaration` (e.g. `@Autowired`).
59
+ return extractAnnotations(node, 'modifiers');
60
+ },
49
61
  extractVisibility(node) {
50
62
  return findVisibility(node, JAVA_VIS, 'package', 'modifiers');
51
63
  },
@@ -37,6 +37,19 @@ export interface FieldExtractionConfig {
37
37
  extractNames?: (node: SyntaxNode) => string[];
38
38
  /** Extract type annotation from a field declaration node */
39
39
  extractType: (node: SyntaxNode) => string | undefined;
40
+ /**
41
+ * Extract the verbatim declared-type source text (trimmed) from a field
42
+ * declaration node, preserving generic arguments (`List<Shape>` stays
43
+ * `List<Shape>`). Unlike `extractType`, the result bypasses
44
+ * `normalizeType`/`resolveType` entirely — it is the untouched source text.
45
+ */
46
+ extractRawType?: (node: SyntaxNode) => string | undefined;
47
+ /**
48
+ * Extract `'@Name'`-prefixed annotation names from a field declaration
49
+ * node (e.g. `['@Autowired']`). Optional — only languages with
50
+ * field-level annotations implement it.
51
+ */
52
+ extractAnnotations?: (node: SyntaxNode) => string[];
40
53
  /** Extract visibility from a field declaration node */
41
54
  extractVisibility: (node: SyntaxNode) => FieldVisibility;
42
55
  /** Extract visibility for one field name from a multi-name declaration. */
@@ -103,9 +103,35 @@ export function createFieldExtractor(config) {
103
103
  if (resolved)
104
104
  type = resolved;
105
105
  }
106
+ // Raw declared type deliberately bypasses normalizeType/resolveType —
107
+ // it is the verbatim source text (generics preserved).
108
+ let rawDeclaredType;
109
+ try {
110
+ rawDeclaredType = config.extractRawType?.(node);
111
+ }
112
+ catch {
113
+ // A throw here (an unexpected tree-sitter node shape, a config bug)
114
+ // must NOT propagate — it would escape processFileGroup to the
115
+ // language-group catch, which treats any throw as "parser unavailable"
116
+ // and silently drops every remaining file in the group. Degrade to a
117
+ // field without the raw type instead. Mirrors the descriptionExtractor
118
+ // / extractTemplateConstraints guards in parse-worker.ts (#2286 review).
119
+ rawDeclaredType = undefined;
120
+ }
121
+ let annotations;
122
+ try {
123
+ annotations = config.extractAnnotations?.(node);
124
+ }
125
+ catch {
126
+ // Same group-drop rationale as the extractRawType guard above —
127
+ // degrade to a field without annotations (#2286 review).
128
+ annotations = undefined;
129
+ }
106
130
  return {
107
131
  name,
108
132
  type,
133
+ ...(rawDeclaredType !== undefined ? { rawDeclaredType } : {}),
134
+ ...(annotations !== undefined && annotations.length > 0 ? { annotations } : {}),
109
135
  visibility: config.extractVisibilityForName?.(node, name) ?? config.extractVisibility(node),
110
136
  isStatic: config.isStatic(node),
111
137
  isReadonly: config.isReadonly(node),