improving code to work with multi-workspaces
This commit is contained in:
parent
1b8288ff96
commit
8e687f7afb
@ -1,9 +1,9 @@
|
||||
use ide_db::{
|
||||
base_db::{CrateOrigin, SourceDatabase, SourceDatabaseExt},
|
||||
RootDatabase,
|
||||
FxIndexSet, RootDatabase,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct CrateInfo {
|
||||
pub name: String,
|
||||
pub version: String,
|
||||
@ -16,7 +16,7 @@ pub struct CrateInfo {
|
||||
//
|
||||
// |===
|
||||
// image::https://user-images.githubusercontent.com/5748995/229394139-2625beab-f4c9-484b-84ed-ad5dee0b1e1a.png[]
|
||||
pub(crate) fn fetch_crates(db: &RootDatabase) -> Vec<CrateInfo> {
|
||||
pub(crate) fn fetch_crates(db: &RootDatabase) -> FxIndexSet<CrateInfo> {
|
||||
let crate_graph = db.crate_graph();
|
||||
crate_graph
|
||||
.iter()
|
||||
|
@ -70,7 +70,7 @@ use ide_db::{
|
||||
salsa::{self, ParallelDatabase},
|
||||
CrateOrigin, Env, FileLoader, FileSet, SourceDatabase, VfsPath,
|
||||
},
|
||||
symbol_index, FxHashMap, LineIndexDatabase,
|
||||
symbol_index, FxHashMap, FxIndexSet, LineIndexDatabase,
|
||||
};
|
||||
use syntax::SourceFile;
|
||||
|
||||
@ -333,7 +333,7 @@ impl Analysis {
|
||||
self.with_db(|db| view_crate_graph::view_crate_graph(db, full))
|
||||
}
|
||||
|
||||
pub fn fetch_crates(&self) -> Cancellable<Vec<CrateInfo>> {
|
||||
pub fn fetch_crates(&self) -> Cancellable<FxIndexSet<CrateInfo>> {
|
||||
self.with_db(|db| fetch_crates::fetch_crates(db))
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,15 @@ import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
|
||||
import { spawnSync } from "child_process";
|
||||
import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
|
||||
import { AstInspector } from "./ast_inspector";
|
||||
import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor, RustEditor } from "./util";
|
||||
import {
|
||||
isRustDocument,
|
||||
isCargoTomlDocument,
|
||||
sleep,
|
||||
isRustEditor,
|
||||
RustEditor,
|
||||
RustDocument,
|
||||
closeDocument,
|
||||
} from "./util";
|
||||
import { startDebugSession, makeDebugConfig } from "./debug";
|
||||
import { LanguageClient } from "vscode-languageclient/node";
|
||||
import { LINKED_COMMANDS } from "./client";
|
||||
@ -269,27 +277,63 @@ export function openCargoToml(ctx: CtxInit): Cmd {
|
||||
|
||||
export function revealDependency(ctx: CtxInit): Cmd {
|
||||
return async (editor: RustEditor) => {
|
||||
const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
|
||||
const documentPath = editor.document.uri.fsPath;
|
||||
if (documentPath.startsWith(rootPath)) return;
|
||||
const dep = ctx.dependencies?.getDependency(documentPath);
|
||||
if (dep) {
|
||||
await ctx.treeView?.reveal(dep, { select: true, expand: true });
|
||||
} else {
|
||||
let documentPath = editor.document.uri.fsPath;
|
||||
const parentChain: DependencyId[] = [{ id: documentPath.toLowerCase() }];
|
||||
do {
|
||||
documentPath = path.dirname(documentPath);
|
||||
parentChain.push({ id: documentPath.toLowerCase() });
|
||||
} while (!ctx.dependencies?.contains(documentPath));
|
||||
parentChain.reverse();
|
||||
for (const idx in parentChain) {
|
||||
await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
|
||||
}
|
||||
await revealParentChain(editor.document, ctx);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* This function calculates the parent chain of a given file until it reaches it crate root contained in ctx.dependencies.
|
||||
* 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:
|
||||
* - core
|
||||
* - alloc
|
||||
* - std
|
||||
*
|
||||
* if I want to reveal alloc/src/str.rs, I have to:
|
||||
|
||||
* 1. reveal every children of alloc
|
||||
* - core
|
||||
* - alloc\
|
||||
*  |-beches\
|
||||
*  |-src\
|
||||
*  |- ...
|
||||
* - std
|
||||
* 2. reveal every children of src:
|
||||
* core
|
||||
* alloc\
|
||||
*  |-beches\
|
||||
*  |-src\
|
||||
*   |- lib.rs\
|
||||
*   |- str.rs <------- FOUND IT!\
|
||||
*   |- ...\
|
||||
*  |- ...\
|
||||
* std
|
||||
*/
|
||||
async function revealParentChain(document: RustDocument, ctx: CtxInit) {
|
||||
let documentPath = document.uri.fsPath;
|
||||
const maxDepth = documentPath.split(path.sep).length - 1;
|
||||
const parentChain: DependencyId[] = [{ id: documentPath.toLowerCase() }];
|
||||
do {
|
||||
documentPath = path.dirname(documentPath);
|
||||
parentChain.push({ id: documentPath.toLowerCase() });
|
||||
if (parentChain.length >= maxDepth) {
|
||||
// this is an odd case that can happen when we change a crate version but we'd still have
|
||||
// a open file referencing the old version
|
||||
await closeDocument(document);
|
||||
return;
|
||||
}
|
||||
} while (!ctx.dependencies?.contains(documentPath));
|
||||
parentChain.reverse();
|
||||
for (const idx in parentChain) {
|
||||
await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
|
||||
}
|
||||
}
|
||||
|
||||
export async function execRevealDependency(e: RustEditor): Promise<void> {
|
||||
await vscode.commands.executeCommand("rust-analyzer.revealDependency", e);
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { Config, prepareVSCodeConfig } from "./config";
|
||||
import { createClient } from "./client";
|
||||
import {
|
||||
executeDiscoverProject,
|
||||
isDocumentInWorkspace,
|
||||
isRustDocument,
|
||||
isRustEditor,
|
||||
LazyOutputChannel,
|
||||
@ -277,15 +278,16 @@ export class Ctx {
|
||||
...this,
|
||||
client: client,
|
||||
};
|
||||
const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
|
||||
this._dependencies = new RustDependenciesProvider(rootPath, ctxInit);
|
||||
this._dependencies = new RustDependenciesProvider(ctxInit);
|
||||
this._treeView = vscode.window.createTreeView("rustDependencies", {
|
||||
treeDataProvider: this._dependencies,
|
||||
showCollapseAll: true,
|
||||
});
|
||||
|
||||
this.pushExtCleanup(this._treeView);
|
||||
vscode.window.onDidChangeActiveTextEditor((e) => {
|
||||
if (e && isRustEditor(e)) {
|
||||
// we should skip documents that belong to the current workspace
|
||||
if (e && isRustEditor(e) && !isDocumentInWorkspace(e.document)) {
|
||||
execRevealDependency(e).catch((reason) => {
|
||||
void vscode.window.showErrorMessage(`Dependency error: ${reason}`);
|
||||
});
|
||||
|
@ -15,7 +15,7 @@ export class RustDependenciesProvider
|
||||
dependenciesMap: { [id: string]: Dependency | DependencyFile };
|
||||
ctx: CtxInit;
|
||||
|
||||
constructor(private readonly workspaceRoot: string,ctx: CtxInit) {
|
||||
constructor(ctx: CtxInit) {
|
||||
this.dependenciesMap = {};
|
||||
this.ctx = ctx;
|
||||
}
|
||||
@ -37,6 +37,7 @@ export class RustDependenciesProvider
|
||||
}
|
||||
|
||||
refresh(): void {
|
||||
this.dependenciesMap = {};
|
||||
this._onDidChangeTreeData.fire();
|
||||
}
|
||||
|
||||
@ -56,7 +57,7 @@ export class RustDependenciesProvider
|
||||
element?: Dependency | DependencyFile
|
||||
): vscode.ProviderResult<Dependency[] | DependencyFile[]> {
|
||||
return new Promise((resolve, _reject) => {
|
||||
if (!this.workspaceRoot) {
|
||||
if (!vscode.workspace.workspaceFolders) {
|
||||
void vscode.window.showInformationMessage("No dependency in empty workspace");
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
@ -108,6 +109,7 @@ export class Dependency extends vscode.TreeItem {
|
||||
public readonly collapsibleState: vscode.TreeItemCollapsibleState
|
||||
) {
|
||||
super(label, collapsibleState);
|
||||
this.id = this.dependencyPath.toLowerCase();
|
||||
this.tooltip = `${this.label}-${this.version}`;
|
||||
this.description = this.version;
|
||||
this.resourceUri = vscode.Uri.file(dependencyPath);
|
||||
|
@ -112,6 +112,24 @@ export function isRustEditor(editor: vscode.TextEditor): editor is RustEditor {
|
||||
return isRustDocument(editor.document);
|
||||
}
|
||||
|
||||
export function isDocumentInWorkspace(document: RustDocument): boolean {
|
||||
const workspaceFolders = vscode.workspace.workspaceFolders;
|
||||
if (!workspaceFolders) {
|
||||
return false;
|
||||
}
|
||||
for (const folder of workspaceFolders) {
|
||||
if (document.uri.fsPath.startsWith(folder.uri.fsPath)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export async function closeDocument(document: RustDocument) {
|
||||
await vscode.window.showTextDocument(document, { preview: true, preserveFocus: false });
|
||||
await vscode.commands.executeCommand("workbench.action.closeActiveEditor");
|
||||
}
|
||||
|
||||
export function isValidExecutable(path: string): boolean {
|
||||
log.debug("Checking availability of a binary at", path);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user