gitnexus 1.6.0 → 1.6.2-rc.1
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/README.md +73 -0
- package/dist/cli/analyze.js +50 -3
- package/dist/core/group/extractors/fs-utils.d.ts +10 -0
- package/dist/core/group/extractors/fs-utils.js +24 -0
- package/dist/core/group/extractors/grpc-extractor.d.ts +17 -8
- package/dist/core/group/extractors/grpc-extractor.js +328 -191
- package/dist/core/group/extractors/grpc-patterns/go.d.ts +2 -0
- package/dist/core/group/extractors/grpc-patterns/go.js +97 -0
- package/dist/core/group/extractors/grpc-patterns/index.d.ts +19 -0
- package/dist/core/group/extractors/grpc-patterns/index.js +46 -0
- package/dist/core/group/extractors/grpc-patterns/java.d.ts +2 -0
- package/dist/core/group/extractors/grpc-patterns/java.js +173 -0
- package/dist/core/group/extractors/grpc-patterns/node.d.ts +4 -0
- package/dist/core/group/extractors/grpc-patterns/node.js +290 -0
- package/dist/core/group/extractors/grpc-patterns/proto.d.ts +9 -0
- package/dist/core/group/extractors/grpc-patterns/proto.js +134 -0
- package/dist/core/group/extractors/grpc-patterns/python.d.ts +2 -0
- package/dist/core/group/extractors/grpc-patterns/python.js +67 -0
- package/dist/core/group/extractors/grpc-patterns/types.d.ts +50 -0
- package/dist/core/group/extractors/grpc-patterns/types.js +1 -0
- package/dist/core/group/extractors/http-patterns/go.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/go.js +215 -0
- package/dist/core/group/extractors/http-patterns/index.d.ts +17 -0
- package/dist/core/group/extractors/http-patterns/index.js +44 -0
- package/dist/core/group/extractors/http-patterns/java.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/java.js +253 -0
- package/dist/core/group/extractors/http-patterns/node.d.ts +4 -0
- package/dist/core/group/extractors/http-patterns/node.js +354 -0
- package/dist/core/group/extractors/http-patterns/php.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/php.js +70 -0
- package/dist/core/group/extractors/http-patterns/python.d.ts +2 -0
- package/dist/core/group/extractors/http-patterns/python.js +133 -0
- package/dist/core/group/extractors/http-patterns/types.d.ts +61 -0
- package/dist/core/group/extractors/http-patterns/types.js +1 -0
- package/dist/core/group/extractors/http-route-extractor.d.ts +10 -13
- package/dist/core/group/extractors/http-route-extractor.js +231 -238
- package/dist/core/group/extractors/manifest-extractor.d.ts +54 -0
- package/dist/core/group/extractors/manifest-extractor.js +277 -0
- package/dist/core/group/extractors/topic-extractor.d.ts +0 -1
- package/dist/core/group/extractors/topic-extractor.js +55 -192
- package/dist/core/group/extractors/topic-patterns/go.d.ts +2 -0
- package/dist/core/group/extractors/topic-patterns/go.js +120 -0
- package/dist/core/group/extractors/topic-patterns/index.d.ts +14 -0
- package/dist/core/group/extractors/topic-patterns/index.js +38 -0
- package/dist/core/group/extractors/topic-patterns/java.d.ts +2 -0
- package/dist/core/group/extractors/topic-patterns/java.js +80 -0
- package/dist/core/group/extractors/topic-patterns/node.d.ts +4 -0
- package/dist/core/group/extractors/topic-patterns/node.js +155 -0
- package/dist/core/group/extractors/topic-patterns/python.d.ts +2 -0
- package/dist/core/group/extractors/topic-patterns/python.js +116 -0
- package/dist/core/group/extractors/topic-patterns/types.d.ts +25 -0
- package/dist/core/group/extractors/topic-patterns/types.js +10 -0
- package/dist/core/group/extractors/tree-sitter-scanner.d.ts +113 -0
- package/dist/core/group/extractors/tree-sitter-scanner.js +94 -0
- package/dist/core/ingestion/binding-accumulator.d.ts +22 -17
- package/dist/core/ingestion/binding-accumulator.js +29 -25
- package/dist/core/ingestion/cobol-processor.d.ts +1 -1
- package/dist/core/ingestion/import-processor.js +1 -1
- package/dist/core/ingestion/language-config.js +1 -1
- package/dist/core/ingestion/language-provider.d.ts +32 -5
- package/dist/core/ingestion/languages/c-cpp.js +2 -2
- package/dist/core/ingestion/languages/dart.d.ts +1 -1
- package/dist/core/ingestion/languages/dart.js +2 -2
- package/dist/core/ingestion/languages/go.d.ts +1 -1
- package/dist/core/ingestion/languages/go.js +2 -2
- package/dist/core/ingestion/languages/ruby.js +16 -1
- package/dist/core/ingestion/languages/swift.d.ts +1 -1
- package/dist/core/ingestion/languages/swift.js +2 -2
- package/dist/core/ingestion/markdown-processor.d.ts +1 -1
- package/dist/core/ingestion/method-extractors/configs/jvm.js +1 -0
- package/dist/core/ingestion/method-extractors/configs/ruby.js +1 -0
- package/dist/core/ingestion/method-extractors/generic.d.ts +6 -0
- package/dist/core/ingestion/method-extractors/generic.js +48 -4
- package/dist/core/ingestion/method-types.d.ts +4 -0
- package/dist/core/ingestion/model/resolve.js +103 -48
- package/dist/core/ingestion/model/semantic-model.d.ts +1 -1
- package/dist/core/ingestion/model/semantic-model.js +1 -1
- package/dist/core/ingestion/model/symbol-table.d.ts +7 -7
- package/dist/core/ingestion/model/symbol-table.js +7 -7
- package/dist/core/ingestion/mro-processor.d.ts +1 -1
- package/dist/core/ingestion/mro-processor.js +1 -1
- package/dist/core/ingestion/parsing-processor.js +54 -42
- package/dist/core/ingestion/pipeline-phases/cobol.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/cobol.js +45 -0
- package/dist/core/ingestion/pipeline-phases/communities.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/communities.js +62 -0
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/cross-file-impl.js +156 -0
- package/dist/core/ingestion/pipeline-phases/cross-file.d.ts +37 -0
- package/dist/core/ingestion/pipeline-phases/cross-file.js +63 -0
- package/dist/core/ingestion/pipeline-phases/index.d.ts +21 -0
- package/dist/core/ingestion/pipeline-phases/index.js +22 -0
- package/dist/core/ingestion/pipeline-phases/markdown.d.ts +17 -0
- package/dist/core/ingestion/pipeline-phases/markdown.js +33 -0
- package/dist/core/ingestion/pipeline-phases/mro.d.ts +18 -0
- package/dist/core/ingestion/pipeline-phases/mro.js +36 -0
- package/dist/core/ingestion/pipeline-phases/orm-extraction.d.ts +22 -0
- package/dist/core/ingestion/pipeline-phases/orm-extraction.js +92 -0
- package/dist/core/ingestion/pipeline-phases/orm.d.ts +15 -0
- package/dist/core/ingestion/pipeline-phases/orm.js +74 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.d.ts +47 -0
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +437 -0
- package/dist/core/ingestion/pipeline-phases/parse.d.ts +49 -0
- package/dist/core/ingestion/pipeline-phases/parse.js +33 -0
- package/dist/core/ingestion/pipeline-phases/processes.d.ts +16 -0
- package/dist/core/ingestion/pipeline-phases/processes.js +143 -0
- package/dist/core/ingestion/pipeline-phases/routes.d.ts +21 -0
- package/dist/core/ingestion/pipeline-phases/routes.js +243 -0
- package/dist/core/ingestion/pipeline-phases/runner.d.ts +22 -0
- package/dist/core/ingestion/pipeline-phases/runner.js +203 -0
- package/dist/core/ingestion/pipeline-phases/scan.d.ts +21 -0
- package/dist/core/ingestion/pipeline-phases/scan.js +46 -0
- package/dist/core/ingestion/pipeline-phases/structure.d.ts +27 -0
- package/dist/core/ingestion/pipeline-phases/structure.js +35 -0
- package/dist/core/ingestion/pipeline-phases/tools.d.ts +20 -0
- package/dist/core/ingestion/pipeline-phases/tools.js +79 -0
- package/dist/core/ingestion/pipeline-phases/types.d.ts +79 -0
- package/dist/core/ingestion/pipeline-phases/types.js +37 -0
- package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.d.ts +70 -0
- package/dist/core/ingestion/pipeline-phases/wildcard-synthesis.js +312 -0
- package/dist/core/ingestion/pipeline.d.ts +16 -10
- package/dist/core/ingestion/pipeline.js +66 -1534
- package/dist/core/ingestion/process-processor.js +1 -1
- package/dist/core/ingestion/tree-sitter-queries.d.ts +2 -2
- package/dist/core/ingestion/tree-sitter-queries.js +69 -0
- package/dist/core/ingestion/utils/ast-helpers.d.ts +1 -3
- package/dist/core/ingestion/utils/ast-helpers.js +48 -21
- package/dist/core/ingestion/utils/env.d.ts +10 -0
- package/dist/core/ingestion/utils/env.js +10 -0
- package/dist/core/ingestion/utils/graph-sort.d.ts +58 -0
- package/dist/core/ingestion/utils/graph-sort.js +100 -0
- package/dist/core/ingestion/workers/parse-worker.js +12 -8
- package/dist/core/lbug/lbug-adapter.d.ts +28 -0
- package/dist/core/lbug/lbug-adapter.js +162 -57
- package/package.json +3 -3
- package/vendor/tree-sitter-proto/binding.gyp +30 -0
- package/vendor/tree-sitter-proto/bindings/node/binding.cc +20 -0
- package/vendor/tree-sitter-proto/bindings/node/index.d.ts +28 -0
- package/vendor/tree-sitter-proto/bindings/node/index.js +7 -0
- package/vendor/tree-sitter-proto/package.json +18 -0
- package/vendor/tree-sitter-proto/src/node-types.json +1145 -0
- package/vendor/tree-sitter-proto/src/parser.c +10149 -0
- package/vendor/tree-sitter-proto/src/tree_sitter/alloc.h +54 -0
- package/vendor/tree-sitter-proto/src/tree_sitter/array.h +291 -0
- package/vendor/tree-sitter-proto/src/tree_sitter/parser.h +266 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import Parser from 'tree-sitter';
|
|
2
|
+
/**
|
|
3
|
+
* Shared, language-agnostic tree-sitter scanning utilities used by group
|
|
4
|
+
* extractors (topic, http, grpc, ...).
|
|
5
|
+
*
|
|
6
|
+
* Design goals:
|
|
7
|
+
* - The top-level extractors must not import any tree-sitter grammar.
|
|
8
|
+
* - Per-language plugins own their grammar import, their query sources,
|
|
9
|
+
* and the mapping from capture → meta.
|
|
10
|
+
* - This module provides the plumbing: compile queries once per plugin,
|
|
11
|
+
* parse a file with a given grammar, run all patterns, and return the
|
|
12
|
+
* captured `string_literal`-style nodes together with the plugin's meta.
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* One pattern owned by a language plugin. Each pattern owns a tree-sitter
|
|
16
|
+
* S-expression query. Plugins can freely choose which capture names to
|
|
17
|
+
* use — the scanner exposes every capture in the returned `captures`
|
|
18
|
+
* map and does not privilege any particular name.
|
|
19
|
+
*
|
|
20
|
+
* `TMeta` is the plugin-specific payload the orchestrator receives back
|
|
21
|
+
* when this pattern matches — e.g. for topic extraction it carries the
|
|
22
|
+
* broker name, role, confidence, symbol name.
|
|
23
|
+
*/
|
|
24
|
+
export interface PatternSpec<TMeta> {
|
|
25
|
+
/** Tree-sitter S-expression. */
|
|
26
|
+
query: string;
|
|
27
|
+
/** Plugin-specific payload returned on every match. */
|
|
28
|
+
meta: TMeta;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* A set of patterns owned by one language plugin, bound to a specific
|
|
32
|
+
* tree-sitter grammar.
|
|
33
|
+
*
|
|
34
|
+
* `language` is typed as `unknown` because tree-sitter's TypeScript
|
|
35
|
+
* declarations use `any` for the grammar object, and the grammar modules
|
|
36
|
+
* export different shapes (plain grammar vs. namespace with `typescript`
|
|
37
|
+
* / `tsx` members). Callers pass the concrete grammar object; this
|
|
38
|
+
* module forwards it to `parser.setLanguage` / `new Parser.Query`.
|
|
39
|
+
*/
|
|
40
|
+
export interface LanguagePatterns<TMeta> {
|
|
41
|
+
/** Human-readable plugin name for diagnostics. */
|
|
42
|
+
name: string;
|
|
43
|
+
/** tree-sitter grammar object. */
|
|
44
|
+
language: unknown;
|
|
45
|
+
/** Patterns authored against `language`. */
|
|
46
|
+
patterns: PatternSpec<TMeta>[];
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Compiled form of a `LanguagePatterns` bundle. Queries are compiled
|
|
50
|
+
* eagerly at module load time so a broken grammar/query pair fails
|
|
51
|
+
* loudly the first time the plugin is imported, instead of silently
|
|
52
|
+
* at scan time when no contract is produced.
|
|
53
|
+
*/
|
|
54
|
+
export interface CompiledPatterns<TMeta> {
|
|
55
|
+
name: string;
|
|
56
|
+
language: unknown;
|
|
57
|
+
patterns: CompiledPattern<TMeta>[];
|
|
58
|
+
}
|
|
59
|
+
export interface CompiledPattern<TMeta> {
|
|
60
|
+
query: Parser.Query;
|
|
61
|
+
meta: TMeta;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Map from capture name → syntax node. Every named capture the query
|
|
65
|
+
* binds is exposed as an entry. If a query captures the same name more
|
|
66
|
+
* than once (unusual), the first occurrence wins — plugins that need
|
|
67
|
+
* all occurrences should use distinct capture names or fall back to
|
|
68
|
+
* `match.captures` array directly by iterating `query.matches()`
|
|
69
|
+
* themselves.
|
|
70
|
+
*/
|
|
71
|
+
export type CaptureMap = Record<string, Parser.SyntaxNode>;
|
|
72
|
+
/**
|
|
73
|
+
* One match returned by `scanFile` / `runCompiledPatterns`. The caller
|
|
74
|
+
* receives the full capture map plus the plugin meta, and is
|
|
75
|
+
* responsible for turning it into a domain object.
|
|
76
|
+
*/
|
|
77
|
+
export interface ScanMatch<TMeta> {
|
|
78
|
+
meta: TMeta;
|
|
79
|
+
captures: CaptureMap;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Compile a LanguagePatterns bundle. Call this once per plugin, at
|
|
83
|
+
* module load time, and export the result. Throws if any pattern
|
|
84
|
+
* fails to compile against the grammar — that's a bug in the plugin
|
|
85
|
+
* author's query, not a runtime condition.
|
|
86
|
+
*/
|
|
87
|
+
export declare function compilePatterns<TMeta>(bundle: LanguagePatterns<TMeta>): CompiledPatterns<TMeta>;
|
|
88
|
+
/**
|
|
89
|
+
* Run every compiled pattern in `plugin` against an already-parsed
|
|
90
|
+
* tree. Use this when a plugin needs multiple query bundles against
|
|
91
|
+
* the same file (e.g. one query for class-level prefixes and another
|
|
92
|
+
* for method-level annotations) and wants to avoid re-parsing.
|
|
93
|
+
*/
|
|
94
|
+
export declare function runCompiledPatterns<TMeta>(plugin: CompiledPatterns<TMeta>, tree: Parser.Tree): ScanMatch<TMeta>[];
|
|
95
|
+
/**
|
|
96
|
+
* Parse `content` with the plugin's grammar and run every compiled
|
|
97
|
+
* pattern against the AST. Returns one `ScanMatch` per matched query
|
|
98
|
+
* occurrence, carrying the plugin's meta payload.
|
|
99
|
+
*
|
|
100
|
+
* Errors are swallowed at the file level (malformed file must not abort
|
|
101
|
+
* the whole extract). Individual pattern failures are swallowed too so
|
|
102
|
+
* a single unusable query doesn't block the rest of the plugin.
|
|
103
|
+
*/
|
|
104
|
+
export declare function scanFile<TMeta>(parser: Parser, plugin: CompiledPatterns<TMeta>, content: string): ScanMatch<TMeta>[];
|
|
105
|
+
/**
|
|
106
|
+
* Strip enclosing quotes from a tree-sitter string literal node's text.
|
|
107
|
+
* Handles single / double / template quotes, Python triple-quoted strings,
|
|
108
|
+
* and Go raw string literals (backticks).
|
|
109
|
+
*
|
|
110
|
+
* Returns null for empty/nullish input so callers can uniformly skip
|
|
111
|
+
* captures whose value is missing.
|
|
112
|
+
*/
|
|
113
|
+
export declare function unquoteLiteral(raw: string): string | null;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import Parser from 'tree-sitter';
|
|
2
|
+
/**
|
|
3
|
+
* Compile a LanguagePatterns bundle. Call this once per plugin, at
|
|
4
|
+
* module load time, and export the result. Throws if any pattern
|
|
5
|
+
* fails to compile against the grammar — that's a bug in the plugin
|
|
6
|
+
* author's query, not a runtime condition.
|
|
7
|
+
*/
|
|
8
|
+
export function compilePatterns(bundle) {
|
|
9
|
+
const compiled = [];
|
|
10
|
+
for (const spec of bundle.patterns) {
|
|
11
|
+
try {
|
|
12
|
+
const query = new Parser.Query(bundle.language, spec.query);
|
|
13
|
+
compiled.push({ query, meta: spec.meta });
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
17
|
+
throw new Error(`[tree-sitter-scanner] Failed to compile pattern in ${bundle.name}: ${message}\n` +
|
|
18
|
+
`Query source:\n${spec.query}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return { name: bundle.name, language: bundle.language, patterns: compiled };
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run every compiled pattern in `plugin` against an already-parsed
|
|
25
|
+
* tree. Use this when a plugin needs multiple query bundles against
|
|
26
|
+
* the same file (e.g. one query for class-level prefixes and another
|
|
27
|
+
* for method-level annotations) and wants to avoid re-parsing.
|
|
28
|
+
*/
|
|
29
|
+
export function runCompiledPatterns(plugin, tree) {
|
|
30
|
+
const out = [];
|
|
31
|
+
for (const compiled of plugin.patterns) {
|
|
32
|
+
let matches;
|
|
33
|
+
try {
|
|
34
|
+
matches = compiled.query.matches(tree.rootNode);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
for (const match of matches) {
|
|
40
|
+
const captures = {};
|
|
41
|
+
for (const cap of match.captures) {
|
|
42
|
+
if (!(cap.name in captures))
|
|
43
|
+
captures[cap.name] = cap.node;
|
|
44
|
+
}
|
|
45
|
+
out.push({ meta: compiled.meta, captures });
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return out;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Parse `content` with the plugin's grammar and run every compiled
|
|
52
|
+
* pattern against the AST. Returns one `ScanMatch` per matched query
|
|
53
|
+
* occurrence, carrying the plugin's meta payload.
|
|
54
|
+
*
|
|
55
|
+
* Errors are swallowed at the file level (malformed file must not abort
|
|
56
|
+
* the whole extract). Individual pattern failures are swallowed too so
|
|
57
|
+
* a single unusable query doesn't block the rest of the plugin.
|
|
58
|
+
*/
|
|
59
|
+
export function scanFile(parser, plugin, content) {
|
|
60
|
+
let tree;
|
|
61
|
+
try {
|
|
62
|
+
parser.setLanguage(plugin.language);
|
|
63
|
+
tree = parser.parse(content);
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
return runCompiledPatterns(plugin, tree);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Strip enclosing quotes from a tree-sitter string literal node's text.
|
|
72
|
+
* Handles single / double / template quotes, Python triple-quoted strings,
|
|
73
|
+
* and Go raw string literals (backticks).
|
|
74
|
+
*
|
|
75
|
+
* Returns null for empty/nullish input so callers can uniformly skip
|
|
76
|
+
* captures whose value is missing.
|
|
77
|
+
*/
|
|
78
|
+
export function unquoteLiteral(raw) {
|
|
79
|
+
if (!raw)
|
|
80
|
+
return null;
|
|
81
|
+
// Python triple-quoted
|
|
82
|
+
if ((raw.startsWith('"""') && raw.endsWith('"""')) ||
|
|
83
|
+
(raw.startsWith("'''") && raw.endsWith("'''"))) {
|
|
84
|
+
return raw.slice(3, -3);
|
|
85
|
+
}
|
|
86
|
+
const first = raw[0];
|
|
87
|
+
const last = raw[raw.length - 1];
|
|
88
|
+
if ((first === '"' || first === "'" || first === '`') && last === first && raw.length >= 2) {
|
|
89
|
+
return raw.slice(1, -1);
|
|
90
|
+
}
|
|
91
|
+
// Some grammars expose the string content without quotes already (e.g.
|
|
92
|
+
// Python `string_content` child). Return as-is.
|
|
93
|
+
return raw;
|
|
94
|
+
}
|
|
@@ -36,9 +36,12 @@
|
|
|
36
36
|
* or (b) post-process worker-path entries through a follow-up resolution
|
|
37
37
|
* pass after the main-thread `SymbolTable` is complete.
|
|
38
38
|
*
|
|
39
|
-
* **Lifecycle contract**: `append → finalize → consume → dispose`.
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* **Lifecycle contract**: single-use — `append* → finalize → consume → dispose`.
|
|
40
|
+
* After `dispose()` the accumulator is permanently dead: any mutating call
|
|
41
|
+
* (`appendFile`) throws, and read methods return empty/undefined as if the
|
|
42
|
+
* accumulator had never been appended to. The instance is not recyclable;
|
|
43
|
+
* construct a new one for a new pipeline run. Finalization and disposal are
|
|
44
|
+
* orthogonal state dimensions and may be invoked in either order.
|
|
42
45
|
*/
|
|
43
46
|
export interface BindingEntry {
|
|
44
47
|
readonly scope: string;
|
|
@@ -119,28 +122,30 @@ export declare class BindingAccumulator {
|
|
|
119
122
|
finalize(): void;
|
|
120
123
|
/**
|
|
121
124
|
* Release the accumulator's heap footprint. Clears both internal storage
|
|
122
|
-
* maps and resets `_totalBindings` to zero. Idempotent
|
|
123
|
-
* `finalize()` — calling `dispose()` does not
|
|
125
|
+
* maps and resets `_totalBindings` to zero. Idempotent — calling twice
|
|
126
|
+
* is a no-op. Orthogonal to `finalize()` — calling `dispose()` does not
|
|
127
|
+
* change the finalized state.
|
|
124
128
|
*
|
|
125
|
-
*
|
|
126
|
-
*
|
|
129
|
+
* **Single-use lifecycle.** This is a one-way terminal transition: the
|
|
130
|
+
* accumulator is not recyclable. Any subsequent `appendFile` call throws
|
|
131
|
+
* (`'BindingAccumulator: use after dispose'`), regardless of whether
|
|
132
|
+
* `finalize()` was called first. Post-dispose reads do not throw —
|
|
133
|
+
* they return empty/undefined state matching a never-appended-to
|
|
134
|
+
* accumulator:
|
|
127
135
|
* - `fileCount === 0`
|
|
128
136
|
* - `totalBindings === 0`
|
|
129
137
|
* - `files()` yields an empty iterator
|
|
130
138
|
* - `getFile(x)` returns `undefined` for all `x`
|
|
131
139
|
* - `fileScopeEntries(x)` returns `[]` for all `x`
|
|
140
|
+
* - `fileScopeGet(x, y)` returns `undefined` for all `x, y`
|
|
132
141
|
* - `estimateMemoryBytes()` returns `0`
|
|
133
142
|
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
* consumers (`processCallsFromExtracted`, `processAssignmentsFromExtracted`)
|
|
141
|
-
* and the ExportedTypeMap enrichment loop have completed, so the heap is
|
|
142
|
-
* released before Phase 14 (`runCrossFileBindingPropagation`) and
|
|
143
|
-
* `runGraphAnalysisPhases` begin their long-running work.
|
|
143
|
+
* Lifecycle note: the pipeline disposes the accumulator inside the
|
|
144
|
+
* `finally` of the `crossFile` phase, which is scheduled after every
|
|
145
|
+
* other accumulator consumer (Phase 9 call/assignment processing and
|
|
146
|
+
* the ExportedTypeMap enrichment loop). The dispose call therefore
|
|
147
|
+
* runs once, on both the happy path and the throw path of the
|
|
148
|
+
* crossFile phase.
|
|
144
149
|
*/
|
|
145
150
|
dispose(): void;
|
|
146
151
|
/** Get all bindings for a file, or undefined if the file is unknown. */
|
|
@@ -36,9 +36,12 @@
|
|
|
36
36
|
* or (b) post-process worker-path entries through a follow-up resolution
|
|
37
37
|
* pass after the main-thread `SymbolTable` is complete.
|
|
38
38
|
*
|
|
39
|
-
* **Lifecycle contract**: `append → finalize → consume → dispose`.
|
|
40
|
-
*
|
|
41
|
-
*
|
|
39
|
+
* **Lifecycle contract**: single-use — `append* → finalize → consume → dispose`.
|
|
40
|
+
* After `dispose()` the accumulator is permanently dead: any mutating call
|
|
41
|
+
* (`appendFile`) throws, and read methods return empty/undefined as if the
|
|
42
|
+
* accumulator had never been appended to. The instance is not recyclable;
|
|
43
|
+
* construct a new one for a new pipeline run. Finalization and disposal are
|
|
44
|
+
* orthogonal state dimensions and may be invoked in either order.
|
|
42
45
|
*/
|
|
43
46
|
/**
|
|
44
47
|
* Merge file-scope bindings from a (finalized) `BindingAccumulator` into an
|
|
@@ -137,17 +140,16 @@ export class BindingAccumulator {
|
|
|
137
140
|
if (this._finalized) {
|
|
138
141
|
throw new Error('[BindingAccumulator] appendFile after finalize — no further appends allowed');
|
|
139
142
|
}
|
|
143
|
+
// Single-use lifecycle: once disposed, the accumulator is dead. A
|
|
144
|
+
// post-dispose append almost always indicates a missed wiring step
|
|
145
|
+
// (the consumer is reading state that was supposed to be released),
|
|
146
|
+
// so convert the silent use-after-dispose into a loud failure.
|
|
147
|
+
if (this._disposed) {
|
|
148
|
+
throw new Error('BindingAccumulator: use after dispose');
|
|
149
|
+
}
|
|
140
150
|
if (entries.length === 0) {
|
|
141
151
|
return;
|
|
142
152
|
}
|
|
143
|
-
// Contract consistency: if this accumulator was previously disposed
|
|
144
|
-
// without being finalized, `dispose()` is documented to leave it
|
|
145
|
-
// "behaving like a fresh one" for subsequent appends. Clear the
|
|
146
|
-
// `_disposed` flag here so the `disposed` getter tracks the actual
|
|
147
|
-
// live state, not a stale signal from the prior lifecycle cycle.
|
|
148
|
-
if (this._disposed) {
|
|
149
|
-
this._disposed = false;
|
|
150
|
-
}
|
|
151
153
|
// Note on the file-scope-only invariant:
|
|
152
154
|
// The accumulator does NOT reject function-scope entries at this
|
|
153
155
|
// boundary. The narrowing contract is enforced by the two production
|
|
@@ -213,28 +215,30 @@ export class BindingAccumulator {
|
|
|
213
215
|
}
|
|
214
216
|
/**
|
|
215
217
|
* Release the accumulator's heap footprint. Clears both internal storage
|
|
216
|
-
* maps and resets `_totalBindings` to zero. Idempotent
|
|
217
|
-
* `finalize()` — calling `dispose()` does not
|
|
218
|
+
* maps and resets `_totalBindings` to zero. Idempotent — calling twice
|
|
219
|
+
* is a no-op. Orthogonal to `finalize()` — calling `dispose()` does not
|
|
220
|
+
* change the finalized state.
|
|
218
221
|
*
|
|
219
|
-
*
|
|
220
|
-
*
|
|
222
|
+
* **Single-use lifecycle.** This is a one-way terminal transition: the
|
|
223
|
+
* accumulator is not recyclable. Any subsequent `appendFile` call throws
|
|
224
|
+
* (`'BindingAccumulator: use after dispose'`), regardless of whether
|
|
225
|
+
* `finalize()` was called first. Post-dispose reads do not throw —
|
|
226
|
+
* they return empty/undefined state matching a never-appended-to
|
|
227
|
+
* accumulator:
|
|
221
228
|
* - `fileCount === 0`
|
|
222
229
|
* - `totalBindings === 0`
|
|
223
230
|
* - `files()` yields an empty iterator
|
|
224
231
|
* - `getFile(x)` returns `undefined` for all `x`
|
|
225
232
|
* - `fileScopeEntries(x)` returns `[]` for all `x`
|
|
233
|
+
* - `fileScopeGet(x, y)` returns `undefined` for all `x, y`
|
|
226
234
|
* - `estimateMemoryBytes()` returns `0`
|
|
227
235
|
*
|
|
228
|
-
*
|
|
229
|
-
*
|
|
230
|
-
*
|
|
231
|
-
*
|
|
232
|
-
*
|
|
233
|
-
*
|
|
234
|
-
* consumers (`processCallsFromExtracted`, `processAssignmentsFromExtracted`)
|
|
235
|
-
* and the ExportedTypeMap enrichment loop have completed, so the heap is
|
|
236
|
-
* released before Phase 14 (`runCrossFileBindingPropagation`) and
|
|
237
|
-
* `runGraphAnalysisPhases` begin their long-running work.
|
|
236
|
+
* Lifecycle note: the pipeline disposes the accumulator inside the
|
|
237
|
+
* `finally` of the `crossFile` phase, which is scheduled after every
|
|
238
|
+
* other accumulator consumer (Phase 9 call/assignment processing and
|
|
239
|
+
* the ExportedTypeMap enrichment loop). The dispose call therefore
|
|
240
|
+
* runs once, on both the happy path and the throw path of the
|
|
241
|
+
* crossFile phase.
|
|
238
242
|
*/
|
|
239
243
|
dispose() {
|
|
240
244
|
this._allByFile.clear();
|
|
@@ -50,5 +50,5 @@ export declare function isJclFile(filePath: string): boolean;
|
|
|
50
50
|
* @param allPathSet - Set of all file paths in the repository
|
|
51
51
|
* @returns Summary of what was extracted
|
|
52
52
|
*/
|
|
53
|
-
export declare const processCobol: (graph: KnowledgeGraph, files: CobolFile[], allPathSet:
|
|
53
|
+
export declare const processCobol: (graph: KnowledgeGraph, files: CobolFile[], allPathSet: ReadonlySet<string>) => CobolProcessResult;
|
|
54
54
|
export {};
|
|
@@ -8,7 +8,7 @@ import { yieldToEventLoop } from './utils/event-loop.js';
|
|
|
8
8
|
import { getTreeSitterBufferSize } from './constants.js';
|
|
9
9
|
import { loadImportConfigs } from './language-config.js';
|
|
10
10
|
import { buildSuffixIndex } from './import-resolvers/utils.js';
|
|
11
|
-
|
|
11
|
+
import { isDev } from './utils/env.js';
|
|
12
12
|
/** Group files by provider (only those with implicit import wiring), then call each wirer
|
|
13
13
|
* with its own language's files. O(n) over files, O(1) per provider lookup. */
|
|
14
14
|
function wireImplicitImports(files, importMap, addImportEdge, projectConfig) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from 'fs/promises';
|
|
2
2
|
import path from 'path';
|
|
3
|
-
|
|
3
|
+
import { isDev } from './utils/env.js';
|
|
4
4
|
// ============================================================================
|
|
5
5
|
// LANGUAGE-SPECIFIC CONFIG LOADERS
|
|
6
6
|
// ============================================================================
|
|
@@ -21,8 +21,25 @@ import type { SyntaxNode } from './utils/ast-helpers.js';
|
|
|
21
21
|
import type { NodeLabel } from '../../_shared/index.js';
|
|
22
22
|
/** Tree-sitter query captures: capture name → AST node (or undefined if not captured). */
|
|
23
23
|
export type CaptureMap = Record<string, SyntaxNode | undefined>;
|
|
24
|
-
/**
|
|
25
|
-
|
|
24
|
+
/**
|
|
25
|
+
* How a language handles imports — determines wildcard synthesis behavior.
|
|
26
|
+
*
|
|
27
|
+
* Import resolution is a graph-traversal policy with multiple distinct strategies,
|
|
28
|
+
* analogous to MRO for method resolution. Each tag picks a strategy:
|
|
29
|
+
*
|
|
30
|
+
* | Tag | Mechanism | Traversal | Languages |
|
|
31
|
+
* |-----------------------|------------------------------------------------|---------------------|--------------------------------------------|
|
|
32
|
+
* | `named` | Per-symbol imports | None (use-site) | JS/TS, Java, C#, Rust, PHP, Kotlin, Vue |
|
|
33
|
+
* | `wildcard-transitive` | Textual paste, symbols chain through files | BFS closure | C, C++ (future: Obj-C, Fortran, Nim) |
|
|
34
|
+
* | `wildcard-leaf` | Whole public API, single hop | None (direct only) | Go, Ruby, Swift, Dart |
|
|
35
|
+
* | `namespace` | Qualified handle; symbols resolved at call site| None at import | Python |
|
|
36
|
+
* | `explicit-reexport` | Opt-in per-symbol re-export (SCAFFOLD) | Topological DAG | (future: TS `export *`, Rust `pub use`) |
|
|
37
|
+
*
|
|
38
|
+
* The `explicit-reexport` tag is a compile-time scaffold; no provider claims it yet.
|
|
39
|
+
* It falls through to `wildcard-leaf` behavior in synthesis so today's TS/Rust
|
|
40
|
+
* handling is unchanged. A future PR will implement the DAG walk for `export *`.
|
|
41
|
+
*/
|
|
42
|
+
export type ImportSemantics = 'named' | 'wildcard-transitive' | 'wildcard-leaf' | 'namespace' | 'explicit-reexport';
|
|
26
43
|
/**
|
|
27
44
|
* Everything a language needs to provide.
|
|
28
45
|
* Required fields must be explicitly set; optional fields have defaults
|
|
@@ -51,10 +68,12 @@ interface LanguageProviderConfig {
|
|
|
51
68
|
/** Named binding extraction from import statements.
|
|
52
69
|
* Default: undefined (language uses wildcard/whole-module imports). */
|
|
53
70
|
readonly namedBindingExtractor?: NamedBindingExtractorFn;
|
|
54
|
-
/** How this language handles imports.
|
|
71
|
+
/** How this language handles imports. See `ImportSemantics` for the full taxonomy.
|
|
55
72
|
* - 'named': per-symbol imports (JS/TS, Java, C#, Rust, PHP, Kotlin)
|
|
56
|
-
* - 'wildcard':
|
|
57
|
-
* - '
|
|
73
|
+
* - 'wildcard-transitive': textual-include closure; imports chain through files (C, C++)
|
|
74
|
+
* - 'wildcard-leaf': whole-module single-hop imports; no transitive chaining (Go, Ruby, Swift, Dart)
|
|
75
|
+
* - 'namespace': qualified namespace imports, needs moduleAliasMap (Python)
|
|
76
|
+
* - 'explicit-reexport': opt-in per-symbol re-export (scaffold; no provider uses yet)
|
|
58
77
|
* Default: 'named'. */
|
|
59
78
|
readonly importSemantics?: ImportSemantics;
|
|
60
79
|
/** Language-specific transformation of raw import path text before resolution.
|
|
@@ -66,6 +85,14 @@ interface LanguageProviderConfig {
|
|
|
66
85
|
* Called with only THIS language's files (pre-grouped by the processor).
|
|
67
86
|
* Default: undefined (no implicit imports). */
|
|
68
87
|
readonly implicitImportWirer?: (languageFiles: string[], importMap: ReadonlyMap<string, ReadonlySet<string>>, addImportEdge: (src: string, target: string) => void, projectConfig: unknown) => void;
|
|
88
|
+
/** Resolve a container node during enclosing-owner tree walks.
|
|
89
|
+
* Called when a CLASS_CONTAINER_TYPES node is found while walking up.
|
|
90
|
+
* - Return a different SyntaxNode to remap the container (e.g., Ruby
|
|
91
|
+
* singleton_class → enclosing class/module).
|
|
92
|
+
* - Return null to skip this container and keep walking up.
|
|
93
|
+
* - Omit (undefined) to use the container node as-is (default).
|
|
94
|
+
* Default: undefined (no remapping). */
|
|
95
|
+
readonly resolveEnclosingOwner?: (node: SyntaxNode) => SyntaxNode | null;
|
|
69
96
|
/** Resolve the enclosing function name + label from an AST ancestor node
|
|
70
97
|
* that is NOT a standard FUNCTION_NODE_TYPE. For languages where the
|
|
71
98
|
* function body is a sibling of the signature (e.g. Dart: function_body ↔
|
|
@@ -293,7 +293,7 @@ export const cProvider = defineLanguage({
|
|
|
293
293
|
typeConfig: cCppConfig,
|
|
294
294
|
exportChecker: cCppExportChecker,
|
|
295
295
|
importResolver: resolveCImport,
|
|
296
|
-
importSemantics: 'wildcard',
|
|
296
|
+
importSemantics: 'wildcard-transitive',
|
|
297
297
|
fieldExtractor: createFieldExtractor(cFieldConfig),
|
|
298
298
|
methodExtractor: createMethodExtractor({
|
|
299
299
|
...cMethodConfig,
|
|
@@ -310,7 +310,7 @@ export const cppProvider = defineLanguage({
|
|
|
310
310
|
typeConfig: cCppConfig,
|
|
311
311
|
exportChecker: cCppExportChecker,
|
|
312
312
|
importResolver: resolveCppImport,
|
|
313
|
-
importSemantics: 'wildcard',
|
|
313
|
+
importSemantics: 'wildcard-transitive',
|
|
314
314
|
mroStrategy: 'leftmost-base',
|
|
315
315
|
fieldExtractor: createFieldExtractor(cppFieldConfig),
|
|
316
316
|
methodExtractor: createMethodExtractor({
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Dart Language Provider
|
|
3
3
|
*
|
|
4
4
|
* Dart traits:
|
|
5
|
-
* - importSemantics: 'wildcard' (Dart imports bring everything public into scope)
|
|
5
|
+
* - importSemantics: 'wildcard-leaf' (Dart imports bring everything public into scope)
|
|
6
6
|
* - exportChecker: public if no leading underscore
|
|
7
7
|
* - Dart SDK imports (dart:*) and external packages are skipped
|
|
8
8
|
* - enclosingFunctionFinder: Dart's tree-sitter grammar places function_body
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Dart Language Provider
|
|
3
3
|
*
|
|
4
4
|
* Dart traits:
|
|
5
|
-
* - importSemantics: 'wildcard' (Dart imports bring everything public into scope)
|
|
5
|
+
* - importSemantics: 'wildcard-leaf' (Dart imports bring everything public into scope)
|
|
6
6
|
* - exportChecker: public if no leading underscore
|
|
7
7
|
* - Dart SDK imports (dart:*) and external packages are skipped
|
|
8
8
|
* - enclosingFunctionFinder: Dart's tree-sitter grammar places function_body
|
|
@@ -83,7 +83,7 @@ export const dartProvider = defineLanguage({
|
|
|
83
83
|
typeConfig: dartConfig,
|
|
84
84
|
exportChecker: dartExportChecker,
|
|
85
85
|
importResolver: resolveDartImport,
|
|
86
|
-
importSemantics: 'wildcard',
|
|
86
|
+
importSemantics: 'wildcard-leaf',
|
|
87
87
|
fieldExtractor: createFieldExtractor(dartFieldConfig),
|
|
88
88
|
methodExtractor: createMethodExtractor(dartMethodConfig),
|
|
89
89
|
classExtractor: createClassExtractor({
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LanguageProvider, following the Strategy pattern used by the pipeline.
|
|
6
6
|
*
|
|
7
7
|
* Key Go traits:
|
|
8
|
-
* - importSemantics: 'wildcard' (Go imports entire packages)
|
|
8
|
+
* - importSemantics: 'wildcard-leaf' (Go imports entire packages)
|
|
9
9
|
* - callRouter: present (Go method calls may need routing)
|
|
10
10
|
*/
|
|
11
11
|
export declare const goProvider: import("../language-provider.js").LanguageProvider;
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LanguageProvider, following the Strategy pattern used by the pipeline.
|
|
6
6
|
*
|
|
7
7
|
* Key Go traits:
|
|
8
|
-
* - importSemantics: 'wildcard' (Go imports entire packages)
|
|
8
|
+
* - importSemantics: 'wildcard-leaf' (Go imports entire packages)
|
|
9
9
|
* - callRouter: present (Go method calls may need routing)
|
|
10
10
|
*/
|
|
11
11
|
import { SupportedLanguages } from '../../../_shared/index.js';
|
|
@@ -26,7 +26,7 @@ export const goProvider = defineLanguage({
|
|
|
26
26
|
typeConfig: goConfig,
|
|
27
27
|
exportChecker: goExportChecker,
|
|
28
28
|
importResolver: resolveGoImport,
|
|
29
|
-
importSemantics: 'wildcard',
|
|
29
|
+
importSemantics: 'wildcard-leaf',
|
|
30
30
|
fieldExtractor: createFieldExtractor(goFieldConfig),
|
|
31
31
|
methodExtractor: createMethodExtractor(goMethodConfig),
|
|
32
32
|
classExtractor: createClassExtractor({
|
|
@@ -99,7 +99,22 @@ export const rubyProvider = defineLanguage({
|
|
|
99
99
|
exportChecker: rubyExportChecker,
|
|
100
100
|
importResolver: resolveRubyImport,
|
|
101
101
|
callRouter: routeRubyCall,
|
|
102
|
-
importSemantics: 'wildcard',
|
|
102
|
+
importSemantics: 'wildcard-leaf',
|
|
103
|
+
resolveEnclosingOwner(node) {
|
|
104
|
+
// Ruby singleton_class (class << self) should resolve to the enclosing
|
|
105
|
+
// class or module for owner/container resolution (HAS_METHOD edges, class IDs).
|
|
106
|
+
if (node.type === 'singleton_class') {
|
|
107
|
+
let ancestor = node.parent;
|
|
108
|
+
while (ancestor) {
|
|
109
|
+
if (ancestor.type === 'class' || ancestor.type === 'module') {
|
|
110
|
+
return ancestor;
|
|
111
|
+
}
|
|
112
|
+
ancestor = ancestor.parent;
|
|
113
|
+
}
|
|
114
|
+
return null; // no enclosing class/module — skip
|
|
115
|
+
}
|
|
116
|
+
return node; // use as-is for all other container types
|
|
117
|
+
},
|
|
103
118
|
fieldExtractor: createFieldExtractor(rubyFieldConfig),
|
|
104
119
|
methodExtractor: createMethodExtractor({
|
|
105
120
|
...rubyMethodConfig,
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LanguageProvider, following the Strategy pattern used by the pipeline.
|
|
6
6
|
*
|
|
7
7
|
* Key Swift traits:
|
|
8
|
-
* - importSemantics: 'wildcard' (Swift imports entire modules)
|
|
8
|
+
* - importSemantics: 'wildcard-leaf' (Swift imports entire modules)
|
|
9
9
|
* - heritageDefaultEdge: 'IMPLEMENTS' (protocols are more common than class inheritance)
|
|
10
10
|
* - implicitImportWirer: all files in the same SPM target see each other
|
|
11
11
|
*/
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* LanguageProvider, following the Strategy pattern used by the pipeline.
|
|
6
6
|
*
|
|
7
7
|
* Key Swift traits:
|
|
8
|
-
* - importSemantics: 'wildcard' (Swift imports entire modules)
|
|
8
|
+
* - importSemantics: 'wildcard-leaf' (Swift imports entire modules)
|
|
9
9
|
* - heritageDefaultEdge: 'IMPLEMENTS' (protocols are more common than class inheritance)
|
|
10
10
|
* - implicitImportWirer: all files in the same SPM target see each other
|
|
11
11
|
*/
|
|
@@ -221,7 +221,7 @@ export const swiftProvider = defineLanguage({
|
|
|
221
221
|
typeConfig: swiftConfig,
|
|
222
222
|
exportChecker: swiftExportChecker,
|
|
223
223
|
importResolver: resolveSwiftImport,
|
|
224
|
-
importSemantics: 'wildcard',
|
|
224
|
+
importSemantics: 'wildcard-leaf',
|
|
225
225
|
heritageDefaultEdge: 'IMPLEMENTS',
|
|
226
226
|
fieldExtractor: createFieldExtractor(swiftFieldConfig),
|
|
227
227
|
methodExtractor: createMethodExtractor({
|
|
@@ -10,7 +10,7 @@ interface MdFile {
|
|
|
10
10
|
path: string;
|
|
11
11
|
content: string;
|
|
12
12
|
}
|
|
13
|
-
export declare const processMarkdown: (graph: KnowledgeGraph, files: MdFile[], allPathSet:
|
|
13
|
+
export declare const processMarkdown: (graph: KnowledgeGraph, files: MdFile[], allPathSet: ReadonlySet<string>) => {
|
|
14
14
|
sections: number;
|
|
15
15
|
links: number;
|
|
16
16
|
};
|
|
@@ -248,6 +248,7 @@ export const kotlinMethodConfig = {
|
|
|
248
248
|
typeDeclarationNodes: ['class_declaration', 'object_declaration', 'companion_object'],
|
|
249
249
|
methodNodeTypes: ['function_declaration'],
|
|
250
250
|
bodyNodeTypes: ['class_body'],
|
|
251
|
+
staticOwnerTypes: new Set(['companion_object', 'object_declaration']),
|
|
251
252
|
extractName(node) {
|
|
252
253
|
for (let i = 0; i < node.namedChildCount; i++) {
|
|
253
254
|
const child = node.namedChild(i);
|
|
@@ -202,6 +202,7 @@ export const rubyMethodConfig = {
|
|
|
202
202
|
typeDeclarationNodes: ['class', 'module', 'singleton_class'],
|
|
203
203
|
methodNodeTypes: ['method', 'singleton_method'],
|
|
204
204
|
bodyNodeTypes: ['body_statement'],
|
|
205
|
+
staticOwnerTypes: new Set(['singleton_class']),
|
|
205
206
|
extractOwnerName(node) {
|
|
206
207
|
// singleton_class (class << self) inherits the enclosing class/module name
|
|
207
208
|
if (node.type === 'singleton_class') {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { MethodExtractor, MethodExtractionConfig } from '../method-types.js';
|
|
2
2
|
/**
|
|
3
3
|
* Create a MethodExtractor from a declarative config.
|
|
4
|
+
*
|
|
5
|
+
* @throws {Error} if `typeDeclarationNodes` contains a static-implying owner
|
|
6
|
+
* type (companion_object / object_declaration / singleton_class) that is
|
|
7
|
+
* not covered by `staticOwnerTypes`. The guard fires once per language at
|
|
8
|
+
* provider construction to prevent silent `isStatic=false` regressions. See
|
|
9
|
+
* `STATIC_IMPLYING_OWNER_TYPES` for the exact opt-out convention.
|
|
4
10
|
*/
|
|
5
11
|
export declare function createMethodExtractor(config: MethodExtractionConfig): MethodExtractor;
|