@saluzi/codegraph 0.1.0 → 0.2.0
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/LICENSE +21 -0
- package/README.md +885 -0
- package/package.json +42 -10
- package/scripts/add-lang/bench.sh +60 -0
- package/scripts/add-lang/check-grammar.mjs +75 -0
- package/scripts/add-lang/dump-ast.mjs +103 -0
- package/scripts/add-lang/verify-extraction.mjs +70 -0
- package/scripts/agent-eval/ab-adoption.sh +91 -0
- package/scripts/agent-eval/ab-hook.sh +86 -0
- package/scripts/agent-eval/ab-impl.sh +78 -0
- package/scripts/agent-eval/ab-new-vs-baseline.sh +102 -0
- package/scripts/agent-eval/ab-sufficiency.sh +78 -0
- package/scripts/agent-eval/arms-F.sh +21 -0
- package/scripts/agent-eval/arms-matrix.sh +37 -0
- package/scripts/agent-eval/audit.sh +68 -0
- package/scripts/agent-eval/bench-readme.sh +28 -0
- package/scripts/agent-eval/bench-why-repo.sh +22 -0
- package/scripts/agent-eval/block-read-hook.sh +19 -0
- package/scripts/agent-eval/hook-settings.json +15 -0
- package/scripts/agent-eval/itrun.sh +120 -0
- package/scripts/agent-eval/offload-eval-3arm.sh +72 -0
- package/scripts/agent-eval/offload-eval-cost.mjs +133 -0
- package/scripts/agent-eval/offload-eval-effort.mjs +108 -0
- package/scripts/agent-eval/offload-eval-frontload-matrix.sh +25 -0
- package/scripts/agent-eval/offload-eval-frontload.sh +47 -0
- package/scripts/agent-eval/offload-eval-ground-truth.json +18 -0
- package/scripts/agent-eval/offload-eval-hook.mjs +84 -0
- package/scripts/agent-eval/offload-eval-judge.mjs +103 -0
- package/scripts/agent-eval/offload-eval-matrix.sh +20 -0
- package/scripts/agent-eval/offload-eval-metrics.mjs +94 -0
- package/scripts/agent-eval/offload-eval-refs1.sh +50 -0
- package/scripts/agent-eval/offload-eval-setup.sh +24 -0
- package/scripts/agent-eval/offload-eval-styles.sh +72 -0
- package/scripts/agent-eval/offload-eval-summarize.mjs +68 -0
- package/scripts/agent-eval/offload-eval.md +76 -0
- package/scripts/agent-eval/parse-arms.mjs +116 -0
- package/scripts/agent-eval/parse-bench-readme.mjs +84 -0
- package/scripts/agent-eval/parse-run.mjs +45 -0
- package/scripts/agent-eval/parse-session.mjs +93 -0
- package/scripts/agent-eval/probe-context.mjs +21 -0
- package/scripts/agent-eval/probe-explore.mjs +40 -0
- package/scripts/agent-eval/probe-node.mjs +20 -0
- package/scripts/agent-eval/probe-sweep.mjs +119 -0
- package/scripts/agent-eval/probe-trace.mjs +20 -0
- package/scripts/agent-eval/redirect-read-hook.sh +38 -0
- package/scripts/agent-eval/repro-concurrent-explore.mjs +119 -0
- package/scripts/agent-eval/repro-daemon-clients.mjs +125 -0
- package/scripts/agent-eval/run-agent.sh +34 -0
- package/scripts/agent-eval/run-all.sh +75 -0
- package/scripts/agent-eval/run-arms.sh +56 -0
- package/scripts/agent-eval/seq-matrix.mjs +137 -0
- package/scripts/build-bundle.sh +123 -0
- package/scripts/extract-release-notes.mjs +130 -0
- package/scripts/local-install.sh +41 -0
- package/scripts/npm-sdk.js +75 -0
- package/scripts/npm-shim.js +275 -0
- package/scripts/pack-npm.sh +119 -0
- package/scripts/prepare-release.mjs +270 -0
- package/dist/bin/codegraph.d.ts +0 -25
- package/dist/bin/node-version-check.d.ts +0 -37
- package/dist/bin/uninstall.d.ts +0 -14
- package/dist/context/formatter.d.ts +0 -33
- package/dist/context/formatter.js +0 -244
- package/dist/context/index.d.ts +0 -117
- package/dist/context/index.js +0 -1050
- package/dist/db/index.d.ts +0 -101
- package/dist/db/index.js +0 -250
- package/dist/db/migrations.d.ts +0 -47
- package/dist/db/migrations.js +0 -131
- package/dist/db/queries.d.ts +0 -291
- package/dist/db/queries.js +0 -1349
- package/dist/db/schema.sql +0 -151
- package/dist/db/sqlite-adapter.d.ts +0 -49
- package/dist/db/sqlite-adapter.js +0 -141
- package/dist/directory.d.ts +0 -62
- package/dist/directory.js +0 -264
- package/dist/errors.d.ts +0 -149
- package/dist/errors.js +0 -219
- package/dist/extraction/dfm-extractor.d.ts +0 -31
- package/dist/extraction/dfm-extractor.js +0 -151
- package/dist/extraction/grammars.d.ts +0 -94
- package/dist/extraction/grammars.js +0 -357
- package/dist/extraction/index.d.ts +0 -148
- package/dist/extraction/index.js +0 -1286
- package/dist/extraction/languages/c-cpp.d.ts +0 -4
- package/dist/extraction/languages/c-cpp.js +0 -126
- package/dist/extraction/languages/csharp.d.ts +0 -3
- package/dist/extraction/languages/csharp.js +0 -72
- package/dist/extraction/languages/dart.d.ts +0 -3
- package/dist/extraction/languages/dart.js +0 -192
- package/dist/extraction/languages/go.d.ts +0 -3
- package/dist/extraction/languages/go.js +0 -58
- package/dist/extraction/languages/index.d.ts +0 -10
- package/dist/extraction/languages/index.js +0 -49
- package/dist/extraction/languages/java.d.ts +0 -3
- package/dist/extraction/languages/java.js +0 -64
- package/dist/extraction/languages/javascript.d.ts +0 -3
- package/dist/extraction/languages/javascript.js +0 -90
- package/dist/extraction/languages/kotlin.d.ts +0 -3
- package/dist/extraction/languages/kotlin.js +0 -253
- package/dist/extraction/languages/lua.d.ts +0 -3
- package/dist/extraction/languages/lua.js +0 -150
- package/dist/extraction/languages/luau.d.ts +0 -3
- package/dist/extraction/languages/luau.js +0 -37
- package/dist/extraction/languages/pascal.d.ts +0 -3
- package/dist/extraction/languages/pascal.js +0 -66
- package/dist/extraction/languages/php.d.ts +0 -3
- package/dist/extraction/languages/php.js +0 -107
- package/dist/extraction/languages/python.d.ts +0 -3
- package/dist/extraction/languages/python.js +0 -56
- package/dist/extraction/languages/ruby.d.ts +0 -3
- package/dist/extraction/languages/ruby.js +0 -114
- package/dist/extraction/languages/rust.d.ts +0 -3
- package/dist/extraction/languages/rust.js +0 -109
- package/dist/extraction/languages/scala.d.ts +0 -3
- package/dist/extraction/languages/scala.js +0 -139
- package/dist/extraction/languages/swift.d.ts +0 -3
- package/dist/extraction/languages/swift.js +0 -91
- package/dist/extraction/languages/typescript.d.ts +0 -3
- package/dist/extraction/languages/typescript.js +0 -129
- package/dist/extraction/liquid-extractor.d.ts +0 -52
- package/dist/extraction/liquid-extractor.js +0 -313
- package/dist/extraction/parse-worker.d.ts +0 -8
- package/dist/extraction/parse-worker.js +0 -94
- package/dist/extraction/svelte-extractor.d.ts +0 -56
- package/dist/extraction/svelte-extractor.js +0 -272
- package/dist/extraction/tree-sitter-helpers.d.ts +0 -39
- package/dist/extraction/tree-sitter-helpers.js +0 -103
- package/dist/extraction/tree-sitter-types.d.ts +0 -191
- package/dist/extraction/tree-sitter-types.js +0 -10
- package/dist/extraction/tree-sitter.d.ts +0 -238
- package/dist/extraction/tree-sitter.js +0 -2430
- package/dist/extraction/vue-extractor.d.ts +0 -36
- package/dist/extraction/vue-extractor.js +0 -163
- package/dist/extraction/wasm/tree-sitter-c.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-c_sharp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-cpp.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-dart.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-go.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-java.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-javascript.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-kotlin.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-lua.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-luau.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-pascal.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-php.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-python.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-ruby.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-rust.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-scala.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-swift.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-tsx.wasm +0 -0
- package/dist/extraction/wasm/tree-sitter-typescript.wasm +0 -0
- package/dist/extraction/wasm-runtime-flags.d.ts +0 -46
- package/dist/extraction/wasm-runtime-flags.js +0 -105
- package/dist/graph/index.d.ts +0 -8
- package/dist/graph/index.js +0 -13
- package/dist/graph/queries.d.ts +0 -109
- package/dist/graph/queries.js +0 -366
- package/dist/graph/traversal.d.ts +0 -137
- package/dist/graph/traversal.js +0 -528
- package/dist/index.d.ts +0 -509
- package/dist/index.js +0 -800
- package/dist/installer/claude-md-template.d.ts +0 -19
- package/dist/installer/config-writer.d.ts +0 -29
- package/dist/installer/index.d.ts +0 -140
- package/dist/installer/instructions-template.d.ts +0 -30
- package/dist/installer/targets/claude.d.ts +0 -55
- package/dist/installer/targets/codex.d.ts +0 -18
- package/dist/installer/targets/cursor.d.ts +0 -35
- package/dist/installer/targets/hermes.d.ts +0 -18
- package/dist/installer/targets/opencode.d.ts +0 -30
- package/dist/installer/targets/registry.d.ts +0 -38
- package/dist/installer/targets/shared.d.ts +0 -92
- package/dist/installer/targets/toml.d.ts +0 -64
- package/dist/installer/targets/types.d.ts +0 -122
- package/dist/mcp/index.d.ts +0 -98
- package/dist/mcp/server-instructions.d.ts +0 -20
- package/dist/mcp/tools.d.ts +0 -269
- package/dist/mcp/transport.d.ts +0 -117
- package/dist/resolution/frameworks/cargo-workspace.d.ts +0 -20
- package/dist/resolution/frameworks/cargo-workspace.js +0 -225
- package/dist/resolution/frameworks/csharp.d.ts +0 -8
- package/dist/resolution/frameworks/csharp.js +0 -213
- package/dist/resolution/frameworks/drupal.d.ts +0 -51
- package/dist/resolution/frameworks/drupal.js +0 -335
- package/dist/resolution/frameworks/express.d.ts +0 -8
- package/dist/resolution/frameworks/express.js +0 -225
- package/dist/resolution/frameworks/go.d.ts +0 -8
- package/dist/resolution/frameworks/go.js +0 -158
- package/dist/resolution/frameworks/index.d.ts +0 -52
- package/dist/resolution/frameworks/index.js +0 -137
- package/dist/resolution/frameworks/java.d.ts +0 -8
- package/dist/resolution/frameworks/java.js +0 -177
- package/dist/resolution/frameworks/laravel.d.ts +0 -13
- package/dist/resolution/frameworks/laravel.js +0 -248
- package/dist/resolution/frameworks/nestjs.d.ts +0 -26
- package/dist/resolution/frameworks/nestjs.js +0 -374
- package/dist/resolution/frameworks/python.d.ts +0 -10
- package/dist/resolution/frameworks/python.js +0 -278
- package/dist/resolution/frameworks/react.d.ts +0 -8
- package/dist/resolution/frameworks/react.js +0 -272
- package/dist/resolution/frameworks/ruby.d.ts +0 -8
- package/dist/resolution/frameworks/ruby.js +0 -198
- package/dist/resolution/frameworks/rust.d.ts +0 -8
- package/dist/resolution/frameworks/rust.js +0 -207
- package/dist/resolution/frameworks/svelte.d.ts +0 -9
- package/dist/resolution/frameworks/svelte.js +0 -249
- package/dist/resolution/frameworks/swift.d.ts +0 -10
- package/dist/resolution/frameworks/swift.js +0 -376
- package/dist/resolution/frameworks/vue.d.ts +0 -9
- package/dist/resolution/frameworks/vue.js +0 -306
- package/dist/resolution/import-resolver.d.ts +0 -61
- package/dist/resolution/import-resolver.js +0 -663
- package/dist/resolution/index.d.ts +0 -118
- package/dist/resolution/index.js +0 -744
- package/dist/resolution/lru-cache.d.ts +0 -24
- package/dist/resolution/lru-cache.js +0 -62
- package/dist/resolution/name-matcher.d.ts +0 -50
- package/dist/resolution/name-matcher.js +0 -384
- package/dist/resolution/path-aliases.d.ts +0 -72
- package/dist/resolution/path-aliases.js +0 -238
- package/dist/resolution/strip-comments.d.ts +0 -40
- package/dist/resolution/strip-comments.js +0 -441
- package/dist/resolution/types.d.ts +0 -181
- package/dist/resolution/types.js +0 -8
- package/dist/search/query-parser.d.ts +0 -61
- package/dist/search/query-parser.js +0 -177
- package/dist/search/query-utils.d.ts +0 -59
- package/dist/search/query-utils.js +0 -383
- package/dist/sync/git-hooks.d.ts +0 -54
- package/dist/sync/git-hooks.js +0 -223
- package/dist/sync/index.d.ts +0 -25
- package/dist/sync/index.js +0 -28
- package/dist/sync/watch-policy.d.ts +0 -51
- package/dist/sync/watch-policy.js +0 -124
- package/dist/sync/watcher.d.ts +0 -83
- package/dist/sync/watcher.js +0 -192
- package/dist/types.d.ts +0 -433
- package/dist/types.js +0 -75
- package/dist/ui/glyphs.d.ts +0 -42
- package/dist/ui/shimmer-progress.d.ts +0 -11
- package/dist/ui/shimmer-worker.d.ts +0 -2
- package/dist/ui/types.d.ts +0 -20
- package/dist/utils.d.ts +0 -231
- package/dist/utils.js +0 -549
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple LRU cache backed by JavaScript's insertion-ordered Map.
|
|
3
|
-
*
|
|
4
|
-
* Used by ReferenceResolver to bound the per-resolver caches that
|
|
5
|
-
* previously grew without limit and OOM'd on large codebases (20k+
|
|
6
|
-
* files). Each cache is sized independently — see `index.ts` for
|
|
7
|
-
* the chosen limits per cache type.
|
|
8
|
-
*
|
|
9
|
-
* Eviction is plain LRU: on `set`, if the cache is full, the
|
|
10
|
-
* least-recently-used entry (the first one in iteration order) is
|
|
11
|
-
* evicted. Touching via `get` moves the entry to the most-recently-used
|
|
12
|
-
* position so hot keys survive eviction passes.
|
|
13
|
-
*/
|
|
14
|
-
export declare class LRUCache<K, V> {
|
|
15
|
-
private readonly max
|
|
16
|
-
private readonly store
|
|
17
|
-
constructor(max: number)
|
|
18
|
-
get size(): number
|
|
19
|
-
get(key: K): V | undefined
|
|
20
|
-
has(key: K): boolean
|
|
21
|
-
set(key: K, value: V): void
|
|
22
|
-
clear(): void
|
|
23
|
-
}
|
|
24
|
-
//# sourceMappingURL=lru-cache.d.ts.map
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LRUCache = void 0;
|
|
4
|
-
/**
|
|
5
|
-
* Simple LRU cache backed by JavaScript's insertion-ordered Map.
|
|
6
|
-
*
|
|
7
|
-
* Used by ReferenceResolver to bound the per-resolver caches that
|
|
8
|
-
* previously grew without limit and OOM'd on large codebases (20k+
|
|
9
|
-
* files). Each cache is sized independently — see `index.ts` for
|
|
10
|
-
* the chosen limits per cache type.
|
|
11
|
-
*
|
|
12
|
-
* Eviction is plain LRU: on `set`, if the cache is full, the
|
|
13
|
-
* least-recently-used entry (the first one in iteration order) is
|
|
14
|
-
* evicted. Touching via `get` moves the entry to the most-recently-used
|
|
15
|
-
* position so hot keys survive eviction passes.
|
|
16
|
-
*/
|
|
17
|
-
class LRUCache {
|
|
18
|
-
max;
|
|
19
|
-
store = new Map();
|
|
20
|
-
constructor(max) {
|
|
21
|
-
if (!Number.isFinite(max) || max <= 0) {
|
|
22
|
-
throw new Error(`LRUCache max must be a positive finite number, got ${max}`);
|
|
23
|
-
}
|
|
24
|
-
this.max = Math.floor(max);
|
|
25
|
-
}
|
|
26
|
-
get size() {
|
|
27
|
-
return this.store.size;
|
|
28
|
-
}
|
|
29
|
-
get(key) {
|
|
30
|
-
const value = this.store.get(key);
|
|
31
|
-
if (value === undefined) {
|
|
32
|
-
// Distinguish "missing" from "stored undefined" by checking has().
|
|
33
|
-
// We don't store undefined in practice, but be defensive.
|
|
34
|
-
return this.store.has(key) ? value : undefined;
|
|
35
|
-
}
|
|
36
|
-
// Refresh recency by re-inserting.
|
|
37
|
-
this.store.delete(key);
|
|
38
|
-
this.store.set(key, value);
|
|
39
|
-
return value;
|
|
40
|
-
}
|
|
41
|
-
has(key) {
|
|
42
|
-
return this.store.has(key);
|
|
43
|
-
}
|
|
44
|
-
set(key, value) {
|
|
45
|
-
if (this.store.has(key)) {
|
|
46
|
-
this.store.delete(key);
|
|
47
|
-
}
|
|
48
|
-
else if (this.store.size >= this.max) {
|
|
49
|
-
// Evict the oldest entry — first key in iteration order.
|
|
50
|
-
const oldest = this.store.keys().next().value;
|
|
51
|
-
if (oldest !== undefined) {
|
|
52
|
-
this.store.delete(oldest);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
this.store.set(key, value);
|
|
56
|
-
}
|
|
57
|
-
clear() {
|
|
58
|
-
this.store.clear();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
exports.LRUCache = LRUCache;
|
|
62
|
-
//# sourceMappingURL=lru-cache.js.map
|
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Name Matcher
|
|
3
|
-
*
|
|
4
|
-
* Handles symbol name matching for reference resolution.
|
|
5
|
-
*/
|
|
6
|
-
import { UnresolvedRef, ResolvedRef, ResolutionContext } from './types'
|
|
7
|
-
/**
|
|
8
|
-
* Try to resolve a path-like reference (e.g., "snippets/drawer-menu.liquid")
|
|
9
|
-
* by matching the filename against file nodes.
|
|
10
|
-
*/
|
|
11
|
-
export declare function matchByFilePath(
|
|
12
|
-
ref: UnresolvedRef,
|
|
13
|
-
context: ResolutionContext,
|
|
14
|
-
): ResolvedRef | null
|
|
15
|
-
/**
|
|
16
|
-
* Try to resolve a reference by exact name match
|
|
17
|
-
*/
|
|
18
|
-
export declare function matchByExactName(
|
|
19
|
-
ref: UnresolvedRef,
|
|
20
|
-
context: ResolutionContext,
|
|
21
|
-
): ResolvedRef | null
|
|
22
|
-
/**
|
|
23
|
-
* Try to resolve by qualified name
|
|
24
|
-
*/
|
|
25
|
-
export declare function matchByQualifiedName(
|
|
26
|
-
ref: UnresolvedRef,
|
|
27
|
-
context: ResolutionContext,
|
|
28
|
-
): ResolvedRef | null
|
|
29
|
-
/**
|
|
30
|
-
* Try to resolve by method name on a class/object
|
|
31
|
-
*/
|
|
32
|
-
export declare function matchMethodCall(
|
|
33
|
-
ref: UnresolvedRef,
|
|
34
|
-
context: ResolutionContext,
|
|
35
|
-
): ResolvedRef | null
|
|
36
|
-
/**
|
|
37
|
-
* Fuzzy match - last resort with lower confidence
|
|
38
|
-
*/
|
|
39
|
-
export declare function matchFuzzy(
|
|
40
|
-
ref: UnresolvedRef,
|
|
41
|
-
context: ResolutionContext,
|
|
42
|
-
): ResolvedRef | null
|
|
43
|
-
/**
|
|
44
|
-
* Match all strategies in order of confidence
|
|
45
|
-
*/
|
|
46
|
-
export declare function matchReference(
|
|
47
|
-
ref: UnresolvedRef,
|
|
48
|
-
context: ResolutionContext,
|
|
49
|
-
): ResolvedRef | null
|
|
50
|
-
//# sourceMappingURL=name-matcher.d.ts.map
|
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Name Matcher
|
|
4
|
-
*
|
|
5
|
-
* Handles symbol name matching for reference resolution.
|
|
6
|
-
*/
|
|
7
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
-
exports.matchByFilePath = matchByFilePath;
|
|
9
|
-
exports.matchByExactName = matchByExactName;
|
|
10
|
-
exports.matchByQualifiedName = matchByQualifiedName;
|
|
11
|
-
exports.matchMethodCall = matchMethodCall;
|
|
12
|
-
exports.matchFuzzy = matchFuzzy;
|
|
13
|
-
exports.matchReference = matchReference;
|
|
14
|
-
/**
|
|
15
|
-
* Try to resolve a path-like reference (e.g., "snippets/drawer-menu.liquid")
|
|
16
|
-
* by matching the filename against file nodes.
|
|
17
|
-
*/
|
|
18
|
-
function matchByFilePath(ref, context) {
|
|
19
|
-
if (!ref.referenceName.includes('/'))
|
|
20
|
-
return null;
|
|
21
|
-
// Extract the filename from the path
|
|
22
|
-
const fileName = ref.referenceName.split('/').pop();
|
|
23
|
-
if (!fileName)
|
|
24
|
-
return null;
|
|
25
|
-
// Search for file nodes with this name
|
|
26
|
-
const candidates = context.getNodesByName(fileName);
|
|
27
|
-
const fileNodes = candidates.filter(n => n.kind === 'file');
|
|
28
|
-
if (fileNodes.length === 0)
|
|
29
|
-
return null;
|
|
30
|
-
// Prefer exact path match on qualified_name
|
|
31
|
-
const exactMatch = fileNodes.find(n => n.qualifiedName === ref.referenceName || n.filePath === ref.referenceName);
|
|
32
|
-
if (exactMatch) {
|
|
33
|
-
return {
|
|
34
|
-
original: ref,
|
|
35
|
-
targetNodeId: exactMatch.id,
|
|
36
|
-
confidence: 0.95,
|
|
37
|
-
resolvedBy: 'file-path',
|
|
38
|
-
};
|
|
39
|
-
}
|
|
40
|
-
// Fall back to suffix match (e.g., ref="snippets/foo.liquid" matches "src/snippets/foo.liquid")
|
|
41
|
-
const suffixMatch = fileNodes.find(n => n.qualifiedName.endsWith(ref.referenceName) || n.filePath.endsWith(ref.referenceName));
|
|
42
|
-
if (suffixMatch) {
|
|
43
|
-
return {
|
|
44
|
-
original: ref,
|
|
45
|
-
targetNodeId: suffixMatch.id,
|
|
46
|
-
confidence: 0.85,
|
|
47
|
-
resolvedBy: 'file-path',
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
// If only one file node with this name, use it with lower confidence
|
|
51
|
-
if (fileNodes.length === 1) {
|
|
52
|
-
return {
|
|
53
|
-
original: ref,
|
|
54
|
-
targetNodeId: fileNodes[0].id,
|
|
55
|
-
confidence: 0.7,
|
|
56
|
-
resolvedBy: 'file-path',
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
return null;
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Try to resolve a reference by exact name match
|
|
63
|
-
*/
|
|
64
|
-
function matchByExactName(ref, context) {
|
|
65
|
-
const candidates = context.getNodesByName(ref.referenceName);
|
|
66
|
-
if (candidates.length === 0) {
|
|
67
|
-
return null;
|
|
68
|
-
}
|
|
69
|
-
// If only one match, use it — but penalize cross-language matches
|
|
70
|
-
if (candidates.length === 1) {
|
|
71
|
-
const isCrossLanguage = candidates[0].language !== ref.language;
|
|
72
|
-
return {
|
|
73
|
-
original: ref,
|
|
74
|
-
targetNodeId: candidates[0].id,
|
|
75
|
-
confidence: isCrossLanguage ? 0.5 : 0.9,
|
|
76
|
-
resolvedBy: 'exact-match',
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
// Multiple matches - try to narrow down
|
|
80
|
-
const bestMatch = findBestMatch(ref, candidates, context);
|
|
81
|
-
if (bestMatch) {
|
|
82
|
-
// Lower confidence when the match is from a distant/unrelated module
|
|
83
|
-
const proximity = computePathProximity(ref.filePath, bestMatch.filePath);
|
|
84
|
-
const confidence = proximity >= 30 ? 0.7 : 0.4;
|
|
85
|
-
return {
|
|
86
|
-
original: ref,
|
|
87
|
-
targetNodeId: bestMatch.id,
|
|
88
|
-
confidence,
|
|
89
|
-
resolvedBy: 'exact-match',
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
return null;
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* Try to resolve by qualified name
|
|
96
|
-
*/
|
|
97
|
-
function matchByQualifiedName(ref, context) {
|
|
98
|
-
// Check if the reference name looks qualified (contains :: or .)
|
|
99
|
-
if (!ref.referenceName.includes('::') && !ref.referenceName.includes('.')) {
|
|
100
|
-
return null;
|
|
101
|
-
}
|
|
102
|
-
const candidates = context.getNodesByQualifiedName(ref.referenceName);
|
|
103
|
-
if (candidates.length === 1) {
|
|
104
|
-
return {
|
|
105
|
-
original: ref,
|
|
106
|
-
targetNodeId: candidates[0].id,
|
|
107
|
-
confidence: 0.95,
|
|
108
|
-
resolvedBy: 'qualified-name',
|
|
109
|
-
};
|
|
110
|
-
}
|
|
111
|
-
// Try partial qualified name match
|
|
112
|
-
const parts = ref.referenceName.split(/[:.]/);
|
|
113
|
-
const lastName = parts[parts.length - 1];
|
|
114
|
-
if (lastName) {
|
|
115
|
-
const partialCandidates = context.getNodesByName(lastName);
|
|
116
|
-
for (const candidate of partialCandidates) {
|
|
117
|
-
if (candidate.qualifiedName.endsWith(ref.referenceName)) {
|
|
118
|
-
return {
|
|
119
|
-
original: ref,
|
|
120
|
-
targetNodeId: candidate.id,
|
|
121
|
-
confidence: 0.85,
|
|
122
|
-
resolvedBy: 'qualified-name',
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Try to resolve by method name on a class/object
|
|
131
|
-
*/
|
|
132
|
-
function matchMethodCall(ref, context) {
|
|
133
|
-
// Parse method call patterns like "obj.method" or "Class::method"
|
|
134
|
-
const dotMatch = ref.referenceName.match(/^(\w+)\.(\w+)$/);
|
|
135
|
-
const colonMatch = ref.referenceName.match(/^(\w+)::(\w+)$/);
|
|
136
|
-
const match = dotMatch || colonMatch;
|
|
137
|
-
if (!match) {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
const [, objectOrClass, methodName] = match;
|
|
141
|
-
// Strategy 1: Direct class name match (existing logic)
|
|
142
|
-
const classCandidates = context.getNodesByName(objectOrClass);
|
|
143
|
-
for (const classNode of classCandidates) {
|
|
144
|
-
if (classNode.kind === 'class' || classNode.kind === 'struct' || classNode.kind === 'interface') {
|
|
145
|
-
// Skip cross-language class matches
|
|
146
|
-
if (classNode.language !== ref.language)
|
|
147
|
-
continue;
|
|
148
|
-
const nodesInFile = context.getNodesInFile(classNode.filePath);
|
|
149
|
-
const methodNode = nodesInFile.find((n) => n.kind === 'method' &&
|
|
150
|
-
n.name === methodName &&
|
|
151
|
-
n.qualifiedName.includes(classNode.name));
|
|
152
|
-
if (methodNode) {
|
|
153
|
-
return {
|
|
154
|
-
original: ref,
|
|
155
|
-
targetNodeId: methodNode.id,
|
|
156
|
-
confidence: 0.85,
|
|
157
|
-
resolvedBy: 'qualified-name',
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
// Strategy 2: Instance variable receiver - try capitalized form to find class
|
|
163
|
-
// e.g., "permissionEngine" → look for classes containing "PermissionEngine"
|
|
164
|
-
const capitalizedReceiver = objectOrClass.charAt(0).toUpperCase() + objectOrClass.slice(1);
|
|
165
|
-
if (capitalizedReceiver !== objectOrClass) {
|
|
166
|
-
const fuzzyClassCandidates = context.getNodesByName(capitalizedReceiver);
|
|
167
|
-
for (const classNode of fuzzyClassCandidates) {
|
|
168
|
-
if (classNode.kind === 'class' || classNode.kind === 'struct' || classNode.kind === 'interface') {
|
|
169
|
-
// Skip cross-language class matches
|
|
170
|
-
if (classNode.language !== ref.language)
|
|
171
|
-
continue;
|
|
172
|
-
const nodesInFile = context.getNodesInFile(classNode.filePath);
|
|
173
|
-
const methodNode = nodesInFile.find((n) => n.kind === 'method' &&
|
|
174
|
-
n.name === methodName &&
|
|
175
|
-
n.qualifiedName.includes(classNode.name));
|
|
176
|
-
if (methodNode) {
|
|
177
|
-
return {
|
|
178
|
-
original: ref,
|
|
179
|
-
targetNodeId: methodNode.id,
|
|
180
|
-
confidence: 0.8,
|
|
181
|
-
resolvedBy: 'instance-method',
|
|
182
|
-
};
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
// Strategy 3: Find methods by name across the codebase, match by receiver
|
|
188
|
-
// name similarity with the containing class. Handles abbreviated variable
|
|
189
|
-
// names like permissionEngine → PermissionRuleEngine.
|
|
190
|
-
if (methodName) {
|
|
191
|
-
const methodCandidates = context.getNodesByName(methodName);
|
|
192
|
-
const methods = methodCandidates.filter((n) => n.kind === 'method' && n.name === methodName);
|
|
193
|
-
// Filter to same-language candidates first
|
|
194
|
-
const sameLanguageMethods = methods.filter(m => m.language === ref.language);
|
|
195
|
-
const targetMethods = sameLanguageMethods.length > 0 ? sameLanguageMethods : methods;
|
|
196
|
-
// If only one same-language method with this name exists, use it
|
|
197
|
-
if (targetMethods.length === 1 && targetMethods[0].language === ref.language) {
|
|
198
|
-
return {
|
|
199
|
-
original: ref,
|
|
200
|
-
targetNodeId: targetMethods[0].id,
|
|
201
|
-
confidence: 0.7,
|
|
202
|
-
resolvedBy: 'instance-method',
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
// Multiple methods: score by receiver name word overlap with class name
|
|
206
|
-
if (targetMethods.length > 1) {
|
|
207
|
-
const receiverWords = splitCamelCase(objectOrClass);
|
|
208
|
-
let bestMatch;
|
|
209
|
-
let bestScore = 0;
|
|
210
|
-
for (const method of targetMethods) {
|
|
211
|
-
const classWords = splitCamelCase(method.qualifiedName);
|
|
212
|
-
let score = receiverWords.filter(w => classWords.some(cw => cw.toLowerCase() === w.toLowerCase())).length;
|
|
213
|
-
// Bonus for same language
|
|
214
|
-
if (method.language === ref.language)
|
|
215
|
-
score += 1;
|
|
216
|
-
if (score > bestScore) {
|
|
217
|
-
bestScore = score;
|
|
218
|
-
bestMatch = method;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
if (bestMatch && bestScore >= 2) {
|
|
222
|
-
return {
|
|
223
|
-
original: ref,
|
|
224
|
-
targetNodeId: bestMatch.id,
|
|
225
|
-
confidence: 0.65,
|
|
226
|
-
resolvedBy: 'instance-method',
|
|
227
|
-
};
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return null;
|
|
232
|
-
}
|
|
233
|
-
/**
|
|
234
|
-
* Split a camelCase or PascalCase string into words.
|
|
235
|
-
*/
|
|
236
|
-
function splitCamelCase(str) {
|
|
237
|
-
return str.replace(/([a-z])([A-Z])/g, '$1 $2')
|
|
238
|
-
.replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2')
|
|
239
|
-
.split(/[\s._:\/\\]+/)
|
|
240
|
-
.filter(w => w.length > 1);
|
|
241
|
-
}
|
|
242
|
-
/**
|
|
243
|
-
* Compute directory proximity between two file paths.
|
|
244
|
-
* Returns a score based on the number of shared directory segments.
|
|
245
|
-
* Higher score = closer in directory tree.
|
|
246
|
-
*/
|
|
247
|
-
function computePathProximity(filePath1, filePath2) {
|
|
248
|
-
const dir1 = filePath1.split('/').slice(0, -1);
|
|
249
|
-
const dir2 = filePath2.split('/').slice(0, -1);
|
|
250
|
-
let shared = 0;
|
|
251
|
-
for (let i = 0; i < Math.min(dir1.length, dir2.length); i++) {
|
|
252
|
-
if (dir1[i] === dir2[i]) {
|
|
253
|
-
shared++;
|
|
254
|
-
}
|
|
255
|
-
else {
|
|
256
|
-
break;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
// Each shared directory segment contributes 15 points, capped at 80
|
|
260
|
-
return Math.min(shared * 15, 80);
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Find the best matching node when there are multiple candidates
|
|
264
|
-
*/
|
|
265
|
-
function findBestMatch(ref, candidates, _context) {
|
|
266
|
-
// Prioritization rules:
|
|
267
|
-
// 1. Same file > different file
|
|
268
|
-
// 2. Directory proximity (same module/package > different module)
|
|
269
|
-
// 3. Same language > different language
|
|
270
|
-
// 4. Functions/methods > classes/types (for call references)
|
|
271
|
-
// 5. Exported > non-exported
|
|
272
|
-
let bestScore = -1;
|
|
273
|
-
let bestNode = null;
|
|
274
|
-
for (const candidate of candidates) {
|
|
275
|
-
let score = 0;
|
|
276
|
-
// Same file bonus
|
|
277
|
-
if (candidate.filePath === ref.filePath) {
|
|
278
|
-
score += 100;
|
|
279
|
-
}
|
|
280
|
-
// Directory proximity bonus — strongly prefer same module/package
|
|
281
|
-
score += computePathProximity(ref.filePath, candidate.filePath);
|
|
282
|
-
// Language matching: strongly prefer same language, penalize cross-language
|
|
283
|
-
if (candidate.language === ref.language) {
|
|
284
|
-
score += 50;
|
|
285
|
-
}
|
|
286
|
-
else {
|
|
287
|
-
score -= 80;
|
|
288
|
-
}
|
|
289
|
-
// For call references, prefer functions/methods
|
|
290
|
-
if (ref.referenceKind === 'calls') {
|
|
291
|
-
if (candidate.kind === 'function' || candidate.kind === 'method') {
|
|
292
|
-
score += 25;
|
|
293
|
-
}
|
|
294
|
-
}
|
|
295
|
-
// For instantiation references (`new Foo()`), prefer class-like
|
|
296
|
-
// targets — without this, a function named `Foo` in another module
|
|
297
|
-
// could outscore the actual class.
|
|
298
|
-
if (ref.referenceKind === 'instantiates') {
|
|
299
|
-
if (candidate.kind === 'class' ||
|
|
300
|
-
candidate.kind === 'struct' ||
|
|
301
|
-
candidate.kind === 'interface') {
|
|
302
|
-
score += 25;
|
|
303
|
-
}
|
|
304
|
-
}
|
|
305
|
-
// For decorator references (`@Foo`), prefer functions. Class
|
|
306
|
-
// decorators (Python `@SomeClass`, Java annotation interfaces)
|
|
307
|
-
// also resolve here, hence the smaller class bonus.
|
|
308
|
-
if (ref.referenceKind === 'decorates') {
|
|
309
|
-
if (candidate.kind === 'function' || candidate.kind === 'method') {
|
|
310
|
-
score += 25;
|
|
311
|
-
}
|
|
312
|
-
else if (candidate.kind === 'class' || candidate.kind === 'interface') {
|
|
313
|
-
score += 15;
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
// Exported bonus
|
|
317
|
-
if (candidate.isExported) {
|
|
318
|
-
score += 10;
|
|
319
|
-
}
|
|
320
|
-
// Closer line number (within same file)
|
|
321
|
-
if (candidate.filePath === ref.filePath && candidate.startLine) {
|
|
322
|
-
const distance = Math.abs(candidate.startLine - ref.line);
|
|
323
|
-
score += Math.max(0, 20 - distance / 10);
|
|
324
|
-
}
|
|
325
|
-
if (score > bestScore) {
|
|
326
|
-
bestScore = score;
|
|
327
|
-
bestNode = candidate;
|
|
328
|
-
}
|
|
329
|
-
}
|
|
330
|
-
return bestNode;
|
|
331
|
-
}
|
|
332
|
-
/**
|
|
333
|
-
* Fuzzy match - last resort with lower confidence
|
|
334
|
-
*/
|
|
335
|
-
function matchFuzzy(ref, context) {
|
|
336
|
-
const lowerName = ref.referenceName.toLowerCase();
|
|
337
|
-
// Use pre-built lowercase index for O(1) lookup instead of scanning all nodes
|
|
338
|
-
const candidates = context.getNodesByLowerName(lowerName);
|
|
339
|
-
// Filter to callable kinds only (function, method, class)
|
|
340
|
-
const callableKinds = new Set(['function', 'method', 'class']);
|
|
341
|
-
const callableCandidates = candidates.filter((n) => callableKinds.has(n.kind));
|
|
342
|
-
// Prefer same-language matches
|
|
343
|
-
const sameLanguageCandidates = callableCandidates.filter(n => n.language === ref.language);
|
|
344
|
-
const finalCandidates = sameLanguageCandidates.length > 0 ? sameLanguageCandidates : callableCandidates;
|
|
345
|
-
if (finalCandidates.length === 1) {
|
|
346
|
-
const isCrossLanguage = finalCandidates[0].language !== ref.language;
|
|
347
|
-
return {
|
|
348
|
-
original: ref,
|
|
349
|
-
targetNodeId: finalCandidates[0].id,
|
|
350
|
-
confidence: isCrossLanguage ? 0.3 : 0.5,
|
|
351
|
-
resolvedBy: 'fuzzy',
|
|
352
|
-
};
|
|
353
|
-
}
|
|
354
|
-
return null;
|
|
355
|
-
}
|
|
356
|
-
/**
|
|
357
|
-
* Match all strategies in order of confidence
|
|
358
|
-
*/
|
|
359
|
-
function matchReference(ref, context) {
|
|
360
|
-
// Try strategies in order of confidence
|
|
361
|
-
let result;
|
|
362
|
-
// 0. File path match (e.g., "snippets/drawer-menu.liquid" → file node)
|
|
363
|
-
result = matchByFilePath(ref, context);
|
|
364
|
-
if (result)
|
|
365
|
-
return result;
|
|
366
|
-
// 1. Qualified name match (highest confidence)
|
|
367
|
-
result = matchByQualifiedName(ref, context);
|
|
368
|
-
if (result)
|
|
369
|
-
return result;
|
|
370
|
-
// 2. Method call pattern
|
|
371
|
-
result = matchMethodCall(ref, context);
|
|
372
|
-
if (result)
|
|
373
|
-
return result;
|
|
374
|
-
// 3. Exact name match
|
|
375
|
-
result = matchByExactName(ref, context);
|
|
376
|
-
if (result)
|
|
377
|
-
return result;
|
|
378
|
-
// 4. Fuzzy match (lowest confidence)
|
|
379
|
-
result = matchFuzzy(ref, context);
|
|
380
|
-
if (result)
|
|
381
|
-
return result;
|
|
382
|
-
return null;
|
|
383
|
-
}
|
|
384
|
-
//# sourceMappingURL=name-matcher.js.map
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project-level import-path alias loading.
|
|
3
|
-
*
|
|
4
|
-
* Reads `compilerOptions.paths` from `tsconfig.json` / `jsconfig.json`
|
|
5
|
-
* at the project root and converts the patterns into a form the
|
|
6
|
-
* import-resolver can consult.
|
|
7
|
-
*
|
|
8
|
-
* This is the single biggest blocker to accurate resolution on modern
|
|
9
|
-
* JS/TS codebases: aliases like `@/components/Foo` (Next, Nuxt, Nest,
|
|
10
|
-
* Vite scaffolds) point into a `paths` map the resolver previously
|
|
11
|
-
* ignored — every import through an alias was treated as unresolvable
|
|
12
|
-
* unless it happened to match the small hard-coded fallback list.
|
|
13
|
-
*
|
|
14
|
-
* Scope deliberately small for v1:
|
|
15
|
-
* - reads tsconfig.json, then jsconfig.json
|
|
16
|
-
* - honours top-level `compilerOptions.baseUrl` and `compilerOptions.paths`
|
|
17
|
-
* - supports `*` wildcard (the only TS-supported wildcard)
|
|
18
|
-
* - does NOT follow `extends` chains yet (most projects don't need it)
|
|
19
|
-
* - does NOT read Vite/webpack/Rollup configs (separate follow-up)
|
|
20
|
-
*
|
|
21
|
-
* The file is parsed as JSON-with-comments-tolerant — tsconfigs in the
|
|
22
|
-
* wild routinely contain `//` and `/* *\/` comments and trailing
|
|
23
|
-
* commas, which JSON.parse rejects. We strip those before parsing.
|
|
24
|
-
*/
|
|
25
|
-
/** A single alias pattern from `compilerOptions.paths`. */
|
|
26
|
-
export interface AliasPattern {
|
|
27
|
-
/** The literal prefix before `*` (or the whole pattern if no `*`). */
|
|
28
|
-
prefix: string
|
|
29
|
-
/** The literal suffix after `*` (almost always empty). */
|
|
30
|
-
suffix: string
|
|
31
|
-
/** Whether the pattern contains a `*` wildcard. */
|
|
32
|
-
hasWildcard: boolean
|
|
33
|
-
/**
|
|
34
|
-
* Replacement templates. When `hasWildcard` is true, `*` in the
|
|
35
|
-
* replacement is filled with the captured wildcard portion of the
|
|
36
|
-
* import path. Stored relative to {@link AliasMap.baseUrl}.
|
|
37
|
-
* tsconfig allows multiple targets per alias (priority order).
|
|
38
|
-
*/
|
|
39
|
-
replacements: string[]
|
|
40
|
-
}
|
|
41
|
-
export interface AliasMap {
|
|
42
|
-
/** Absolute path. The directory `compilerOptions.paths` is rooted at. */
|
|
43
|
-
baseUrl: string
|
|
44
|
-
/**
|
|
45
|
-
* Patterns ordered by specificity: longer prefix first, then literal-
|
|
46
|
-
* before-wildcard, so the resolver tries the most-specific match.
|
|
47
|
-
*/
|
|
48
|
-
patterns: AliasPattern[]
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Load aliases for `projectRoot`. Returns `null` when no tsconfig /
|
|
52
|
-
* jsconfig is present or when the file has no usable `paths`.
|
|
53
|
-
*
|
|
54
|
-
* Cheap to call repeatedly — caching is the caller's job (the
|
|
55
|
-
* resolver does it via {@link aliasCache}).
|
|
56
|
-
*/
|
|
57
|
-
export declare function loadProjectAliases(projectRoot: string): AliasMap | null
|
|
58
|
-
/**
|
|
59
|
-
* Resolve an import path through an {@link AliasMap}. Returns the list
|
|
60
|
-
* of candidate filesystem paths (relative to `projectRoot`), in the
|
|
61
|
-
* priority order defined by tsconfig (multiple replacements per alias
|
|
62
|
-
* are tried in order). Returns `[]` when no alias matches.
|
|
63
|
-
*
|
|
64
|
-
* Callers still need to try each candidate with the language's
|
|
65
|
-
* extension list — this function only does the alias rewrite.
|
|
66
|
-
*/
|
|
67
|
-
export declare function applyAliases(
|
|
68
|
-
importPath: string,
|
|
69
|
-
aliases: AliasMap,
|
|
70
|
-
projectRoot: string,
|
|
71
|
-
): string[]
|
|
72
|
-
//# sourceMappingURL=path-aliases.d.ts.map
|