diff options
| author | David Barsky <me@davidbarsky.com> | 2023-03-09 15:06:26 -0500 |
|---|---|---|
| committer | David Barsky <me@davidbarsky.com> | 2023-03-13 13:30:18 -0400 |
| commit | 8af3d6367ecead0abf80e697176f697d97c25215 (patch) | |
| tree | 54a28c70aadc17ddc93991fb4344a516ae6cba29 /editors/code/src/ctx.ts | |
| parent | 95497533524537b1cc7a2870ce94b0b14503be8b (diff) | |
| download | rust-8af3d6367ecead0abf80e697176f697d97c25215.tar.gz rust-8af3d6367ecead0abf80e697176f697d97c25215.zip | |
This commit add Cargo-style project discovery for Buck and Bazel users.
This feature requires the user to add a command that generates a
`rust-project.json` from a set of files. Project discovery can be invoked
in two ways:
1. At extension activation time, which includes the generated
`rust-project.json` as part of the linkedProjects argument in
InitializeParams
2. Through a new command titled "Add current file to workspace", which
makes use of a new, rust-analyzer specific LSP request that adds
the workspace without erasing any existing workspaces.
I think that the command-running functionality _could_ merit being
placed into its own extension (and expose it via extension contribution
points), if only provide build-system idiomatic progress reporting and
status handling, but I haven't (yet) made an extension that does this.
Diffstat (limited to 'editors/code/src/ctx.ts')
| -rw-r--r-- | editors/code/src/ctx.ts | 42 |
1 files changed, 31 insertions, 11 deletions
diff --git a/editors/code/src/ctx.ts b/editors/code/src/ctx.ts index 1708d47cee7..ba2d4e97af1 100644 --- a/editors/code/src/ctx.ts +++ b/editors/code/src/ctx.ts @@ -4,10 +4,11 @@ import * as ra from "./lsp_ext"; import { Config, substituteVSCodeVariables } from "./config"; import { createClient } from "./client"; -import { isRustDocument, isRustEditor, LazyOutputChannel, log, RustEditor } from "./util"; +import { executeDiscoverProject, isRustDocument, isRustEditor, LazyOutputChannel, log, RustEditor } from "./util"; import { ServerStatusParams } from "./lsp_ext"; import { PersistentState } from "./persistent_state"; import { bootstrap } from "./bootstrap"; +import { ExecOptions } from "child_process"; // We only support local folders, not eg. Live Share (`vlsl:` scheme), so don't activate if // only those are in use. We use "Empty" to represent these scenarios @@ -16,12 +17,12 @@ import { bootstrap } from "./bootstrap"; export type Workspace = | { kind: "Empty" } | { - kind: "Workspace Folder"; - } + kind: "Workspace Folder"; + } | { - kind: "Detached Files"; - files: vscode.TextDocument[]; - }; + kind: "Detached Files"; + files: vscode.TextDocument[]; + }; export function fetchWorkspace(): Workspace { const folders = (vscode.workspace.workspaceFolders || []).filter( @@ -35,12 +36,19 @@ export function fetchWorkspace(): Workspace { ? rustDocuments.length === 0 ? { kind: "Empty" } : { - kind: "Detached Files", - files: rustDocuments, - } + kind: "Detached Files", + files: rustDocuments, + } : { kind: "Workspace Folder" }; } +export async function discoverWorkspace(files: readonly vscode.TextDocument[], command: string[], options: ExecOptions): Promise<JsonProject> { + const paths = files.map((f) => f.uri.fsPath).join(" "); + const joinedCommand = command.join(" "); + const data = await executeDiscoverProject(`${joinedCommand} -- ${paths}`, options); + return JSON.parse(data) as JsonProject; +} + export type CommandFactory = { enabled: (ctx: CtxInit) => Cmd; disabled?: (ctx: Ctx) => Cmd; @@ -63,6 +71,7 @@ export class Ctx { private state: PersistentState; private commandFactories: Record<string, CommandFactory>; private commandDisposables: Disposable[]; + private discoveredWorkspaces: JsonProject[] | undefined; get client() { return this._client; @@ -71,7 +80,7 @@ export class Ctx { constructor( readonly extCtx: vscode.ExtensionContext, commandFactories: Record<string, CommandFactory>, - workspace: Workspace + workspace: Workspace, ) { extCtx.subscriptions.push(this); this.statusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left); @@ -169,7 +178,18 @@ export class Ctx { }; } - const initializationOptions = substituteVSCodeVariables(rawInitializationOptions); + const discoverProjectCommand = this.config.discoverProjectCommand; + if (discoverProjectCommand) { + let workspaces: JsonProject[] = await Promise.all(vscode.workspace.workspaceFolders!.map(async (folder): Promise<JsonProject> => { + return discoverWorkspace(vscode.workspace.textDocuments, discoverProjectCommand, { cwd: folder.uri.fsPath }); + })); + + this.discoveredWorkspaces = workspaces; + } + + let initializationOptions = substituteVSCodeVariables(rawInitializationOptions); + // this appears to be load-bearing, for better or worse. + await initializationOptions.update('linkedProjects', this.discoveredWorkspaces) this._client = await createClient( this.traceOutputChannel, |
