gitnexus 1.6.9-rc.42 → 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.
- package/dist/_shared/graph/types.d.ts +16 -0
- package/dist/_shared/graph/types.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts +1 -1
- package/dist/_shared/lbug/schema-constants.d.ts.map +1 -1
- package/dist/_shared/lbug/schema-constants.js +1 -0
- package/dist/_shared/lbug/schema-constants.js.map +1 -1
- package/dist/core/incremental/subgraph-extract.js +14 -1
- package/dist/core/ingestion/di-extractors/index.d.ts +47 -0
- package/dist/core/ingestion/di-extractors/index.js +35 -0
- package/dist/core/ingestion/di-extractors/spring.d.ts +82 -0
- package/dist/core/ingestion/di-extractors/spring.js +220 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +12 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.js +28 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.js +13 -1
- package/dist/core/ingestion/field-extractors/generic.d.ts +13 -0
- package/dist/core/ingestion/field-extractors/generic.js +26 -0
- package/dist/core/ingestion/field-types.d.ts +13 -0
- package/dist/core/ingestion/languages/java/scope-resolver.js +1 -0
- package/dist/core/ingestion/method-extractors/configs/jvm.js +3 -18
- package/dist/core/ingestion/pipeline-phases/di.d.ts +47 -0
- package/dist/core/ingestion/pipeline-phases/di.js +217 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +1 -0
- package/dist/core/ingestion/pipeline-phases/index.js +1 -0
- package/dist/core/ingestion/pipeline.d.ts +1 -1
- package/dist/core/ingestion/pipeline.js +3 -2
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +48 -5
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.js +11 -5
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.d.ts +43 -0
- package/dist/core/ingestion/scope-resolution/passes/compound-receiver.js +199 -9
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.d.ts +15 -8
- package/dist/core/ingestion/scope-resolution/passes/receiver-bound-calls.js +15 -7
- package/dist/core/ingestion/workers/parse-worker.js +16 -0
- package/dist/core/lbug/lbug-adapter.d.ts +19 -0
- package/dist/core/lbug/lbug-adapter.js +59 -69
- package/dist/core/lbug/lbug-config.d.ts +21 -0
- package/dist/core/lbug/lbug-config.js +24 -0
- package/dist/core/run-analyze.js +14 -1
- package/dist/mcp/local/local-backend.js +8 -0
- package/dist/mcp/tools.js +6 -2
- package/dist/storage/parse-cache.js +1 -1
- package/package.json +1 -1
- package/web/assets/{agent-PekRmfZA.js → agent-Dli_x7bU.js} +1 -1
- package/web/assets/{architectureDiagram-UL44E2DR-BT7OtZ21.js → architectureDiagram-UL44E2DR-dEkqUZN9.js} +1 -1
- package/web/assets/{chunk-LCXTWHL2-BaR-mDRh.js → chunk-LCXTWHL2-CfLLCywY.js} +1 -1
- package/web/assets/{chunk-RG4AUYOV-C3Zi_WJJ.js → chunk-RG4AUYOV-CqWzWsV3.js} +1 -1
- package/web/assets/{classDiagram-KGZ6W3CR-DwCv2Ceh.js → classDiagram-KGZ6W3CR-CMne4tG9.js} +1 -1
- package/web/assets/{classDiagram-v2-72OJOZXJ-DwCv2Ceh.js → classDiagram-v2-72OJOZXJ-CMne4tG9.js} +1 -1
- package/web/assets/{dagre-ND4H6XIP-Bbr-DOod.js → dagre-ND4H6XIP-Co5rRx9X.js} +1 -1
- package/web/assets/{diagram-3NCE3AQN-t2SsI_89.js → diagram-3NCE3AQN-DBp4O00j.js} +1 -1
- package/web/assets/{diagram-GF46GFSD-DOPCRZb_.js → diagram-GF46GFSD-6N_8yS0i.js} +1 -1
- package/web/assets/{diagram-QXG6HAR7-C-ni48MX.js → diagram-QXG6HAR7-Di093rFg.js} +1 -1
- package/web/assets/{diagram-WEQXMOUZ-BhkxXWUs.js → diagram-WEQXMOUZ-DZWi4SUN.js} +1 -1
- package/web/assets/{erDiagram-L5TCEMPS-BgU0MxfG.js → erDiagram-L5TCEMPS-8X1y6R4Y.js} +1 -1
- package/web/assets/{flowDiagram-H6V6AXG4-aCbzaZWr.js → flowDiagram-H6V6AXG4-CMpY8Ufn.js} +1 -1
- package/web/assets/{index-CJuHkVdg.js → index-KctnI3Vq.js} +6 -6
- package/web/assets/{infoDiagram-3YFTVSEB-DVvyoVXw.js → infoDiagram-3YFTVSEB-BaLMZkUg.js} +1 -1
- package/web/assets/{ishikawaDiagram-BNXS4ZKH-hPZmDrPW.js → ishikawaDiagram-BNXS4ZKH-DfYpxnE5.js} +1 -1
- package/web/assets/{kanban-definition-75IXJCU3-pU7f9k-3.js → kanban-definition-75IXJCU3-CpfVLLf9.js} +1 -1
- package/web/assets/{mindmap-definition-2TDM6QVE-Wq8ESINo.js → mindmap-definition-2TDM6QVE-DypvbOMQ.js} +1 -1
- package/web/assets/{pieDiagram-CU6KROY3-o1D7lwHW.js → pieDiagram-CU6KROY3-s27EFWgP.js} +1 -1
- package/web/assets/{requirementDiagram-JXO7QTGE-BDiLsn6Z.js → requirementDiagram-JXO7QTGE-CWhqInuf.js} +1 -1
- package/web/assets/{sequenceDiagram-VS2MUI6T-DRI70L3-.js → sequenceDiagram-VS2MUI6T-RyTlZ5cR.js} +1 -1
- package/web/assets/{stateDiagram-7D4R322I-BnkJ0BQS.js → stateDiagram-7D4R322I-DTjVfX4A.js} +1 -1
- package/web/assets/{stateDiagram-v2-36443NZ5-i2xSyyw9.js → stateDiagram-v2-36443NZ5-xY9_k9_Q.js} +1 -1
- package/web/assets/{timeline-definition-O6YCAMPW-DDbISsUy.js → timeline-definition-O6YCAMPW-DrrqLYAf.js} +1 -1
- package/web/assets/{vennDiagram-MWXL3ELB-CkSSCEqU.js → vennDiagram-MWXL3ELB-B0RkWAim.js} +1 -1
- package/web/assets/{wardleyDiagram-CUQ6CDDI-CVWX5pm-.js → wardleyDiagram-CUQ6CDDI-boUxiQ5F.js} +1 -1
- package/web/assets/{xychartDiagram-N2JHSOCM-dHr2kp24.js → xychartDiagram-N2JHSOCM-BOLm0eNm.js} +1 -1
- 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,
|
|
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
|
-
|
|
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),
|