diff --git a/mlir/utils/vscode/src/configWatcher.ts b/mlir/utils/vscode/src/configWatcher.ts --- a/mlir/utils/vscode/src/configWatcher.ts +++ b/mlir/utils/vscode/src/configWatcher.ts @@ -1,5 +1,4 @@ import * as chokidar from 'chokidar'; -import * as path from 'path'; import * as vscode from 'vscode'; import * as config from './config'; @@ -42,7 +41,7 @@ * Activate the watchers that track configuration changes which decide when to * restart the server. */ -export function activate(mlirContext: MLIRContext) { +export async function activate(mlirContext: MLIRContext) { // When a configuration change happens, check to see if we should restart the // server. mlirContext.subscriptions.push(vscode.workspace.onDidChangeConfiguration(event => { @@ -63,7 +62,7 @@ // server may not be in a workspace directory. const settings: string[] = [ 'server_path', 'pdll_server_path' ]; for (const setting of settings) { - const serverPath = config.get(setting); + const serverPath = await mlirContext.resolveServerPath(setting); // Check that the path actually exists. if (serverPath === '') { diff --git a/mlir/utils/vscode/src/mlirContext.ts b/mlir/utils/vscode/src/mlirContext.ts --- a/mlir/utils/vscode/src/mlirContext.ts +++ b/mlir/utils/vscode/src/mlirContext.ts @@ -1,4 +1,5 @@ import * as fs from 'fs'; +import * as path from 'path'; import * as vscode from 'vscode'; import * as vscodelc from 'vscode-languageclient'; @@ -20,26 +21,27 @@ async activate(outputChannel: vscode.OutputChannel, warnOnEmptyServerPath: boolean) { // Create the language clients for mlir and pdll. - this.pdllClient = this.startLanguageClient( + this.pdllClient = await this.startLanguageClient( outputChannel, warnOnEmptyServerPath, 'pdll_server_path', 'pdll'); - this.client = this.startLanguageClient(outputChannel, warnOnEmptyServerPath, - 'server_path', 'mlir'); + this.client = await this.startLanguageClient( + outputChannel, warnOnEmptyServerPath, 'server_path', 'mlir'); // Watch for configuration changes. - configWatcher.activate(this); + await configWatcher.activate(this); } /** * Start a new language client for the given language. */ - startLanguageClient(outputChannel: vscode.OutputChannel, - warnOnEmptyServerPath: boolean, serverSettingName: string, - languageName: string): vscodelc.LanguageClient { + async startLanguageClient(outputChannel: vscode.OutputChannel, + warnOnEmptyServerPath: boolean, + serverSettingName: string, languageName: string): + Promise { const clientTitle = languageName.toUpperCase() + ' Language Client'; // Get the path of the lsp-server that is used to provide language // functionality. - const serverPath = config.get(serverSettingName); + var serverPath = await this.resolveServerPath(serverSettingName); // If we aren't emitting warnings on an empty server path, and the server // path is empty, bail. @@ -97,6 +99,52 @@ return languageClient; } + /** + * Given a server setting, return the default server path. + */ + static getDefaultServerPath(serverSettingName: string): string { + if (serverSettingName === 'pdll_server_path') { + return 'mlir-pdll-lsp-server'; + } + if (serverSettingName === 'server_path') { + return 'mlir-lsp-server'; + } + return ''; + } + + /** + * Try to resolve the path for the given server setting. + */ + async resolveServerPath(serverSettingName: string): Promise { + let configServerPath = config.get(serverSettingName); + let serverPath = configServerPath; + + // If the path is already fully resolved, there is nothing to do. + if (path.isAbsolute(serverPath)) { + return serverPath; + } + + // If a path hasn't been set, try to use the default path. + if (serverPath === '') { + serverPath = MLIRContext.getDefaultServerPath(serverSettingName); + if (serverPath === '') { + return serverPath; + } + // Fallthrough to try resolving the default path. + } + + // Try to resolve the path relative to the workspace. + const foundUris: vscode.Uri[] = + await vscode.workspace.findFiles('**/' + serverPath, null, 1); + if (foundUris.length === 0) { + // If we couldn't resolve it, just return the current configuration path + // anyways. The file might not exist yet. + return configServerPath; + } + // Otherwise, return the resolved path. + return foundUris[0].fsPath; + } + dispose() { this.subscriptions.forEach((d) => { d.dispose(); }); this.subscriptions = [];