From 79d53557cd0941d97a93d2a937949850b1f86c39 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Fri, 12 Jan 2024 13:01:37 -0300 Subject: [PATCH] Fallback to guessing the active workspace if none is found based on URI (#976) * Fallback to guessing the active workspace if none is found based on URI * Reduce workspace dependency for launching debugger --- src/debugger.ts | 31 ++++++++++++++----------------- src/rubyLsp.ts | 24 +++++++++++++++++++++++- 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/src/debugger.ts b/src/debugger.ts index 46d543f7..a1ed5860 100644 --- a/src/debugger.ts +++ b/src/debugger.ts @@ -15,12 +15,12 @@ export class Debugger private debugProcess?: ChildProcessWithoutNullStreams; private readonly console = vscode.debug.activeDebugConsole; private readonly workspaceResolver: ( - uri: vscode.Uri, + uri: vscode.Uri | undefined, ) => Workspace | undefined; constructor( context: vscode.ExtensionContext, - workspaceResolver: (uri: vscode.Uri) => Workspace | undefined, + workspaceResolver: (uri: vscode.Uri | undefined) => Workspace | undefined, ) { this.workspaceResolver = workspaceResolver; @@ -86,14 +86,12 @@ export class Debugger debugConfiguration: vscode.DebugConfiguration, _token?: vscode.CancellationToken, ): vscode.ProviderResult { - if (!folder) { - throw new Error("Debugging requires a workspace folder to be opened"); - } - - const workspace = this.workspaceResolver(folder.uri); + const workspace = this.workspaceResolver(folder?.uri); if (!workspace) { - throw new Error(`Couldn't find workspace ${folder.name}`); + throw new Error( + `Couldn't find a workspace for URI: ${folder?.uri} or editor: ${vscode.window.activeTextEditor}`, + ); } if (debugConfiguration.env) { @@ -106,6 +104,8 @@ export class Debugger debugConfiguration.env = workspace.ruby.env; } + debugConfiguration.workspace = workspace; + const workspacePath = workspace.workspaceFolder.uri.fsPath; let customGemfilePath = path.join(workspacePath, ".ruby-lsp", "Gemfile"); @@ -165,14 +165,11 @@ export class Debugger let initialMessage = ""; let initialized = false; - const workspaceFolder = session.workspaceFolder; - if (!workspaceFolder) { - throw new Error("Debugging requires a workspace folder to be opened"); - } - - const cwd = workspaceFolder.uri.fsPath; - const sockPath = this.socketPath(cwd); const configuration = session.configuration; + const workspaceFolder: vscode.WorkspaceFolder = + configuration.workspace.workspaceFolder; + const cwd = workspaceFolder.uri.fsPath; + const sockPath = this.socketPath(workspaceFolder.name); return new Promise((resolve, reject) => { const args = [ @@ -241,14 +238,14 @@ export class Debugger // Generate a socket path so that Ruby debug doesn't have to create one for us. This makes coordination easier since // we always know the path to the socket - private socketPath(cwd: string) { + private socketPath(workspaceName: string) { const socketsDir = path.join("/", "tmp", "ruby-lsp-debug-sockets"); if (!fs.existsSync(socketsDir)) { fs.mkdirSync(socketsDir); } let socketIndex = 0; - const prefix = `ruby-debug-${path.basename(cwd)}`; + const prefix = `ruby-debug-${workspaceName}`; const existingSockets = fs .readdirSync(socketsDir) .map((file) => file) diff --git a/src/rubyLsp.ts b/src/rubyLsp.ts index 0d03b961..30b72486 100644 --- a/src/rubyLsp.ts +++ b/src/rubyLsp.ts @@ -31,7 +31,7 @@ export class RubyLsp { this.telemetry, this.currentActiveWorkspace.bind(this), ); - this.debug = new Debugger(context, this.getWorkspace.bind(this)); + this.debug = new Debugger(context, this.workspaceResolver.bind(this)); this.registerCommands(context); this.statusItems = new StatusItems(); @@ -359,6 +359,28 @@ export class RubyLsp { return this.workspaces.get(uri.toString()); } + private workspaceResolver( + uri: vscode.Uri | undefined, + ): Workspace | undefined { + // If no URI is passed, we try to figured out what the active workspace is + if (!uri) { + return this.currentActiveWorkspace(); + } + + // If a workspace is found for that URI, then we return that one + const workspace = this.workspaces.get(uri.toString()); + if (workspace) { + return workspace; + } + + // Otherwise, if there's a URI, but we can't find a workspace for it, we fallback to trying to figure out what the + // active workspace is. This situation may happen if we receive a workspace folder URI that is not the actual + // workspace where the Ruby application exists. For example, if you have a monorepo with client and server + // directories and the `launch.json` file is in the top level directory, then we may receive the URI for the top + // level, but the actual workspace is the server directory + return this.currentActiveWorkspace(); + } + // Displays a quick pick to select which workspace to perform an action on. For example, if multiple workspaces exist, // then we need to know which workspace to restart the language server on private async showWorkspacePick(): Promise {