Skip to content

Commit 8e687f7

Browse files
committed
improving code to work with multi-workspaces
1 parent 1b8288f commit 8e687f7

File tree

6 files changed

+89
-23
lines changed

6 files changed

+89
-23
lines changed

crates/ide/src/fetch_crates.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use ide_db::{
22
base_db::{CrateOrigin, SourceDatabase, SourceDatabaseExt},
3-
RootDatabase,
3+
FxIndexSet, RootDatabase,
44
};
55

6-
#[derive(Debug)]
6+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
77
pub struct CrateInfo {
88
pub name: String,
99
pub version: String,
@@ -16,7 +16,7 @@ pub struct CrateInfo {
1616
//
1717
// |===
1818
// image::https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png[]
19-
pub(crate) fn fetch_crates(db: &RootDatabase) -> Vec<CrateInfo> {
19+
pub(crate) fn fetch_crates(db: &RootDatabase) -> FxIndexSet<CrateInfo> {
2020
let crate_graph = db.crate_graph();
2121
crate_graph
2222
.iter()

crates/ide/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ use ide_db::{
7070
salsa::{self, ParallelDatabase},
7171
CrateOrigin, Env, FileLoader, FileSet, SourceDatabase, VfsPath,
7272
},
73-
symbol_index, FxHashMap, LineIndexDatabase,
73+
symbol_index, FxHashMap, FxIndexSet, LineIndexDatabase,
7474
};
7575
use syntax::SourceFile;
7676

@@ -333,7 +333,7 @@ impl Analysis {
333333
self.with_db(|db| view_crate_graph::view_crate_graph(db, full))
334334
}
335335

336-
pub fn fetch_crates(&self) -> Cancellable<Vec<CrateInfo>> {
336+
pub fn fetch_crates(&self) -> Cancellable<FxIndexSet<CrateInfo>> {
337337
self.with_db(|db| fetch_crates::fetch_crates(db))
338338
}
339339

editors/code/src/commands.ts

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@ import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
88
import { spawnSync } from "child_process";
99
import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
1010
import { AstInspector } from "./ast_inspector";
11-
import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor, RustEditor } from "./util";
11+
import {
12+
isRustDocument,
13+
isCargoTomlDocument,
14+
sleep,
15+
isRustEditor,
16+
RustEditor,
17+
RustDocument,
18+
closeDocument,
19+
} from "./util";
1220
import { startDebugSession, makeDebugConfig } from "./debug";
1321
import { LanguageClient } from "vscode-languageclient/node";
1422
import { LINKED_COMMANDS } from "./client";
@@ -269,27 +277,63 @@ export function openCargoToml(ctx: CtxInit): Cmd {
269277

270278
export function revealDependency(ctx: CtxInit): Cmd {
271279
return async (editor: RustEditor) => {
272-
const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
273280
const documentPath = editor.document.uri.fsPath;
274-
if (documentPath.startsWith(rootPath)) return;
275281
const dep = ctx.dependencies?.getDependency(documentPath);
276282
if (dep) {
277283
await ctx.treeView?.reveal(dep, { select: true, expand: true });
278284
} else {
279-
let documentPath = editor.document.uri.fsPath;
280-
const parentChain: DependencyId[] = [{ id: documentPath.toLowerCase() }];
281-
do {
282-
documentPath = path.dirname(documentPath);
283-
parentChain.push({ id: documentPath.toLowerCase() });
284-
} while (!ctx.dependencies?.contains(documentPath));
285-
parentChain.reverse();
286-
for (const idx in parentChain) {
287-
await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
288-
}
285+
await revealParentChain(editor.document, ctx);
289286
}
290287
};
291288
}
292289

290+
/**
291+
* This function calculates the parent chain of a given file until it reaches it crate root contained in ctx.dependencies.
292+
* This is need because the TreeView is Lazy, so at first it only has the root dependencies: For example if we have the following crates:
293+
* - core
294+
* - alloc
295+
* - std
296+
*
297+
* if I want to reveal alloc/src/str.rs, I have to:
298+
299+
* 1. reveal every children of alloc
300+
* - core
301+
* - alloc\
302+
* &emsp;|-beches\
303+
* &emsp;|-src\
304+
* &emsp;|- ...
305+
* - std
306+
* 2. reveal every children of src:
307+
* core
308+
* alloc\
309+
* &emsp;|-beches\
310+
* &emsp;|-src\
311+
* &emsp;&emsp;|- lib.rs\
312+
* &emsp;&emsp;|- str.rs <------- FOUND IT!\
313+
* &emsp;&emsp;|- ...\
314+
* &emsp;|- ...\
315+
* std
316+
*/
317+
async function revealParentChain(document: RustDocument, ctx: CtxInit) {
318+
let documentPath = document.uri.fsPath;
319+
const maxDepth = documentPath.split(path.sep).length - 1;
320+
const parentChain: DependencyId[] = [{ id: documentPath.toLowerCase() }];
321+
do {
322+
documentPath = path.dirname(documentPath);
323+
parentChain.push({ id: documentPath.toLowerCase() });
324+
if (parentChain.length >= maxDepth) {
325+
// this is an odd case that can happen when we change a crate version but we'd still have
326+
// a open file referencing the old version
327+
await closeDocument(document);
328+
return;
329+
}
330+
} while (!ctx.dependencies?.contains(documentPath));
331+
parentChain.reverse();
332+
for (const idx in parentChain) {
333+
await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
334+
}
335+
}
336+
293337
export async function execRevealDependency(e: RustEditor): Promise<void> {
294338
await vscode.commands.executeCommand("rust-analyzer.revealDependency", e);
295339
}

editors/code/src/ctx.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import { Config, prepareVSCodeConfig } from "./config";
77
import { createClient } from "./client";
88
import {
99
executeDiscoverProject,
10+
isDocumentInWorkspace,
1011
isRustDocument,
1112
isRustEditor,
1213
LazyOutputChannel,
@@ -277,15 +278,16 @@ export class Ctx {
277278
...this,
278279
client: client,
279280
};
280-
const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
281-
this._dependencies = new RustDependenciesProvider(rootPath, ctxInit);
281+
this._dependencies = new RustDependenciesProvider(ctxInit);
282282
this._treeView = vscode.window.createTreeView("rustDependencies", {
283283
treeDataProvider: this._dependencies,
284284
showCollapseAll: true,
285285
});
286286

287+
this.pushExtCleanup(this._treeView);
287288
vscode.window.onDidChangeActiveTextEditor((e) => {
288-
if (e && isRustEditor(e)) {
289+
// we should skip documents that belong to the current workspace
290+
if (e && isRustEditor(e) && !isDocumentInWorkspace(e.document)) {
289291
execRevealDependency(e).catch((reason) => {
290292
void vscode.window.showErrorMessage(`Dependency error: ${reason}`);
291293
});

editors/code/src/dependencies_provider.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ export class RustDependenciesProvider
1515
dependenciesMap: { [id: string]: Dependency | DependencyFile };
1616
ctx: CtxInit;
1717

18-
constructor(private readonly workspaceRoot: string,ctx: CtxInit) {
18+
constructor(ctx: CtxInit) {
1919
this.dependenciesMap = {};
2020
this.ctx = ctx;
2121
}
@@ -37,6 +37,7 @@ export class RustDependenciesProvider
3737
}
3838

3939
refresh(): void {
40+
this.dependenciesMap = {};
4041
this._onDidChangeTreeData.fire();
4142
}
4243

@@ -56,7 +57,7 @@ export class RustDependenciesProvider
5657
element?: Dependency | DependencyFile
5758
): vscode.ProviderResult<Dependency[] | DependencyFile[]> {
5859
return new Promise((resolve, _reject) => {
59-
if (!this.workspaceRoot) {
60+
if (!vscode.workspace.workspaceFolders) {
6061
void vscode.window.showInformationMessage("No dependency in empty workspace");
6162
return Promise.resolve([]);
6263
}
@@ -108,6 +109,7 @@ export class Dependency extends vscode.TreeItem {
108109
public readonly collapsibleState: vscode.TreeItemCollapsibleState
109110
) {
110111
super(label, collapsibleState);
112+
this.id = this.dependencyPath.toLowerCase();
111113
this.tooltip = `${this.label}-${this.version}`;
112114
this.description = this.version;
113115
this.resourceUri = vscode.Uri.file(dependencyPath);

editors/code/src/util.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,24 @@ export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor {
112112
return isRustDocument(editor.document);
113113
}
114114

115+
export function isDocumentInWorkspace(document: RustDocument): boolean {
116+
const workspaceFolders = vscode.workspace.workspaceFolders;
117+
if (!workspaceFolders) {
118+
return false;
119+
}
120+
for (const folder of workspaceFolders) {
121+
if (document.uri.fsPath.startsWith(folder.uri.fsPath)) {
122+
return true;
123+
}
124+
}
125+
return false;
126+
}
127+
128+
export async function closeDocument(document: RustDocument) {
129+
await vscode.window.showTextDocument(document, { preview: true, preserveFocus: false });
130+
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
131+
}
132+
115133
export function isValidExecutable(path: string): boolean {
116134
log.debug("Checking availability of a binary at", path);
117135

0 commit comments

Comments
 (0)