@lzehrung/codegraph 2.3.26 → 2.3.28
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/codegraph-skill/codegraph/SKILL.md +1 -0
- package/dist/agent/explain.d.ts +9 -1
- package/dist/agent/explain.d.ts.map +1 -1
- package/dist/agent/explain.js +18 -1
- package/dist/agent/explain.js.map +1 -1
- package/dist/agent/refactor-plan.d.ts +2 -0
- package/dist/agent/refactor-plan.d.ts.map +1 -1
- package/dist/agent/refactor-plan.js +11 -0
- package/dist/agent/refactor-plan.js.map +1 -1
- package/dist/agent/rename-preview.d.ts.map +1 -1
- package/dist/agent/rename-preview.js +49 -11
- package/dist/agent/rename-preview.js.map +1 -1
- package/dist/agent-tools.d.ts +2 -1
- package/dist/agent-tools.d.ts.map +1 -1
- package/dist/agent-tools.js +8 -0
- package/dist/agent-tools.js.map +1 -1
- package/dist/agent.d.ts +1 -1
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js.map +1 -1
- package/dist/bin/cli.js +3933 -2390
- package/dist/bin/query-index-worker.js +56 -18
- package/dist/cli/navigation.d.ts.map +1 -1
- package/dist/cli/navigation.js +4 -0
- package/dist/cli/navigation.js.map +1 -1
- package/dist/impact/call-compatibility.js +3 -3
- package/dist/impact/call-compatibility.js.map +1 -1
- package/dist/impact/direct.js +1 -1
- package/dist/impact/direct.js.map +1 -1
- package/dist/impact/reference-cache.d.ts +1 -0
- package/dist/impact/reference-cache.d.ts.map +1 -1
- package/dist/impact/reference-cache.js +44 -18
- package/dist/impact/reference-cache.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/indexer/build-cache/module-cache.d.ts.map +1 -1
- package/dist/indexer/build-cache/module-cache.js +30 -0
- package/dist/indexer/build-cache/module-cache.js.map +1 -1
- package/dist/indexer/build-cache/options.d.ts +14 -2
- package/dist/indexer/build-cache/options.d.ts.map +1 -1
- package/dist/indexer/build-cache/options.js +14 -2
- package/dist/indexer/build-cache/options.js.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.d.ts.map +1 -1
- package/dist/indexer/build-cache/project-snapshot.js +60 -5
- package/dist/indexer/build-cache/project-snapshot.js.map +1 -1
- package/dist/indexer/import-types.d.ts +14 -1
- package/dist/indexer/import-types.d.ts.map +1 -1
- package/dist/indexer/imports/binding-ranges.d.ts +50 -0
- package/dist/indexer/imports/binding-ranges.d.ts.map +1 -0
- package/dist/indexer/imports/binding-ranges.js +297 -0
- package/dist/indexer/imports/binding-ranges.js.map +1 -0
- package/dist/indexer/imports/js-text-imports.d.ts +4 -0
- package/dist/indexer/imports/js-text-imports.d.ts.map +1 -1
- package/dist/indexer/imports/js-text-imports.js +210 -48
- package/dist/indexer/imports/js-text-imports.js.map +1 -1
- package/dist/indexer/imports/language-specific.d.ts +3 -0
- package/dist/indexer/imports/language-specific.d.ts.map +1 -1
- package/dist/indexer/imports/language-specific.js +97 -23
- package/dist/indexer/imports/language-specific.js.map +1 -1
- package/dist/indexer/imports/native-captures.d.ts.map +1 -1
- package/dist/indexer/imports/native-captures.js +52 -30
- package/dist/indexer/imports/native-captures.js.map +1 -1
- package/dist/indexer/imports/python.d.ts +2 -0
- package/dist/indexer/imports/python.d.ts.map +1 -1
- package/dist/indexer/imports/python.js +55 -18
- package/dist/indexer/imports/python.js.map +1 -1
- package/dist/indexer/imports.d.ts.map +1 -1
- package/dist/indexer/imports.js +15 -1
- package/dist/indexer/imports.js.map +1 -1
- package/dist/indexer/navigation-goto.d.ts +1 -1
- package/dist/indexer/navigation-goto.d.ts.map +1 -1
- package/dist/indexer/navigation-goto.js +66 -17
- package/dist/indexer/navigation-goto.js.map +1 -1
- package/dist/indexer/navigation-references.d.ts +23 -2
- package/dist/indexer/navigation-references.d.ts.map +1 -1
- package/dist/indexer/navigation-references.js +196 -4
- package/dist/indexer/navigation-references.js.map +1 -1
- package/dist/indexer/navigation.d.ts +9 -3
- package/dist/indexer/navigation.d.ts.map +1 -1
- package/dist/indexer/navigation.js +154 -41
- package/dist/indexer/navigation.js.map +1 -1
- package/dist/indexer/scope.d.ts.map +1 -1
- package/dist/indexer/scope.js +18 -0
- package/dist/indexer/scope.js.map +1 -1
- package/dist/indexer/symbols.d.ts +1 -0
- package/dist/indexer/symbols.d.ts.map +1 -1
- package/dist/indexer/types.d.ts +10 -0
- package/dist/indexer/types.d.ts.map +1 -1
- package/dist/indexer.d.ts +1 -1
- package/dist/indexer.d.ts.map +1 -1
- package/dist/indexer.js.map +1 -1
- package/dist/languages/definitions/javascript.d.ts.map +1 -1
- package/dist/languages/definitions/javascript.js +10 -2
- package/dist/languages/definitions/javascript.js.map +1 -1
- package/dist/languages/definitions/php.d.ts.map +1 -1
- package/dist/languages/definitions/php.js +15 -8
- package/dist/languages/definitions/php.js.map +1 -1
- package/dist/languages/definitions/python.d.ts.map +1 -1
- package/dist/languages/definitions/python.js +11 -1
- package/dist/languages/definitions/python.js.map +1 -1
- package/dist/languages/definitions/typescript.d.ts.map +1 -1
- package/dist/languages/definitions/typescript.js +20 -3
- package/dist/languages/definitions/typescript.js.map +1 -1
- package/dist/languages/definitions/zig.d.ts.map +1 -1
- package/dist/languages/definitions/zig.js +10 -3
- package/dist/languages/definitions/zig.js.map +1 -1
- package/dist/languages/import-statement-parsers.d.ts +3 -0
- package/dist/languages/import-statement-parsers.d.ts.map +1 -1
- package/dist/languages/import-statement-parsers.js +4 -0
- package/dist/languages/import-statement-parsers.js.map +1 -1
- package/dist/mcp/handlers.d.ts +2 -1
- package/dist/mcp/handlers.d.ts.map +1 -1
- package/dist/mcp/handlers.js +15 -1
- package/dist/mcp/handlers.js.map +1 -1
- package/dist/review/summaries.d.ts.map +1 -1
- package/dist/review/summaries.js +11 -19
- package/dist/review/summaries.js.map +1 -1
- package/dist/review/types.d.ts +2 -1
- package/dist/review/types.d.ts.map +1 -1
- package/dist/review/types.js.map +1 -1
- package/dist/session.d.ts +2 -9
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/sql/navigation.d.ts +6 -1
- package/dist/sql/navigation.d.ts.map +1 -1
- package/dist/sql/navigation.js +35 -3
- package/dist/sql/navigation.js.map +1 -1
- package/dist/util/comments.d.ts +10 -0
- package/dist/util/comments.d.ts.map +1 -1
- package/dist/util/comments.js +43 -2
- package/dist/util/comments.js.map +1 -1
- package/dist/util/lines.d.ts +2 -0
- package/dist/util/lines.d.ts.map +1 -1
- package/dist/util/lines.js +14 -0
- package/dist/util/lines.js.map +1 -1
- package/dist/util/resolution/cargo-targets.d.ts +8 -0
- package/dist/util/resolution/cargo-targets.d.ts.map +1 -0
- package/dist/util/resolution/cargo-targets.js +186 -0
- package/dist/util/resolution/cargo-targets.js.map +1 -0
- package/dist/util/resolution/rust.d.ts.map +1 -1
- package/dist/util/resolution/rust.js +264 -26
- package/dist/util/resolution/rust.js.map +1 -1
- package/docs/mcp.md +1 -1
- package/package.json +3 -3
package/dist/util/lines.js
CHANGED
|
@@ -6,4 +6,18 @@ export function collectLineStartOffsets(source) {
|
|
|
6
6
|
}
|
|
7
7
|
return lineStarts;
|
|
8
8
|
}
|
|
9
|
+
export function positionAtOffset(lineStarts, index) {
|
|
10
|
+
let low = 0;
|
|
11
|
+
let high = lineStarts.length - 1;
|
|
12
|
+
while (low < high) {
|
|
13
|
+
const middle = Math.ceil((low + high) / 2);
|
|
14
|
+
if (lineStarts[middle] <= index) {
|
|
15
|
+
low = middle;
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
high = middle - 1;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return { line: low + 1, column: index - lineStarts[low] + 1, index };
|
|
22
|
+
}
|
|
9
23
|
//# sourceMappingURL=lines.js.map
|
package/dist/util/lines.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lines.js","sourceRoot":"","sources":["../../src/util/lines.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"lines.js","sourceRoot":"","sources":["../../src/util/lines.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,MAAM,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACtD,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI;YAAE,UAAU,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,UAAU,CAAC;AACpB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,UAA6B,EAAE,KAAa;IAC3E,IAAI,GAAG,GAAG,CAAC,CAAC;IACZ,IAAI,IAAI,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IACjC,OAAO,GAAG,GAAG,IAAI,EAAE,CAAC;QAClB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAI,UAAU,CAAC,MAAM,CAAE,IAAI,KAAK,EAAE,CAAC;YACjC,GAAG,GAAG,MAAM,CAAC;QACf,CAAC;aAAM,CAAC;YACN,IAAI,GAAG,MAAM,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,EAAE,MAAM,EAAE,KAAK,GAAG,UAAU,CAAC,GAAG,CAAE,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type RustCrateRoots = {
|
|
2
|
+
/** Existing, resolved, project-confined crate root files. */
|
|
3
|
+
roots: string[];
|
|
4
|
+
/** Every candidate path considered, existing or not, for cache revalidation. */
|
|
5
|
+
probed: string[];
|
|
6
|
+
};
|
|
7
|
+
export declare function rustCrateRootFiles(cargoRoot: string, projectRoot: string): Promise<RustCrateRoots>;
|
|
8
|
+
//# sourceMappingURL=cargo-targets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cargo-targets.d.ts","sourceRoot":"","sources":["../../../src/util/resolution/cargo-targets.ts"],"names":[],"mappings":"AAsKA,MAAM,MAAM,cAAc,GAAG;IAC3B,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,gFAAgF;IAChF,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,wBAAsB,kBAAkB,CAAC,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAsCxG"}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import fsp from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { parse as parseToml } from "smol-toml";
|
|
4
|
+
import { isFilePathWithinRoot } from "../paths.js";
|
|
5
|
+
const AUTO_DISCOVERY_GROUPS = [
|
|
6
|
+
{ flag: "autobins", directory: path.join("src", "bin") },
|
|
7
|
+
{ flag: "autotests", directory: "tests" },
|
|
8
|
+
{ flag: "autoexamples", directory: "examples" },
|
|
9
|
+
{ flag: "autobenches", directory: "benches" },
|
|
10
|
+
];
|
|
11
|
+
function isTomlTable(value) {
|
|
12
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
13
|
+
}
|
|
14
|
+
function tomlTables(value) {
|
|
15
|
+
if (Array.isArray(value))
|
|
16
|
+
return value.filter(isTomlTable);
|
|
17
|
+
return isTomlTable(value) ? [value] : [];
|
|
18
|
+
}
|
|
19
|
+
function tomlString(table, key) {
|
|
20
|
+
const value = table[key];
|
|
21
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
22
|
+
}
|
|
23
|
+
function packageAutoFlag(parsed, key) {
|
|
24
|
+
const pkg = isTomlTable(parsed.package) ? parsed.package : undefined;
|
|
25
|
+
const fromPackage = pkg?.[key];
|
|
26
|
+
if (typeof fromPackage === "boolean")
|
|
27
|
+
return fromPackage;
|
|
28
|
+
const fromRoot = parsed[key];
|
|
29
|
+
if (typeof fromRoot === "boolean")
|
|
30
|
+
return fromRoot;
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
function packageBuildScriptPath(parsed) {
|
|
34
|
+
const pkg = isTomlTable(parsed.package) ? parsed.package : undefined;
|
|
35
|
+
const build = pkg?.build;
|
|
36
|
+
if (typeof build === "boolean") {
|
|
37
|
+
if (!build)
|
|
38
|
+
return null;
|
|
39
|
+
return "build.rs";
|
|
40
|
+
}
|
|
41
|
+
if (typeof build === "string" && build.length)
|
|
42
|
+
return build;
|
|
43
|
+
return "build.rs";
|
|
44
|
+
}
|
|
45
|
+
function packageName(parsed) {
|
|
46
|
+
const pkg = isTomlTable(parsed.package) ? parsed.package : undefined;
|
|
47
|
+
return pkg ? tomlString(pkg, "name") : undefined;
|
|
48
|
+
}
|
|
49
|
+
function inferredNamedTargetDirectory(kind) {
|
|
50
|
+
if (kind === "bin")
|
|
51
|
+
return path.join("src", "bin");
|
|
52
|
+
if (kind === "example")
|
|
53
|
+
return "examples";
|
|
54
|
+
if (kind === "test")
|
|
55
|
+
return "tests";
|
|
56
|
+
return "benches";
|
|
57
|
+
}
|
|
58
|
+
function inferredNamedTargetPaths(kind, name, pkgName) {
|
|
59
|
+
const directory = inferredNamedTargetDirectory(kind);
|
|
60
|
+
const candidates = [path.join(directory, `${name}.rs`), path.join(directory, name, "main.rs")];
|
|
61
|
+
if (kind === "bin" && pkgName && name === pkgName) {
|
|
62
|
+
candidates.push(path.join("src", "main.rs"));
|
|
63
|
+
}
|
|
64
|
+
return candidates;
|
|
65
|
+
}
|
|
66
|
+
function explicitTargetPaths(parsed) {
|
|
67
|
+
const paths = [];
|
|
68
|
+
const lib = isTomlTable(parsed.lib) ? parsed.lib : undefined;
|
|
69
|
+
const libPath = lib ? tomlString(lib, "path") : undefined;
|
|
70
|
+
if (libPath)
|
|
71
|
+
paths.push(libPath);
|
|
72
|
+
const pkgName = packageName(parsed);
|
|
73
|
+
for (const key of ["bin", "example", "test", "bench"]) {
|
|
74
|
+
for (const target of tomlTables(parsed[key])) {
|
|
75
|
+
const targetPath = tomlString(target, "path");
|
|
76
|
+
if (targetPath) {
|
|
77
|
+
paths.push(targetPath);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const name = tomlString(target, "name");
|
|
81
|
+
if (!name)
|
|
82
|
+
continue;
|
|
83
|
+
paths.push(...inferredNamedTargetPaths(key, name, pkgName));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return paths;
|
|
87
|
+
}
|
|
88
|
+
async function parseCargoToml(cargoRoot) {
|
|
89
|
+
try {
|
|
90
|
+
const raw = await fsp.readFile(path.join(cargoRoot, "Cargo.toml"), "utf8");
|
|
91
|
+
const parsed = parseToml(raw);
|
|
92
|
+
return isTomlTable(parsed) ? parsed : null;
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
return null;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
async function acceptCrateRoot(candidate, projectRoot, requireRustExtension = false) {
|
|
99
|
+
const resolved = path.resolve(candidate);
|
|
100
|
+
if (requireRustExtension && !resolved.endsWith(".rs"))
|
|
101
|
+
return null;
|
|
102
|
+
try {
|
|
103
|
+
const stat = await fsp.stat(resolved);
|
|
104
|
+
if (!stat.isFile())
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if (!isFilePathWithinRoot(projectRoot, resolved))
|
|
111
|
+
return null;
|
|
112
|
+
try {
|
|
113
|
+
const realRoot = await fsp.realpath(projectRoot);
|
|
114
|
+
const realCandidate = await fsp.realpath(resolved);
|
|
115
|
+
if (!isFilePathWithinRoot(realRoot, realCandidate))
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
return resolved;
|
|
122
|
+
}
|
|
123
|
+
async function addCrateRoot(roots, probed, candidate, projectRoot, requireRustExtension = false) {
|
|
124
|
+
const resolved = path.resolve(candidate);
|
|
125
|
+
probed.add(resolved);
|
|
126
|
+
const accepted = await acceptCrateRoot(resolved, projectRoot, requireRustExtension);
|
|
127
|
+
if (accepted)
|
|
128
|
+
roots.add(accepted);
|
|
129
|
+
}
|
|
130
|
+
async function addAutodiscoveredDirectory(roots, probed, directory, projectRoot) {
|
|
131
|
+
probed.add(path.resolve(directory));
|
|
132
|
+
let entries = [];
|
|
133
|
+
try {
|
|
134
|
+
entries = await fsp.readdir(directory, { withFileTypes: true });
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
if (entry.isDirectory()) {
|
|
141
|
+
await addCrateRoot(roots, probed, path.join(directory, entry.name, "main.rs"), projectRoot, true);
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
if (entry.name.endsWith(".rs")) {
|
|
145
|
+
await addCrateRoot(roots, probed, path.join(directory, entry.name), projectRoot, true);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
export async function rustCrateRootFiles(cargoRoot, projectRoot) {
|
|
150
|
+
const root = path.resolve(cargoRoot);
|
|
151
|
+
const roots = new Set();
|
|
152
|
+
const probed = new Set();
|
|
153
|
+
const parsed = await parseCargoToml(root);
|
|
154
|
+
if (parsed && !isTomlTable(parsed.package)) {
|
|
155
|
+
return { roots: [], probed: [] };
|
|
156
|
+
}
|
|
157
|
+
if (parsed) {
|
|
158
|
+
for (const relativePath of explicitTargetPaths(parsed)) {
|
|
159
|
+
await addCrateRoot(roots, probed, path.resolve(root, relativePath), projectRoot);
|
|
160
|
+
}
|
|
161
|
+
const buildScript = packageBuildScriptPath(parsed);
|
|
162
|
+
if (buildScript) {
|
|
163
|
+
await addCrateRoot(roots, probed, path.resolve(root, buildScript), projectRoot);
|
|
164
|
+
}
|
|
165
|
+
const lib = isTomlTable(parsed.lib) ? parsed.lib : undefined;
|
|
166
|
+
const libPath = lib ? tomlString(lib, "path") : undefined;
|
|
167
|
+
if (!libPath && (lib || packageAutoFlag(parsed, "autolib"))) {
|
|
168
|
+
await addCrateRoot(roots, probed, path.join(root, "src", "lib.rs"), projectRoot);
|
|
169
|
+
}
|
|
170
|
+
if (packageAutoFlag(parsed, "autobins")) {
|
|
171
|
+
await addCrateRoot(roots, probed, path.join(root, "src", "main.rs"), projectRoot);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
await addCrateRoot(roots, probed, path.join(root, "build.rs"), projectRoot);
|
|
176
|
+
await addCrateRoot(roots, probed, path.join(root, "src", "lib.rs"), projectRoot);
|
|
177
|
+
await addCrateRoot(roots, probed, path.join(root, "src", "main.rs"), projectRoot);
|
|
178
|
+
}
|
|
179
|
+
for (const group of AUTO_DISCOVERY_GROUPS) {
|
|
180
|
+
if (parsed && !packageAutoFlag(parsed, group.flag))
|
|
181
|
+
continue;
|
|
182
|
+
await addAutodiscoveredDirectory(roots, probed, path.join(root, group.directory), projectRoot);
|
|
183
|
+
}
|
|
184
|
+
return { roots: [...roots], probed: [...probed] };
|
|
185
|
+
}
|
|
186
|
+
//# sourceMappingURL=cargo-targets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cargo-targets.js","sourceRoot":"","sources":["../../../src/util/resolution/cargo-targets.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rust.d.ts","sourceRoot":"","sources":["../../../src/util/resolution/rust.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"rust.d.ts","sourceRoot":"","sources":["../../../src/util/resolution/rust.ts"],"names":[],"mappings":"AAmKA,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,MAAM,CAWzF;AAED,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAoB1E;AAED,wBAAgB,mCAAmC,CAAC,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAGnG;AAWD,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,GAAG,MAAM,EAAE,CAEnG;AAeD,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,CAAC,EAAE,MAAM,GAAG,MAAM,CASjH;AAED,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,mBAAmB,CAAC,EAAE,MAAM,EAC5B,UAAU,SAAI,GACb,MAAM,GAAG,SAAS,CAMpB;AA8HD,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,EACnB,mBAAmB,CAAC,EAAE,MAAM,GAC3B,MAAM,GAAG,SAAS,CAWpB;AAyfD,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,aAAa,CAAC,EAAE,MAAM,EACtB,mBAAmB,CAAC,EAAE,MAAM,GAC3B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiDxB"}
|
|
@@ -3,12 +3,16 @@ import path from "node:path";
|
|
|
3
3
|
import { isRustItemStartBoundary, skipRustAttribute, skipRustBalancedDelimiters, skipRustCommentOrLiteral, skipRustCommentsAndWhitespaceBackward, skipRustMacroTokenTree, skipRustOuterAttribute, } from "../../languages/import-statement-parsers.js";
|
|
4
4
|
import { XID_IDENTIFIER_SOURCE } from "../identifiers.js";
|
|
5
5
|
import { lruMapGet, lruMapSet } from "../lru-map.js";
|
|
6
|
-
import { isFilePathWithinRoot } from "../paths.js";
|
|
6
|
+
import { fileIdentityKey, isFilePathWithinRoot } from "../paths.js";
|
|
7
7
|
import { fileExists } from "../workspace.js";
|
|
8
|
+
import { rustCrateRootFiles } from "./cargo-targets.js";
|
|
8
9
|
function isWithinOrEqual(candidate, root) {
|
|
9
10
|
const relative = path.relative(root, candidate);
|
|
10
11
|
return !relative || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
11
12
|
}
|
|
13
|
+
function rustPathIdentity(filePath) {
|
|
14
|
+
return fileIdentityKey(path.resolve(filePath));
|
|
15
|
+
}
|
|
12
16
|
async function findNearestCargoRoot(fromFile, projectRoot) {
|
|
13
17
|
const root = path.resolve(projectRoot);
|
|
14
18
|
let dir = path.dirname(path.resolve(fromFile));
|
|
@@ -60,16 +64,31 @@ async function resolveRustModuleParts(baseDir, parts) {
|
|
|
60
64
|
const RUST_PATH_ATTRIBUTE_PATTERN = /#\s*\[\s*path\s*=\s*(?:r(#*)"([\s\S]*?)"\1|"([^"]*)")\s*\]/gu;
|
|
61
65
|
const RUST_CFG_TEST_ATTRIBUTE_PATTERN = /#\s*\[\s*cfg\s*\(\s*test\s*\)\s*\]/;
|
|
62
66
|
const RUST_VISIBILITY_PATTERN = /^(?:pub(?:\s*\([^)]*\))?\s+)/;
|
|
63
|
-
const RUST_MOD_NAME_PATTERN = new RegExp(String.raw `^mod\s+(${XID_IDENTIFIER_SOURCE})`, "u");
|
|
67
|
+
const RUST_MOD_NAME_PATTERN = new RegExp(String.raw `^mod\s+(?:r#)?(${XID_IDENTIFIER_SOURCE})`, "u");
|
|
64
68
|
const MAX_RUST_PATH_ATTRIBUTE_CACHE_ENTRIES = 256;
|
|
69
|
+
const MAX_RUST_MODULE_TREE_CACHE_ENTRIES = 256;
|
|
70
|
+
const MAX_RUST_MODULE_TREE_FILES = 4096;
|
|
71
|
+
const MAX_RUST_MODULE_TREE_DEPTH = 32;
|
|
72
|
+
const MISSING_PATH_SIGNATURE = "missing";
|
|
73
|
+
/**
|
|
74
|
+
* A cached module tree is re-checked against its recorded stat signatures at most once per
|
|
75
|
+
* interval. Every reachable file and every probed path contributes a signature, so validating on
|
|
76
|
+
* each lookup would cost one stat per crate file per resolved `super` specifier. The window bounds
|
|
77
|
+
* that to one sweep per interval; a source edit is therefore observed within the interval rather
|
|
78
|
+
* than on the next lookup.
|
|
79
|
+
*/
|
|
80
|
+
const RUST_MODULE_TREE_REVALIDATE_INTERVAL_MS = 100;
|
|
65
81
|
const EMPTY_RUST_MODULE_SCOPE = {
|
|
66
82
|
pathAttributes: new Map(),
|
|
67
83
|
inlineModules: new Map(),
|
|
84
|
+
declaredModules: [],
|
|
68
85
|
};
|
|
69
86
|
const rustPathAttributeCache = new Map();
|
|
70
87
|
const rustPathAttributeInflight = new Map();
|
|
88
|
+
const rustModuleTreeCache = new Map();
|
|
89
|
+
const rustModuleTreeInflight = new Map();
|
|
71
90
|
function createRustModuleScope() {
|
|
72
|
-
return { pathAttributes: new Map(), inlineModules: new Map() };
|
|
91
|
+
return { pathAttributes: new Map(), inlineModules: new Map(), declaredModules: [] };
|
|
73
92
|
}
|
|
74
93
|
function pathAttributeFromAttributeBlock(attributes) {
|
|
75
94
|
let last;
|
|
@@ -246,6 +265,9 @@ function scanRustModuleScope(source, start, end, scope) {
|
|
|
246
265
|
if (!testOnly && pathValue && !scope.pathAttributes.has(moduleName)) {
|
|
247
266
|
scope.pathAttributes.set(moduleName, pathValue);
|
|
248
267
|
}
|
|
268
|
+
if (!testOnly) {
|
|
269
|
+
scope.declaredModules.push({ name: moduleName, pathValue });
|
|
270
|
+
}
|
|
249
271
|
index = cursor + 1;
|
|
250
272
|
continue;
|
|
251
273
|
}
|
|
@@ -289,9 +311,21 @@ export function extractRustModPathAttribute(source, moduleName, statementStartIn
|
|
|
289
311
|
return undefined;
|
|
290
312
|
return extractRustModPathAttributeScopes(source).pathAttributes.get(moduleName);
|
|
291
313
|
}
|
|
292
|
-
async function isExistingAttributedPathInsideProject(projectRoot, attributedPath) {
|
|
293
|
-
if (
|
|
294
|
-
|
|
314
|
+
async function isExistingAttributedPathInsideProject(projectRoot, attributedPath, knownStat) {
|
|
315
|
+
if (knownStat !== undefined) {
|
|
316
|
+
if (knownStat === null || !knownStat.isFile())
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
319
|
+
else {
|
|
320
|
+
try {
|
|
321
|
+
const stat = await fsp.stat(attributedPath);
|
|
322
|
+
if (!stat.isFile())
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
295
329
|
if (!isFilePathWithinRoot(projectRoot, attributedPath))
|
|
296
330
|
return false;
|
|
297
331
|
try {
|
|
@@ -306,6 +340,27 @@ async function isExistingAttributedPathInsideProject(projectRoot, attributedPath
|
|
|
306
340
|
function rustPathAttributeSignature(stat) {
|
|
307
341
|
return `${stat.size}:${stat.mtimeMs}`;
|
|
308
342
|
}
|
|
343
|
+
async function currentPathSignature(target) {
|
|
344
|
+
try {
|
|
345
|
+
const stat = await fsp.stat(target);
|
|
346
|
+
return rustPathAttributeSignature(stat);
|
|
347
|
+
}
|
|
348
|
+
catch {
|
|
349
|
+
return MISSING_PATH_SIGNATURE;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
async function recordPathStat(target, signatures) {
|
|
353
|
+
const resolved = path.resolve(target);
|
|
354
|
+
try {
|
|
355
|
+
const stat = await fsp.stat(resolved);
|
|
356
|
+
signatures.set(resolved, rustPathAttributeSignature(stat));
|
|
357
|
+
return stat;
|
|
358
|
+
}
|
|
359
|
+
catch {
|
|
360
|
+
signatures.set(resolved, MISSING_PATH_SIGNATURE);
|
|
361
|
+
return null;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
309
364
|
async function loadRustPathAttributeScope(file) {
|
|
310
365
|
const resolved = path.resolve(file);
|
|
311
366
|
let signature;
|
|
@@ -349,6 +404,153 @@ function rustChildModuleDir(parentFile) {
|
|
|
349
404
|
return dir;
|
|
350
405
|
return path.join(dir, stem);
|
|
351
406
|
}
|
|
407
|
+
async function resolveDeclaredConventionalModule(projectRoot, currentModuleDir, name, signatures) {
|
|
408
|
+
for (const candidate of rustModuleCandidates(currentModuleDir, [name])) {
|
|
409
|
+
const resolved = path.resolve(candidate);
|
|
410
|
+
const stat = await recordPathStat(resolved, signatures);
|
|
411
|
+
if (!stat?.isFile())
|
|
412
|
+
continue;
|
|
413
|
+
if (await isExistingAttributedPathInsideProject(projectRoot, resolved, stat))
|
|
414
|
+
return resolved;
|
|
415
|
+
return null;
|
|
416
|
+
}
|
|
417
|
+
return null;
|
|
418
|
+
}
|
|
419
|
+
function addAttributedOwner(ownerSets, target, owner) {
|
|
420
|
+
const targetKey = rustPathIdentity(target);
|
|
421
|
+
let set = ownerSets.get(targetKey);
|
|
422
|
+
if (!set) {
|
|
423
|
+
set = new Map();
|
|
424
|
+
ownerSets.set(targetKey, set);
|
|
425
|
+
}
|
|
426
|
+
const parentFile = path.resolve(owner.parentFile);
|
|
427
|
+
const parentModuleDir = path.resolve(owner.parentModuleDir);
|
|
428
|
+
set.set(`${rustPathIdentity(parentFile)}\0${rustPathIdentity(parentModuleDir)}`, {
|
|
429
|
+
parentFile,
|
|
430
|
+
parentModuleDir,
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
async function rustModuleTreeSignaturesMatch(tree) {
|
|
434
|
+
const entries = [...tree.signatures];
|
|
435
|
+
const actual = await Promise.all(entries.map(([filePath]) => currentPathSignature(filePath)));
|
|
436
|
+
for (let i = 0; i < entries.length; i += 1) {
|
|
437
|
+
if (actual[i] !== entries[i]?.[1])
|
|
438
|
+
return false;
|
|
439
|
+
}
|
|
440
|
+
return true;
|
|
441
|
+
}
|
|
442
|
+
async function buildRustModuleTree(cargoRoot, projectRoot) {
|
|
443
|
+
const signatures = new Map();
|
|
444
|
+
const reachable = new Set();
|
|
445
|
+
const ownerSets = new Map();
|
|
446
|
+
let truncated = false;
|
|
447
|
+
await recordPathStat(path.join(cargoRoot, "Cargo.toml"), signatures);
|
|
448
|
+
for (const relative of ["src", path.join("src", "bin"), "tests", "examples", "benches"]) {
|
|
449
|
+
await recordPathStat(path.join(cargoRoot, relative), signatures);
|
|
450
|
+
}
|
|
451
|
+
const crateRoots = await rustCrateRootFiles(cargoRoot, projectRoot);
|
|
452
|
+
const crateRootSet = new Set(crateRoots.roots.map((file) => rustPathIdentity(file)));
|
|
453
|
+
for (const candidate of crateRoots.probed) {
|
|
454
|
+
await recordPathStat(candidate, signatures);
|
|
455
|
+
}
|
|
456
|
+
const walkFile = async (file, depth) => {
|
|
457
|
+
if (truncated)
|
|
458
|
+
return;
|
|
459
|
+
if (depth > MAX_RUST_MODULE_TREE_DEPTH) {
|
|
460
|
+
truncated = true;
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const resolved = path.resolve(file);
|
|
464
|
+
const identity = rustPathIdentity(resolved);
|
|
465
|
+
if (reachable.has(identity))
|
|
466
|
+
return;
|
|
467
|
+
const stat = await recordPathStat(resolved, signatures);
|
|
468
|
+
if (!(await isExistingAttributedPathInsideProject(projectRoot, resolved, stat)))
|
|
469
|
+
return;
|
|
470
|
+
if (reachable.size >= MAX_RUST_MODULE_TREE_FILES) {
|
|
471
|
+
truncated = true;
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
reachable.add(identity);
|
|
475
|
+
const scope = await loadRustPathAttributeScope(resolved);
|
|
476
|
+
const moduleDir = crateRootSet.has(identity) ? path.dirname(resolved) : rustChildModuleDir(resolved);
|
|
477
|
+
await walkScope(scope, resolved, moduleDir, path.dirname(resolved), depth);
|
|
478
|
+
};
|
|
479
|
+
const walkScope = async (scope, currentFile, currentModuleDir, attributeDirectory, depth) => {
|
|
480
|
+
if (truncated)
|
|
481
|
+
return;
|
|
482
|
+
if (depth > MAX_RUST_MODULE_TREE_DEPTH) {
|
|
483
|
+
truncated = true;
|
|
484
|
+
return;
|
|
485
|
+
}
|
|
486
|
+
for (const { name, pathValue } of scope.declaredModules) {
|
|
487
|
+
if (truncated)
|
|
488
|
+
return;
|
|
489
|
+
let target = null;
|
|
490
|
+
if (pathValue !== undefined) {
|
|
491
|
+
const attributedPath = path.resolve(attributeDirectory, pathValue);
|
|
492
|
+
const attributedStat = await recordPathStat(attributedPath, signatures);
|
|
493
|
+
if (await isExistingAttributedPathInsideProject(projectRoot, attributedPath, attributedStat)) {
|
|
494
|
+
target = path.resolve(attributedPath);
|
|
495
|
+
addAttributedOwner(ownerSets, target, { parentFile: currentFile, parentModuleDir: currentModuleDir });
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
else {
|
|
499
|
+
target = await resolveDeclaredConventionalModule(projectRoot, currentModuleDir, name, signatures);
|
|
500
|
+
}
|
|
501
|
+
if (target)
|
|
502
|
+
await walkFile(target, depth + 1);
|
|
503
|
+
}
|
|
504
|
+
for (const [name, child] of scope.inlineModules) {
|
|
505
|
+
if (truncated)
|
|
506
|
+
return;
|
|
507
|
+
const nextDir = path.resolve(currentModuleDir, child.inlineLocation?.directory ?? name);
|
|
508
|
+
await walkScope(child, currentFile, nextDir, nextDir, depth + 1);
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
for (const crateRoot of crateRoots.roots) {
|
|
512
|
+
await walkFile(crateRoot, 0);
|
|
513
|
+
}
|
|
514
|
+
const owners = new Map();
|
|
515
|
+
for (const [target, set] of ownerSets) {
|
|
516
|
+
owners.set(target, [...set.values()]);
|
|
517
|
+
}
|
|
518
|
+
return { signatures, truncated, reachable, owners, validatedAt: Date.now() };
|
|
519
|
+
}
|
|
520
|
+
async function getRustModuleTree(cargoRoot, projectRoot) {
|
|
521
|
+
const resolvedCargoRoot = path.resolve(cargoRoot);
|
|
522
|
+
const resolvedProjectRoot = path.resolve(projectRoot);
|
|
523
|
+
const key = `${rustPathIdentity(resolvedCargoRoot)}\0${rustPathIdentity(resolvedProjectRoot)}`;
|
|
524
|
+
const cached = lruMapGet(rustModuleTreeCache, key);
|
|
525
|
+
if (cached && Date.now() - cached.validatedAt < RUST_MODULE_TREE_REVALIDATE_INTERVAL_MS) {
|
|
526
|
+
return cached;
|
|
527
|
+
}
|
|
528
|
+
const inflight = rustModuleTreeInflight.get(key);
|
|
529
|
+
if (inflight)
|
|
530
|
+
return await inflight;
|
|
531
|
+
const pending = (async () => {
|
|
532
|
+
try {
|
|
533
|
+
const existing = lruMapGet(rustModuleTreeCache, key);
|
|
534
|
+
if (existing) {
|
|
535
|
+
if (Date.now() - existing.validatedAt < RUST_MODULE_TREE_REVALIDATE_INTERVAL_MS) {
|
|
536
|
+
return existing;
|
|
537
|
+
}
|
|
538
|
+
if (await rustModuleTreeSignaturesMatch(existing)) {
|
|
539
|
+
existing.validatedAt = Date.now();
|
|
540
|
+
return existing;
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const tree = await buildRustModuleTree(resolvedCargoRoot, resolvedProjectRoot);
|
|
544
|
+
lruMapSet(rustModuleTreeCache, key, tree, MAX_RUST_MODULE_TREE_CACHE_ENTRIES);
|
|
545
|
+
return tree;
|
|
546
|
+
}
|
|
547
|
+
finally {
|
|
548
|
+
rustModuleTreeInflight.delete(key);
|
|
549
|
+
}
|
|
550
|
+
})();
|
|
551
|
+
rustModuleTreeInflight.set(key, pending);
|
|
552
|
+
return await pending;
|
|
553
|
+
}
|
|
352
554
|
async function rustDeclaringFileCandidates(fromFile, sourceRoot) {
|
|
353
555
|
const files = [];
|
|
354
556
|
const seen = new Set();
|
|
@@ -424,37 +626,66 @@ async function findAttributedDeclarationParent(projectRoot, declaringFile, targe
|
|
|
424
626
|
const scope = await loadRustPathAttributeScope(declaringFile);
|
|
425
627
|
return walk(scope, path.resolve(declaringFile), rustChildModuleDir(declaringFile), path.dirname(declaringFile));
|
|
426
628
|
}
|
|
427
|
-
async function findPathAttributeParent(projectRoot, fromFile, sourceRoot) {
|
|
629
|
+
async function findPathAttributeParent(projectRoot, fromFile, sourceRoot, cargoRoot) {
|
|
630
|
+
if (cargoRoot) {
|
|
631
|
+
const tree = await getRustModuleTree(cargoRoot, projectRoot);
|
|
632
|
+
if (!tree.truncated) {
|
|
633
|
+
const fromKey = rustPathIdentity(fromFile);
|
|
634
|
+
const owners = tree.owners.get(fromKey) ?? [];
|
|
635
|
+
if (owners.length === 1) {
|
|
636
|
+
const owner = owners[0];
|
|
637
|
+
if (owner)
|
|
638
|
+
return { status: "resolved", parent: owner };
|
|
639
|
+
}
|
|
640
|
+
if (owners.length > 1)
|
|
641
|
+
return { status: "ambiguous" };
|
|
642
|
+
if (tree.reachable.has(fromKey))
|
|
643
|
+
return { status: "unresolved" };
|
|
644
|
+
}
|
|
645
|
+
}
|
|
428
646
|
const candidates = await rustDeclaringFileCandidates(fromFile, sourceRoot);
|
|
429
647
|
for (const candidate of candidates) {
|
|
430
648
|
const found = await findAttributedDeclarationParent(projectRoot, candidate, fromFile);
|
|
431
649
|
if (found)
|
|
432
|
-
return found;
|
|
650
|
+
return { status: "resolved", parent: found };
|
|
433
651
|
}
|
|
434
|
-
return
|
|
652
|
+
return { status: "unresolved" };
|
|
435
653
|
}
|
|
436
|
-
async function rustSuperModuleContext(projectRoot, fromFile, sourceRoot) {
|
|
437
|
-
const attributed = await findPathAttributeParent(projectRoot, fromFile, sourceRoot);
|
|
438
|
-
if (attributed)
|
|
439
|
-
return
|
|
654
|
+
async function rustSuperModuleContext(projectRoot, fromFile, sourceRoot, cargoRoot) {
|
|
655
|
+
const attributed = await findPathAttributeParent(projectRoot, fromFile, sourceRoot, cargoRoot);
|
|
656
|
+
if (attributed.status === "ambiguous")
|
|
657
|
+
return { status: "ambiguous" };
|
|
658
|
+
if (attributed.status === "resolved") {
|
|
659
|
+
return {
|
|
660
|
+
status: "resolved",
|
|
661
|
+
parentFile: attributed.parent.parentFile,
|
|
662
|
+
parentModuleDir: attributed.parent.parentModuleDir,
|
|
663
|
+
};
|
|
664
|
+
}
|
|
440
665
|
const currentDir = path.dirname(fromFile);
|
|
441
666
|
const parentModuleDir = parentRustModuleDir(fromFile, currentDir);
|
|
442
|
-
return {
|
|
667
|
+
return {
|
|
668
|
+
status: "resolved",
|
|
669
|
+
parentFile: await resolveRustModuleParts(parentModuleDir, []),
|
|
670
|
+
parentModuleDir,
|
|
671
|
+
};
|
|
443
672
|
}
|
|
444
|
-
async function declaringFileForSpecifierHead(projectRoot, fromFile, sourceRoot, head) {
|
|
673
|
+
async function declaringFileForSpecifierHead(projectRoot, fromFile, sourceRoot, cargoRoot, head) {
|
|
445
674
|
if (head === "*")
|
|
446
|
-
return null;
|
|
675
|
+
return { status: "resolved", file: null };
|
|
447
676
|
if (head === "crate") {
|
|
448
|
-
return resolveRustModuleParts(sourceRoot, []);
|
|
677
|
+
return { status: "resolved", file: await resolveRustModuleParts(sourceRoot, []) };
|
|
449
678
|
}
|
|
450
679
|
if (head === "self") {
|
|
451
|
-
return path.resolve(fromFile);
|
|
680
|
+
return { status: "resolved", file: path.resolve(fromFile) };
|
|
452
681
|
}
|
|
453
682
|
if (head === "super") {
|
|
454
|
-
const context = await rustSuperModuleContext(projectRoot, fromFile, sourceRoot);
|
|
455
|
-
|
|
683
|
+
const context = await rustSuperModuleContext(projectRoot, fromFile, sourceRoot, cargoRoot);
|
|
684
|
+
if (context.status === "ambiguous")
|
|
685
|
+
return { status: "ambiguous" };
|
|
686
|
+
return { status: "resolved", file: context.parentFile };
|
|
456
687
|
}
|
|
457
|
-
return path.resolve(fromFile);
|
|
688
|
+
return { status: "resolved", file: path.resolve(fromFile) };
|
|
458
689
|
}
|
|
459
690
|
function rustScopeAtDirectory(scope, fromDir, toDir) {
|
|
460
691
|
const relative = path.relative(fromDir, toDir);
|
|
@@ -469,19 +700,24 @@ function rustScopeAtDirectory(scope, fromDir, toDir) {
|
|
|
469
700
|
}
|
|
470
701
|
return current;
|
|
471
702
|
}
|
|
472
|
-
async function resolveAttributedRustModulePath(projectRoot, fromFile, parts, sourceRoot) {
|
|
703
|
+
async function resolveAttributedRustModulePath(projectRoot, fromFile, parts, sourceRoot, cargoRoot) {
|
|
473
704
|
const head = parts[0];
|
|
474
705
|
if (!head)
|
|
475
706
|
return undefined;
|
|
476
707
|
let startFile;
|
|
477
708
|
let startModuleDir;
|
|
478
709
|
if (head === "super") {
|
|
479
|
-
const context = await rustSuperModuleContext(projectRoot, fromFile, sourceRoot);
|
|
710
|
+
const context = await rustSuperModuleContext(projectRoot, fromFile, sourceRoot, cargoRoot);
|
|
711
|
+
if (context.status === "ambiguous")
|
|
712
|
+
return null;
|
|
480
713
|
startFile = context.parentFile;
|
|
481
714
|
startModuleDir = context.parentModuleDir;
|
|
482
715
|
}
|
|
483
716
|
else {
|
|
484
|
-
|
|
717
|
+
const declaring = await declaringFileForSpecifierHead(projectRoot, fromFile, sourceRoot, cargoRoot, head);
|
|
718
|
+
if (declaring.status === "ambiguous")
|
|
719
|
+
return null;
|
|
720
|
+
startFile = declaring.file;
|
|
485
721
|
}
|
|
486
722
|
if (!startFile)
|
|
487
723
|
return undefined;
|
|
@@ -572,7 +808,7 @@ export async function resolveRustImportPath(projectRoot, fromFile, spec, pathAtt
|
|
|
572
808
|
}
|
|
573
809
|
const cargoRoot = await findNearestCargoRoot(fromFile, projectRoot);
|
|
574
810
|
const sourceRoot = crateSourceRoot(cargoRoot, projectRoot);
|
|
575
|
-
const walked = await resolveAttributedRustModulePath(projectRoot, fromFile, parts, sourceRoot);
|
|
811
|
+
const walked = await resolveAttributedRustModulePath(projectRoot, fromFile, parts, sourceRoot, cargoRoot);
|
|
576
812
|
if (walked !== undefined)
|
|
577
813
|
return walked;
|
|
578
814
|
const currentDir = path.dirname(fromFile);
|
|
@@ -587,7 +823,9 @@ export async function resolveRustImportPath(projectRoot, fromFile, spec, pathAtt
|
|
|
587
823
|
return resolveRustModuleParts(currentDir, tail);
|
|
588
824
|
}
|
|
589
825
|
if (head === "super") {
|
|
590
|
-
const context = await rustSuperModuleContext(projectRoot, fromFile, sourceRoot);
|
|
826
|
+
const context = await rustSuperModuleContext(projectRoot, fromFile, sourceRoot, cargoRoot);
|
|
827
|
+
if (context.status === "ambiguous")
|
|
828
|
+
return null;
|
|
591
829
|
if (!tail.length)
|
|
592
830
|
return context.parentFile;
|
|
593
831
|
return resolveRustModuleParts(context.parentModuleDir, tail);
|