about summary refs log tree commit diff
path: root/editors/code/src
diff options
context:
space:
mode:
authorBruno Ortiz <brunortiz11@gmail.com>2023-04-02 21:58:20 -0300
committerBruno Ortiz <brunortiz11@gmail.com>2023-05-02 10:56:09 -0300
commit09e0a00d3648eb4080d16f07c6dae73f7c73c431 (patch)
tree4cbc611accb6cd706ab2692f824a5359c88936ff /editors/code/src
parent1201b156d839ac5b5cc7bca1ea1c1f0cf6fbf6a9 (diff)
downloadrust-09e0a00d3648eb4080d16f07c6dae73f7c73c431.tar.gz
rust-09e0a00d3648eb4080d16f07c6dae73f7c73c431.zip
fetching dependencies from the server
Diffstat (limited to 'editors/code/src')
-rw-r--r--editors/code/src/commands.ts8
-rw-r--r--editors/code/src/ctx.ts48
-rw-r--r--editors/code/src/dependencies_provider.ts77
-rw-r--r--editors/code/src/toolchain.ts75
4 files changed, 56 insertions, 152 deletions
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 70eeab897c9..7fe32754c90 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -272,19 +272,19 @@ export function revealDependency(ctx: CtxInit): Cmd {
         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);
+        const dep = ctx.dependencies?.getDependency(documentPath);
         if (dep) {
-            await ctx.treeView.reveal(dep, { select: true, expand: true });
+            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));
+            } while (!ctx.dependencies?.contains(documentPath));
             parentChain.reverse();
             for (const idx in parentChain) {
-                await ctx.treeView.reveal(parentChain[idx], { select: true, expand: true });
+                await ctx.treeView?.reveal(parentChain[idx], { select: true, expand: true });
             }
         }
     };
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts
index feb39198c22..d62716c26db 100644
--- a/editors/code/src/ctx.ts
+++ b/editors/code/src/ctx.ts
@@ -91,19 +91,25 @@ export class Ctx {
     private commandFactories: Record<string, CommandFactory>;
     private commandDisposables: Disposable[];
     private unlinkedFiles: vscode.Uri[];
-    readonly dependencies: RustDependenciesProvider;
-    readonly treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId>;
+    private _dependencies: RustDependenciesProvider | undefined;
+    private _treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId> | undefined;
 
     get client() {
         return this._client;
     }
 
+    get treeView() {
+        return this._treeView;
+    }
+
+    get dependencies() {
+        return this._dependencies;
+    }
+
     constructor(
         readonly extCtx: vscode.ExtensionContext,
         commandFactories: Record<string, CommandFactory>,
         workspace: Workspace,
-        dependencies: RustDependenciesProvider,
-        treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId>
     ) {
         extCtx.subscriptions.push(this);
         this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left);
@@ -112,9 +118,6 @@ export class Ctx {
         this.commandDisposables = [];
         this.commandFactories = commandFactories;
         this.unlinkedFiles = [];
-        this.dependencies = dependencies;
-        this.treeView = treeView;
-
         this.state = new PersistentState(extCtx.globalState);
         this.config = new Config(extCtx);
 
@@ -123,13 +126,6 @@ export class Ctx {
         this.setServerStatus({
             health: "stopped",
         });
-        vscode.window.onDidChangeActiveTextEditor((e) => {
-            if (e && isRustEditor(e)) {
-                execRevealDependency(e).catch((reason) => {
-                    void vscode.window.showErrorMessage(`Dependency error: ${reason}`);
-                });
-            }
-        });
     }
 
     dispose() {
@@ -267,6 +263,28 @@ export class Ctx {
         }
         await client.start();
         this.updateCommands();
+        this.prepareTreeDependenciesView(client);
+    }
+
+    private prepareTreeDependenciesView(client: lc.LanguageClient) {
+        const ctxInit: CtxInit = {
+            ...this,
+            client: client
+        };
+        const rootPath = vscode.workspace.workspaceFolders![0].uri.fsPath;
+        this._dependencies = new RustDependenciesProvider(rootPath, ctxInit);
+        this._treeView = vscode.window.createTreeView("rustDependencies", {
+            treeDataProvider: this._dependencies,
+            showCollapseAll: true,
+        });
+
+        vscode.window.onDidChangeActiveTextEditor((e) => {
+            if (e && isRustEditor(e)) {
+                execRevealDependency(e).catch((reason) => {
+                    void vscode.window.showErrorMessage(`Dependency error: ${reason}`);
+                });
+            }
+        });
     }
 
     async restart() {
@@ -369,7 +387,7 @@ export class Ctx {
                 statusBar.color = undefined;
                 statusBar.backgroundColor = undefined;
                 statusBar.command = "rust-analyzer.stopServer";
-                this.dependencies.refresh();
+                this.dependencies?.refresh();
                 break;
             case "warning":
                 if (status.message) {
diff --git a/editors/code/src/dependencies_provider.ts b/editors/code/src/dependencies_provider.ts
index 48d51523e86..195f41417dd 100644
--- a/editors/code/src/dependencies_provider.ts
+++ b/editors/code/src/dependencies_provider.ts
@@ -1,23 +1,16 @@
 import * as vscode from "vscode";
 import * as fspath from "path";
 import * as fs from "fs";
-import * as os from "os";
-import { activeToolchain, Cargo, Crate, getRustcVersion } from "./toolchain";
-import { Ctx } from "./ctx";
-import { setFlagsFromString } from "v8";
+import { CtxInit } from "./ctx";
 import * as ra from "./lsp_ext";
-
-const debugOutput = vscode.window.createOutputChannel("Debug");
+import { FetchDependencyGraphResult } from "./lsp_ext";
 
 export class RustDependenciesProvider
-    implements vscode.TreeDataProvider<Dependency | DependencyFile>
-{
-    cargo: Cargo;
+    implements vscode.TreeDataProvider<Dependency | DependencyFile> {
     dependenciesMap: { [id: string]: Dependency | DependencyFile };
-    ctx: Ctx;
+    ctx: CtxInit;
 
-    constructor(private readonly workspaceRoot: string, ctx: Ctx) {
-        this.cargo = new Cargo(this.workspaceRoot || ".", debugOutput);
+    constructor(private readonly workspaceRoot: string, ctx: CtxInit) {
         this.dependenciesMap = {};
         this.ctx = ctx;
     }
@@ -62,7 +55,6 @@ export class RustDependenciesProvider
                 void vscode.window.showInformationMessage("No dependency in empty workspace");
                 return Promise.resolve([]);
             }
-
             if (element) {
                 const files = fs.readdirSync(element.dependencyPath).map((fileName) => {
                     const filePath = fspath.join(element.dependencyPath, fileName);
@@ -81,59 +73,26 @@ export class RustDependenciesProvider
     }
 
     private async getRootDependencies(): Promise<Dependency[]> {
-        const crates = await this.ctx.client.sendRequest(ra.fetchDependencyGraph, {});
-
-        const registryDir = fspath.join(os.homedir(), ".cargo", "registry", "src");
-        const basePath = fspath.join(registryDir, fs.readdirSync(registryDir)[0]);
-        const deps = await this.getDepsInCartoTree(basePath);
-        const stdlib = await this.getStdLib();
-        this.dependenciesMap[stdlib.dependencyPath.toLowerCase()] = stdlib;
-        return [stdlib].concat(deps);
-    }
-
-    private async getStdLib(): Promise<Dependency> {
-        const toolchain = await activeToolchain();
-        const rustVersion = await getRustcVersion(os.homedir());
-        const stdlibPath = fspath.join(
-            os.homedir(),
-            ".rustup",
-            "toolchains",
-            toolchain,
-            "lib",
-            "rustlib",
-            "src",
-            "rust",
-            "library"
-        );
-        const stdlib = new Dependency(
-            "stdlib",
-            rustVersion,
-            stdlibPath,
-            vscode.TreeItemCollapsibleState.Collapsed
-        );
-
-        return stdlib;
-    }
-
-    private async getDepsInCartoTree(basePath: string): Promise<Dependency[]> {
-        const crates: Crate[] = await this.cargo.crates();
-        const toDep = (moduleName: string, version: string): Dependency => {
-            const cratePath = fspath.join(basePath, `${moduleName}-${version}`);
-            return new Dependency(
-                moduleName,
-                version,
-                cratePath,
-                vscode.TreeItemCollapsibleState.Collapsed
-            );
-        };
+        const dependenciesResult: FetchDependencyGraphResult = await this.ctx.client.sendRequest(ra.fetchDependencyGraph, {});
+        const crates = dependenciesResult.crates;
 
         const deps = crates.map((crate) => {
-            const dep = toDep(crate.name, crate.version);
+            const dep = this.toDep(crate.name, crate.version, crate.path);
             this.dependenciesMap[dep.dependencyPath.toLowerCase()] = dep;
             return dep;
         });
         return deps;
     }
+
+    private toDep(moduleName: string, version: string, path: string): Dependency {
+        // const cratePath = fspath.join(basePath, `${moduleName}-${version}`);
+        return new Dependency(
+            moduleName,
+            version,
+            path,
+            vscode.TreeItemCollapsibleState.Collapsed
+        );
+    }
 }
 
 export class Dependency extends vscode.TreeItem {
diff --git a/editors/code/src/toolchain.ts b/editors/code/src/toolchain.ts
index c068cfc3118..771f6bcba45 100644
--- a/editors/code/src/toolchain.ts
+++ b/editors/code/src/toolchain.ts
@@ -5,14 +5,8 @@ import * as readline from "readline";
 import * as vscode from "vscode";
 import { execute, log, memoizeAsync } from "./util";
 
-const TREE_LINE_PATTERN = new RegExp(/(.+)\sv(\d+\.\d+\.\d+)(?:\s\((.+)\))?/);
 const TOOLCHAIN_PATTERN = new RegExp(/(.*)\s\(.*\)/);
 
-export interface Crate {
-    name: string;
-    version: string;
-}
-
 interface CompilationArtifact {
     fileName: string;
     name: string;
@@ -30,7 +24,7 @@ export class Cargo {
         readonly rootFolder: string,
         readonly output: vscode.OutputChannel,
         readonly env: Record<string, string>
-    ) {}
+    ) { }
 
     // Made public for testing purposes
     static artifactSpec(args: readonly string[]): ArtifactSpec {
@@ -104,40 +98,6 @@ export class Cargo {
         return artifacts[0].fileName;
     }
 
-    async crates(): Promise<Crate[]> {
-        const pathToCargo = await cargoPath();
-        return await new Promise((resolve, reject) => {
-            const crates: Crate[] = [];
-
-            const cargo = cp.spawn(pathToCargo, ["tree", "--prefix", "none"], {
-                stdio: ["ignore", "pipe", "pipe"],
-                cwd: this.rootFolder,
-            });
-            const rl = readline.createInterface({ input: cargo.stdout });
-            rl.on("line", (line) => {
-                const match = line.match(TREE_LINE_PATTERN);
-                if (match) {
-                    const name = match[1];
-                    const version = match[2];
-                    const extraInfo = match[3];
-                    // ignore duplicates '(*)' and path dependencies
-                    if (this.shouldIgnore(extraInfo)) {
-                        return;
-                    }
-                    crates.push({ name, version });
-                }
-            });
-            cargo.on("exit", (exitCode, _) => {
-                if (exitCode === 0) resolve(crates);
-                else reject(new Error(`exit code: ${exitCode}.`));
-            });
-        });
-    }
-
-    private shouldIgnore(extraInfo: string): boolean {
-        return extraInfo !== undefined && (extraInfo === "*" || path.isAbsolute(extraInfo));
-    }
-
     private async runCargo(
         cargoArgs: string[],
         onStdoutJson: (obj: any) => void,
@@ -169,29 +129,6 @@ export class Cargo {
     }
 }
 
-export async function activeToolchain(): Promise<string> {
-    const pathToRustup = await rustupPath();
-    return await new Promise((resolve, reject) => {
-        const execution = cp.spawn(pathToRustup, ["show", "active-toolchain"], {
-            stdio: ["ignore", "pipe", "pipe"],
-            cwd: os.homedir(),
-        });
-        const rl = readline.createInterface({ input: execution.stdout });
-
-        let currToolchain: string | undefined = undefined;
-        rl.on("line", (line) => {
-            const match = line.match(TOOLCHAIN_PATTERN);
-            if (match) {
-                currToolchain = match[1];
-            }
-        });
-        execution.on("exit", (exitCode, _) => {
-            if (exitCode === 0 && currToolchain) resolve(currToolchain);
-            else reject(new Error(`exit code: ${exitCode}.`));
-        });
-    });
-}
-
 /** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/
 export async function getSysroot(dir: string): Promise<string> {
     const rustcPath = await getPathForExecutable("rustc");
@@ -210,16 +147,6 @@ export async function getRustcId(dir: string): Promise<string> {
     return rx.exec(data)![1];
 }
 
-export async function getRustcVersion(dir: string): Promise<string> {
-    const rustcPath = await getPathForExecutable("rustc");
-
-    // do not memoize the result because the toolchain may change between runs
-    const data = await execute(`${rustcPath} -V`, { cwd: dir });
-    const rx = /(\d\.\d+\.\d+)/;
-
-    return rx.exec(data)![1];
-}
-
 /** Mirrors `toolchain::cargo()` implementation */
 export function cargoPath(): Promise<string> {
     return getPathForExecutable("cargo");