Creating rust dependencies tree view

This commit is contained in:
bruno-ortiz 2022-02-25 21:37:55 -03:00 committed by Bruno Ortiz
parent 09e0a00d36
commit d01fc6405b
4 changed files with 115 additions and 6 deletions

View file

@ -285,6 +285,14 @@
"title": "Clear flycheck diagnostics", "title": "Clear flycheck diagnostics",
"category": "rust-analyzer" "category": "rust-analyzer"
}, },
{
"command": "rust-analyzer.revealDependency",
"title": "Reveal File"
},
{
"command": "rust-analyzer.openFile",
"title": "Open File"
},
{ {
"command": "rust-analyzer.revealDependency", "command": "rust-analyzer.revealDependency",
"title": "Reveal File" "title": "Reveal File"
@ -1975,4 +1983,4 @@
} }
] ]
} }
} }

View file

@ -8,7 +8,7 @@ import { applySnippetWorkspaceEdit, applySnippetTextEdits } from "./snippets";
import { spawnSync } from "child_process"; import { spawnSync } from "child_process";
import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run"; import { RunnableQuickPick, selectRunnable, createTask, createArgs } from "./run";
import { AstInspector } from "./ast_inspector"; import { AstInspector } from "./ast_inspector";
import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor, RustEditor } from "./util"; import { isRustDocument, isCargoTomlDocument, sleep, isRustEditor, RustEditor } from './util';
import { startDebugSession, makeDebugConfig } from "./debug"; import { startDebugSession, makeDebugConfig } from "./debug";
import { LanguageClient } from "vscode-languageclient/node"; import { LanguageClient } from "vscode-languageclient/node";
import { LINKED_COMMANDS } from "./client"; import { LINKED_COMMANDS } from "./client";

View file

@ -3,8 +3,8 @@ import * as lc from "vscode-languageclient/node";
import * as ra from "./lsp_ext"; import * as ra from "./lsp_ext";
import * as path from "path"; import * as path from "path";
import {Config, prepareVSCodeConfig} from "./config"; import {Config, prepareVSCodeConfig} from './config';
import {createClient} from "./client"; import {createClient} from './client';
import { import {
executeDiscoverProject, executeDiscoverProject,
isRustDocument, isRustDocument,
@ -12,8 +12,10 @@ import {
LazyOutputChannel, LazyOutputChannel,
log, log,
RustEditor, RustEditor,
} from "./util"; } from './util';
import {ServerStatusParams} from "./lsp_ext"; import {ServerStatusParams} from './lsp_ext';
import { Dependency, DependencyFile, RustDependenciesProvider, DependencyId } from './dependencies_provider';
import { execRevealDependency } from './commands';
import { import {
Dependency, Dependency,
DependencyFile, DependencyFile,

View file

@ -98,6 +98,43 @@ export class Cargo {
return artifacts[0].fileName; 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( private async runCargo(
cargoArgs: string[], cargoArgs: string[],
onStdoutJson: (obj: any) => void, onStdoutJson: (obj: any) => void,
@ -129,6 +166,58 @@ 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}.`));
});
});
}
export async function rustVersion(): 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 === 1 && currToolchain)
resolve(currToolchain);
else
reject(new Error(`exit code: ${exitCode}.`));
});
});
}
/** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/ /** Mirrors `project_model::sysroot::discover_sysroot_dir()` implementation*/
export async function getSysroot(dir: string): Promise<string> { export async function getSysroot(dir: string): Promise<string> {
const rustcPath = await getPathForExecutable("rustc"); const rustcPath = await getPathForExecutable("rustc");
@ -147,6 +236,16 @@ export async function getRustcId(dir: string): Promise<string> {
return rx.exec(data)![1]; 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 */ /** Mirrors `toolchain::cargo()` implementation */
export function cargoPath(): Promise<string> { export function cargoPath(): Promise<string> {
return getPathForExecutable("cargo"); return getPathForExecutable("cargo");