gitnexus 1.6.12-rc.1 → 1.6.12-rc.11
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 +1 -1
- package/dist/cli/optional-grammars.d.ts +7 -8
- package/dist/cli/optional-grammars.js +9 -19
- package/dist/core/ingestion/call-extractors/zig-static-gating.d.ts +5 -8
- package/dist/core/ingestion/languages/zig/query.js +7 -8
- package/dist/core/ingestion/languages/zig/scope-resolver.js +2 -0
- package/dist/core/ingestion/languages/zig/workspace-static-gating.d.ts +8 -0
- package/dist/core/ingestion/languages/zig/workspace-static-gating.js +76 -0
- package/dist/core/ingestion/parsing-processor.d.ts +22 -6
- package/dist/core/ingestion/parsing-processor.js +38 -19
- package/dist/core/ingestion/pipeline-phases/parse-impl.js +291 -93
- package/dist/core/ingestion/pipeline-phases/parse-round-budget.d.ts +42 -0
- package/dist/core/ingestion/pipeline-phases/parse-round-budget.js +50 -0
- package/dist/core/ingestion/scope-resolution/contract/scope-resolver.d.ts +13 -0
- package/dist/core/ingestion/scope-resolution/pipeline/phase.js +1 -0
- package/dist/core/ingestion/scope-resolution/pipeline/run.js +5 -0
- package/dist/core/ingestion/workers/parse-worker.js +14 -6
- package/dist/core/ingestion/workers/worker-pool.d.ts +56 -2
- package/dist/core/ingestion/workers/worker-pool.js +117 -26
- package/dist/core/search/fts-indexes.js +13 -4
- package/dist/core/tree-sitter/parser-loader.js +4 -12
- package/dist/core/tree-sitter/vendored-grammars.d.ts +1 -1
- package/dist/core/tree-sitter/vendored-grammars.js +2 -1
- package/dist/mcp/local/local-backend.js +9 -3
- package/dist/storage/parsedfile-store.js +53 -1
- package/dist/storage/v8-sidecar.d.ts +11 -0
- package/dist/storage/v8-sidecar.js +15 -7
- package/package.json +1 -5
- package/scripts/build-tree-sitter-grammars.cjs +2 -1
- package/vendor/tree-sitter-zig/LICENSE +21 -0
- package/vendor/tree-sitter-zig/README.md +25 -0
- package/vendor/tree-sitter-zig/binding.gyp +29 -0
- package/vendor/tree-sitter-zig/bindings/node/binding.cc +20 -0
- package/vendor/tree-sitter-zig/bindings/node/index.d.ts +28 -0
- package/vendor/tree-sitter-zig/bindings/node/index.js +11 -0
- package/vendor/tree-sitter-zig/grammar.js +900 -0
- package/vendor/tree-sitter-zig/package.json +18 -0
- package/vendor/tree-sitter-zig/prebuilds/SHA256SUMS +6 -0
- package/vendor/tree-sitter-zig/prebuilds/darwin-arm64/tree-sitter-zig.node +0 -0
- package/vendor/tree-sitter-zig/prebuilds/darwin-x64/tree-sitter-zig.node +0 -0
- package/vendor/tree-sitter-zig/prebuilds/linux-arm64/tree-sitter-zig.node +0 -0
- package/vendor/tree-sitter-zig/prebuilds/linux-x64/tree-sitter-zig.node +0 -0
- package/vendor/tree-sitter-zig/prebuilds/win32-arm64/tree-sitter-zig.node +0 -0
- package/vendor/tree-sitter-zig/prebuilds/win32-x64/tree-sitter-zig.node +0 -0
- package/vendor/tree-sitter-zig/src/grammar.json +6570 -0
- package/vendor/tree-sitter-zig/src/node-types.json +3178 -0
- package/vendor/tree-sitter-zig/src/parser.c +169829 -0
- package/vendor/tree-sitter-zig/src/tree_sitter/alloc.h +54 -0
- package/vendor/tree-sitter-zig/src/tree_sitter/array.h +291 -0
- package/vendor/tree-sitter-zig/src/tree_sitter/parser.h +266 -0
package/README.md
CHANGED
|
@@ -631,7 +631,7 @@ results until you re-run `gitnexus analyze --repair-fts` from a shell where the
|
|
|
631
631
|
|
|
632
632
|
### Installation fails with native module errors
|
|
633
633
|
|
|
634
|
-
Some optional language grammars (Dart, Proto, Swift, Kotlin)
|
|
634
|
+
Some optional language grammars (Dart, Proto, Swift, Kotlin, Zig) ship vendored native prebuilds. If a prebuild is missing and a source build is not possible, GitNexus still works — those languages will be skipped. To skip them intentionally (no C++ toolchain needed), set `GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1` before installing.
|
|
635
635
|
|
|
636
636
|
If `npm install -g gitnexus` fails on native modules:
|
|
637
637
|
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Optional grammar availability check.
|
|
3
3
|
*
|
|
4
|
-
* tree-sitter-dart, -proto, -swift, and -
|
|
5
|
-
* loaded from there by absolute path (NEVER copied into
|
|
6
|
-
* core/tree-sitter/vendored-grammars.ts / #2111). Each
|
|
7
|
-
* prebuilds activated via node-gyp-build. All can
|
|
8
|
-
* GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or
|
|
9
|
-
* soft-fail when no prebuild matches the host platform (and a
|
|
10
|
-
* unavailable / not attempted).
|
|
11
|
-
* optionalDependency in the list; its `probe` overrides the vendored load.
|
|
4
|
+
* tree-sitter-dart, -proto, -swift, -kotlin, and -zig are vendored under
|
|
5
|
+
* vendor/ and loaded from there by absolute path (NEVER copied into
|
|
6
|
+
* node_modules — see core/tree-sitter/vendored-grammars.ts / #2111). Each
|
|
7
|
+
* ships committed platform prebuilds activated via node-gyp-build. All can
|
|
8
|
+
* be skipped via GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or
|
|
9
|
+
* can silently soft-fail when no prebuild matches the host platform (and a
|
|
10
|
+
* source build was unavailable / not attempted).
|
|
12
11
|
*
|
|
13
12
|
* Either path produces the same observable: the .node binding is absent
|
|
14
13
|
* at runtime. This helper detects that condition and surfaces a single
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Optional grammar availability check.
|
|
3
3
|
*
|
|
4
|
-
* tree-sitter-dart, -proto, -swift, and -
|
|
5
|
-
* loaded from there by absolute path (NEVER copied into
|
|
6
|
-
* core/tree-sitter/vendored-grammars.ts / #2111). Each
|
|
7
|
-
* prebuilds activated via node-gyp-build. All can
|
|
8
|
-
* GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or
|
|
9
|
-
* soft-fail when no prebuild matches the host platform (and a
|
|
10
|
-
* unavailable / not attempted).
|
|
11
|
-
* optionalDependency in the list; its `probe` overrides the vendored load.
|
|
4
|
+
* tree-sitter-dart, -proto, -swift, -kotlin, and -zig are vendored under
|
|
5
|
+
* vendor/ and loaded from there by absolute path (NEVER copied into
|
|
6
|
+
* node_modules — see core/tree-sitter/vendored-grammars.ts / #2111). Each
|
|
7
|
+
* ships committed platform prebuilds activated via node-gyp-build. All can
|
|
8
|
+
* be skipped via GITNEXUS_SKIP_OPTIONAL_GRAMMARS=1 (postinstall scripts), or
|
|
9
|
+
* can silently soft-fail when no prebuild matches the host platform (and a
|
|
10
|
+
* source build was unavailable / not attempted).
|
|
12
11
|
*
|
|
13
12
|
* Either path produces the same observable: the .node binding is absent
|
|
14
13
|
* at runtime. This helper detects that condition and surfaces a single
|
|
15
14
|
* stderr line per missing grammar so users learn why .dart/.proto/.swift/.kt/.zig
|
|
16
15
|
* support is unavailable instead of silently getting a degraded index.
|
|
17
16
|
*/
|
|
18
|
-
import { createRequire } from 'node:module';
|
|
19
17
|
import { SupportedLanguages } from '../_shared/index.js';
|
|
20
18
|
import { isGrammarRuntimeSkipped } from '../core/tree-sitter/parser-loader.js';
|
|
21
19
|
import { requireVendoredGrammar } from '../core/tree-sitter/vendored-grammars.js';
|
|
22
20
|
import { cliWarn } from './cli-message.js';
|
|
23
|
-
const _require = createRequire(import.meta.url);
|
|
24
21
|
const OPTIONAL_GRAMMARS = [
|
|
25
22
|
{
|
|
26
23
|
name: 'tree-sitter-dart',
|
|
@@ -43,11 +40,9 @@ const OPTIONAL_GRAMMARS = [
|
|
|
43
40
|
},
|
|
44
41
|
{
|
|
45
42
|
name: 'tree-sitter-zig',
|
|
46
|
-
pkg: '
|
|
43
|
+
pkg: 'tree-sitter-zig',
|
|
47
44
|
extensions: ['.zig'],
|
|
48
45
|
language: SupportedLanguages.Zig,
|
|
49
|
-
// npm optionalDependency, not vendored — probe via plain require.
|
|
50
|
-
probe: () => _require('@tree-sitter-grammars/tree-sitter-zig'),
|
|
51
46
|
},
|
|
52
47
|
];
|
|
53
48
|
/**
|
|
@@ -84,12 +79,7 @@ export function detectMissingOptionalGrammars() {
|
|
|
84
79
|
continue;
|
|
85
80
|
}
|
|
86
81
|
try {
|
|
87
|
-
|
|
88
|
-
g.probe();
|
|
89
|
-
}
|
|
90
|
-
else {
|
|
91
|
-
requireVendoredGrammar(g.pkg);
|
|
92
|
-
}
|
|
82
|
+
requireVendoredGrammar(g.pkg);
|
|
93
83
|
}
|
|
94
84
|
catch (err) {
|
|
95
85
|
const code = err?.code;
|
|
@@ -11,17 +11,14 @@
|
|
|
11
11
|
* Conservative by design: we only tag an edge when we can prove the
|
|
12
12
|
* gating expression evaluates to `false`. Anything ambiguous → live.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
14
|
+
* Supported scope:
|
|
15
15
|
*
|
|
16
16
|
* (a) **File-local** consts (`pub const FOO = false;`, plus const-to-const
|
|
17
17
|
* aliases up to 5 hops), built once per file by `buildZigBoolConstMap`.
|
|
18
|
-
* (b) **Cross-file** (`const cfg = @import("./cfg.zig");
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* returns `undefined`, because the capture emitter runs in the parse
|
|
23
|
-
* worker and sees only the current file. Tracked in #3162. Until then
|
|
24
|
-
* every `cfg.FOO` condition folds to unknown, i.e. live.
|
|
18
|
+
* (b) **Cross-file** direct imports (`const cfg = @import("./cfg.zig");
|
|
19
|
+
* if (cfg.FOO)`) are enriched after per-file extraction. The workspace
|
|
20
|
+
* caller supplies `importAliases` and `lookupBoolsForPath`; the parse
|
|
21
|
+
* worker still uses empty/undefined inputs and remains file-local.
|
|
25
22
|
*
|
|
26
23
|
* Also out of scope: multi-hop member access (`cfg.sub.FOO`), re-exported
|
|
27
24
|
* consts, runtime-evaluated bools (`const FOO = computeIt();`), and
|
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
import Parser from 'tree-sitter';
|
|
2
|
-
import {
|
|
3
|
-
const _require = createRequire(import.meta.url);
|
|
2
|
+
import { requireVendoredGrammar } from '../../../tree-sitter/vendored-grammars.js';
|
|
4
3
|
/**
|
|
5
4
|
* Zig scope-resolution query (RFC #909 Ring 3).
|
|
6
5
|
*
|
|
7
|
-
* The grammar is
|
|
8
|
-
* so the language module is required lazily and
|
|
9
|
-
* `getZigScopeQuery` throw only when actually invoked without
|
|
10
|
-
* installed. That is safe: the parse pipeline filters `.zig` files
|
|
11
|
-
* `parser-loader.isLanguageAvailable` before any scope extraction runs.
|
|
6
|
+
* The grammar is vendored (`vendor/tree-sitter-zig`) and may be absent on a
|
|
7
|
+
* platform without a prebuild, so the language module is required lazily and
|
|
8
|
+
* `getZigParser` / `getZigScopeQuery` throw only when actually invoked without
|
|
9
|
+
* the grammar installed. That is safe: the parse pipeline filters `.zig` files
|
|
10
|
+
* through `parser-loader.isLanguageAvailable` before any scope extraction runs.
|
|
12
11
|
*
|
|
13
12
|
* Zig specifics encoded here:
|
|
14
13
|
* - Containers (struct/enum/union/opaque) are anonymous nodes bound by the
|
|
@@ -409,7 +408,7 @@ const ZIG_SCOPE_QUERY = `
|
|
|
409
408
|
let _parser = null;
|
|
410
409
|
let _query = null;
|
|
411
410
|
function getZigLanguage() {
|
|
412
|
-
return
|
|
411
|
+
return requireVendoredGrammar('tree-sitter-zig');
|
|
413
412
|
}
|
|
414
413
|
export function getZigParser() {
|
|
415
414
|
if (_parser === null) {
|
|
@@ -16,6 +16,7 @@ import { resolveZigImportInternal } from '../../import-resolvers/zig.js';
|
|
|
16
16
|
import { zigProvider } from '../zig.js';
|
|
17
17
|
import { expandZigWildcardNames, zigArityCompatibility, zigMergeBindings } from './index.js';
|
|
18
18
|
import { populateZigRangeBindings } from './range-binding.js';
|
|
19
|
+
import { populateZigWorkspaceStaticGating } from './workspace-static-gating.js';
|
|
19
20
|
export const zigScopeResolver = {
|
|
20
21
|
language: SupportedLanguages.Zig,
|
|
21
22
|
languageProvider: zigProvider,
|
|
@@ -48,6 +49,7 @@ export const zigScopeResolver = {
|
|
|
48
49
|
arityCompatibility: zigArityCompatibility,
|
|
49
50
|
buildMro: (graph, parsedFiles, nodeLookup) => buildMro(graph, parsedFiles, nodeLookup, defaultLinearize),
|
|
50
51
|
populateOwners: (parsed) => populateClassOwnedMembers(parsed),
|
|
52
|
+
populateWorkspaceReferences: populateZigWorkspaceStaticGating,
|
|
51
53
|
// Payload captures — `for (items) |it|`, `if (opt) |v|`, `while (it.next())
|
|
52
54
|
// |x|` — typed from the subject's binding after finalize (F6).
|
|
53
55
|
populateRangeBindings: populateZigRangeBindings,
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ParsedFile } from '../../../../_shared/index.js';
|
|
2
|
+
export declare function populateZigWorkspaceStaticGating(parsedFiles: ParsedFile[], ctx: {
|
|
3
|
+
readonly fileContents: ReadonlyMap<string, string>;
|
|
4
|
+
readonly treeCache?: {
|
|
5
|
+
get(filePath: string): unknown;
|
|
6
|
+
};
|
|
7
|
+
readonly resolutionConfig?: unknown;
|
|
8
|
+
}): void;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { getTreeSitterBufferSize } from '../../constants.js';
|
|
2
|
+
import { resolveZigImportInternal } from '../../import-resolvers/zig.js';
|
|
3
|
+
import { buildZigBoolConstMap, collectZigStaticGatedRanges, isPositionStaticGated, } from '../../call-extractors/zig-static-gating.js';
|
|
4
|
+
import { parseSourceSafe, ParseTimeoutError } from '../../../tree-sitter/safe-parse.js';
|
|
5
|
+
import { getZigParser } from './query.js';
|
|
6
|
+
export function populateZigWorkspaceStaticGating(parsedFiles, ctx) {
|
|
7
|
+
const parser = getZigParser();
|
|
8
|
+
const trees = new Map();
|
|
9
|
+
const bools = new Map();
|
|
10
|
+
for (const parsed of parsedFiles) {
|
|
11
|
+
const source = ctx.fileContents.get(parsed.filePath);
|
|
12
|
+
if (source === undefined)
|
|
13
|
+
continue;
|
|
14
|
+
let tree = ctx.treeCache?.get(parsed.filePath);
|
|
15
|
+
if (tree === undefined) {
|
|
16
|
+
try {
|
|
17
|
+
tree = parseSourceSafe(parser, source, undefined, {
|
|
18
|
+
bufferSize: getTreeSitterBufferSize(source),
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (err instanceof ParseTimeoutError)
|
|
23
|
+
continue;
|
|
24
|
+
throw err;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
trees.set(parsed.filePath, tree);
|
|
28
|
+
bools.set(parsed.filePath, buildZigBoolConstMap(tree.rootNode));
|
|
29
|
+
}
|
|
30
|
+
const knownPaths = new Set(trees.keys());
|
|
31
|
+
for (const [index, parsed] of parsedFiles.entries()) {
|
|
32
|
+
const tree = trees.get(parsed.filePath);
|
|
33
|
+
if (tree === undefined)
|
|
34
|
+
continue;
|
|
35
|
+
const aliases = collectImportAliases(tree, parsed.filePath, knownPaths, ctx.resolutionConfig);
|
|
36
|
+
if (aliases.size === 0)
|
|
37
|
+
continue;
|
|
38
|
+
const ranges = collectZigStaticGatedRanges(tree.rootNode, bools.get(parsed.filePath) ?? new Map(), aliases, (filePath) => bools.get(filePath));
|
|
39
|
+
if (ranges.length === 0)
|
|
40
|
+
continue;
|
|
41
|
+
const next = parsed.referenceSites.map((site) => site.kind === 'call' &&
|
|
42
|
+
site.staticGated !== true &&
|
|
43
|
+
isPositionStaticGated(site.atRange.startLine, site.atRange.startCol, ranges)
|
|
44
|
+
? { ...site, staticGated: true }
|
|
45
|
+
: site);
|
|
46
|
+
parsedFiles[index] = Object.freeze({ ...parsed, referenceSites: Object.freeze(next) });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function collectImportAliases(tree, fromFile, knownPaths, resolutionConfig) {
|
|
50
|
+
const candidates = new Map();
|
|
51
|
+
const declarationCounts = new Map();
|
|
52
|
+
for (const decl of tree.rootNode.descendantsOfType('variable_declaration')) {
|
|
53
|
+
const names = decl.namedChildren.filter((node) => node.type === 'identifier');
|
|
54
|
+
const binding = names[0]?.text;
|
|
55
|
+
if (binding === undefined)
|
|
56
|
+
continue;
|
|
57
|
+
declarationCounts.set(binding, (declarationCounts.get(binding) ?? 0) + 1);
|
|
58
|
+
const builtin = decl.namedChildren.find((node) => node.type === 'builtin_function' && node.text.startsWith('@import('));
|
|
59
|
+
const raw = builtin?.descendantsOfType('string').at(0)?.text;
|
|
60
|
+
if (raw === undefined)
|
|
61
|
+
continue;
|
|
62
|
+
const specifier = raw.replace(/^['"]|['"]$/g, '');
|
|
63
|
+
const target = resolveZigImportInternal(fromFile, specifier, knownPaths, resolutionConfig);
|
|
64
|
+
if (target !== null)
|
|
65
|
+
candidates.set(binding, target);
|
|
66
|
+
}
|
|
67
|
+
const aliases = new Map();
|
|
68
|
+
for (const [binding, target] of candidates) {
|
|
69
|
+
// Alias lookup below is name-based rather than position-aware. If a name
|
|
70
|
+
// is redeclared in another lexical scope, fail open instead of applying
|
|
71
|
+
// either module's constants to every use of that spelling.
|
|
72
|
+
if (declarationCounts.get(binding) === 1)
|
|
73
|
+
aliases.set(binding, target);
|
|
74
|
+
}
|
|
75
|
+
return aliases;
|
|
76
|
+
}
|
|
@@ -3,6 +3,7 @@ import type { SymbolTableWriter } from './model/index.js';
|
|
|
3
3
|
import { type ExportedTypeMap } from './call-processor.js';
|
|
4
4
|
import type { ParsedFile } from '../../_shared/index.js';
|
|
5
5
|
import { WorkerPool } from './workers/worker-pool.js';
|
|
6
|
+
import type { DispatchGroup } from './workers/worker-pool.js';
|
|
6
7
|
import type { ParseWorkerResult, ExtractedRoute, ExtractedFetchCall, ExtractedDecoratorRoute, ExtractedModuleConstants, ExtractedToolDef, FileScopeBindings, ExtractedORMQuery, FetchWrapperDef } from './workers/parse-worker.js';
|
|
7
8
|
import type { ExtractedRouterConstructorPrefix, ExtractedRouterImport, ExtractedRouterInclude, ExtractedRouterModuleAlias } from './route-extractors/fastapi-router-bindings.js';
|
|
8
9
|
import type { SharedSpringType } from './route-extractors/spring-shared.js';
|
|
@@ -47,12 +48,12 @@ export interface WorkerExtractedData {
|
|
|
47
48
|
*/
|
|
48
49
|
export declare const mergeChunkResults: (graph: KnowledgeGraph, symbolTable: SymbolTableWriter, chunkResults: readonly ParseWorkerResult[], exportedTypeMap?: ExportedTypeMap) => WorkerExtractedData;
|
|
49
50
|
/**
|
|
50
|
-
* Dispatch
|
|
51
|
-
* results, WITHOUT merging them into the graph.
|
|
52
|
-
* {@link
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
51
|
+
* Dispatch ONE chunk's files to the worker pool and return the RAW per-worker
|
|
52
|
+
* results, WITHOUT merging them into the graph. A thin single-group wrapper
|
|
53
|
+
* over {@link dispatchChunkParseRound}, used by {@link processParsing}'s
|
|
54
|
+
* one-shot path. The chunk-to-chunk overlap this once described now lives in
|
|
55
|
+
* `parse-impl.ts` at ROUND granularity (`startRound` / `drainRound` /
|
|
56
|
+
* `closeRound`), which batches several chunks into one dispatch.
|
|
56
57
|
* Returns `[]` for an all-unparseable chunk (the caller merges `[]` → empty).
|
|
57
58
|
*/
|
|
58
59
|
export declare const dispatchChunkParse: (files: {
|
|
@@ -67,6 +68,21 @@ outRawResults?: ParseWorkerResult[],
|
|
|
67
68
|
* (#2038). `undefined` ⇒ no durable write (tests / no-cache path).
|
|
68
69
|
*/
|
|
69
70
|
chunkHash?: string) => Promise<ParseWorkerResult[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Dispatch SEVERAL parse-cache chunks as one pool round and return their raw
|
|
73
|
+
* results, one array per input group in input order.
|
|
74
|
+
*
|
|
75
|
+
* `WorkerPool.dispatch` is a barrier, so one round-trip per chunk leaves most
|
|
76
|
+
* slots idle whenever a chunk is smaller than the pool — which stable
|
|
77
|
+
* `(language, hash(path) % 128)` packs usually are. Batching chunks into one
|
|
78
|
+
* `dispatchGroups` call removes those barriers; jobs are still cut at chunk
|
|
79
|
+
* boundaries, so every result stays attributable to the chunk whose cache key
|
|
80
|
+
* owns it.
|
|
81
|
+
*/
|
|
82
|
+
export declare const dispatchChunkParseRound: (groups: ReadonlyArray<DispatchGroup<{
|
|
83
|
+
path: string;
|
|
84
|
+
content: string;
|
|
85
|
+
}>>, workerPool: WorkerPool, onFileProgress?: FileProgressCallback) => Promise<ParseWorkerResult[][]>;
|
|
70
86
|
export declare const processParsing: (graph: KnowledgeGraph, files: {
|
|
71
87
|
path: string;
|
|
72
88
|
content: string;
|
|
@@ -147,12 +147,12 @@ export const mergeChunkResults = (graph, symbolTable, chunkResults, exportedType
|
|
|
147
147
|
};
|
|
148
148
|
};
|
|
149
149
|
/**
|
|
150
|
-
* Dispatch
|
|
151
|
-
* results, WITHOUT merging them into the graph.
|
|
152
|
-
* {@link
|
|
153
|
-
*
|
|
154
|
-
*
|
|
155
|
-
*
|
|
150
|
+
* Dispatch ONE chunk's files to the worker pool and return the RAW per-worker
|
|
151
|
+
* results, WITHOUT merging them into the graph. A thin single-group wrapper
|
|
152
|
+
* over {@link dispatchChunkParseRound}, used by {@link processParsing}'s
|
|
153
|
+
* one-shot path. The chunk-to-chunk overlap this once described now lives in
|
|
154
|
+
* `parse-impl.ts` at ROUND granularity (`startRound` / `drainRound` /
|
|
155
|
+
* `closeRound`), which batches several chunks into one dispatch.
|
|
156
156
|
* Returns `[]` for an all-unparseable chunk (the caller merges `[]` → empty).
|
|
157
157
|
*/
|
|
158
158
|
export const dispatchChunkParse = async (files, workerPool, onFileProgress,
|
|
@@ -164,23 +164,42 @@ outRawResults,
|
|
|
164
164
|
* (#2038). `undefined` ⇒ no durable write (tests / no-cache path).
|
|
165
165
|
*/
|
|
166
166
|
chunkHash) => {
|
|
167
|
-
const
|
|
168
|
-
for (const file of files) {
|
|
169
|
-
const lang = getLanguageFromFilename(file.path);
|
|
170
|
-
if (lang)
|
|
171
|
-
parseableFiles.push({ path: file.path, content: file.content });
|
|
172
|
-
}
|
|
173
|
-
if (parseableFiles.length === 0)
|
|
174
|
-
return [];
|
|
175
|
-
const total = files.length;
|
|
176
|
-
const chunkResults = await workerPool.dispatch(parseableFiles, (filesProcessed) => {
|
|
177
|
-
onFileProgress?.(Math.min(filesProcessed, total), total, 'Parsing...');
|
|
178
|
-
}, chunkHash);
|
|
167
|
+
const [chunkResults = []] = await dispatchChunkParseRound([{ items: files, chunkHash }], workerPool, onFileProgress);
|
|
179
168
|
// Capture raw results for the incremental parse cache before merging.
|
|
180
169
|
if (outRawResults) {
|
|
181
170
|
for (const r of chunkResults)
|
|
182
171
|
outRawResults.push(r);
|
|
183
172
|
}
|
|
173
|
+
return chunkResults;
|
|
174
|
+
};
|
|
175
|
+
/**
|
|
176
|
+
* Dispatch SEVERAL parse-cache chunks as one pool round and return their raw
|
|
177
|
+
* results, one array per input group in input order.
|
|
178
|
+
*
|
|
179
|
+
* `WorkerPool.dispatch` is a barrier, so one round-trip per chunk leaves most
|
|
180
|
+
* slots idle whenever a chunk is smaller than the pool — which stable
|
|
181
|
+
* `(language, hash(path) % 128)` packs usually are. Batching chunks into one
|
|
182
|
+
* `dispatchGroups` call removes those barriers; jobs are still cut at chunk
|
|
183
|
+
* boundaries, so every result stays attributable to the chunk whose cache key
|
|
184
|
+
* owns it.
|
|
185
|
+
*/
|
|
186
|
+
export const dispatchChunkParseRound = async (groups, workerPool, onFileProgress) => {
|
|
187
|
+
const dispatchGroups = groups.map((group) => {
|
|
188
|
+
const items = [];
|
|
189
|
+
for (const file of group.items) {
|
|
190
|
+
const lang = getLanguageFromFilename(file.path);
|
|
191
|
+
if (lang)
|
|
192
|
+
items.push({ path: file.path, content: file.content });
|
|
193
|
+
}
|
|
194
|
+
return { items, chunkHash: group.chunkHash };
|
|
195
|
+
});
|
|
196
|
+
const total = groups.reduce((sum, group) => sum + group.items.length, 0);
|
|
197
|
+
if (dispatchGroups.every((group) => group.items.length === 0))
|
|
198
|
+
return groups.map(() => []);
|
|
199
|
+
const perGroup = await workerPool.dispatchGroups(dispatchGroups, (filesProcessed) => {
|
|
200
|
+
onFileProgress?.(Math.min(filesProcessed, total), total, 'Parsing...');
|
|
201
|
+
});
|
|
202
|
+
const chunkResults = perGroup.flat();
|
|
184
203
|
// Skipped-language telemetry (worker output, independent of the merge).
|
|
185
204
|
const skippedLanguages = new Map();
|
|
186
205
|
for (const result of chunkResults) {
|
|
@@ -238,7 +257,7 @@ chunkHash) => {
|
|
|
238
257
|
logger.warn(` Sanitized ${skippedPaths.length} file(s) with non-serializable parse output: ${shown}${more}`);
|
|
239
258
|
}
|
|
240
259
|
onFileProgress?.(total, total, 'done');
|
|
241
|
-
return
|
|
260
|
+
return perGroup;
|
|
242
261
|
};
|
|
243
262
|
// ============================================================================
|
|
244
263
|
// Public API
|