Skip to content

Commit ade148d

Browse files
committed
[mlir-vscode] Add better resolution for server file paths
We currently require that server paths are full paths, which is fairly inconvenient for a myriad of reasons. This commit attempts to resolve a given server path with the current workspace. This has a nice additional affect that we can now actually have default server paths. This means that mlir-lsp-server and mlir-pdll-lsp-server can be transparently picked up from build directories (i.e. generally no need for upstream users to configure the extension). Fixes llvm#54627 Differential Revision: https://reviews.llvm.org/D122792
1 parent 2e51a32 commit ade148d

File tree

2 files changed

+67
-18
lines changed

2 files changed

+67
-18
lines changed

mlir/utils/vscode/src/configWatcher.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import * as chokidar from 'chokidar';
2-
import * as path from 'path';
32
import * as vscode from 'vscode';
43

54
import * as config from './config';
@@ -42,7 +41,8 @@ async function promptRestart(settingName: string, promptMessage: string) {
4241
* Activate the watchers that track configuration changes which decide when to
4342
* restart the server.
4443
*/
45-
export function activate(mlirContext: MLIRContext) {
44+
export async function activate(mlirContext: MLIRContext,
45+
serverPathsToWatch: string[]) {
4646
// When a configuration change happens, check to see if we should restart the
4747
// server.
4848
mlirContext.subscriptions.push(vscode.workspace.onDidChangeConfiguration(event => {
@@ -61,10 +61,7 @@ export function activate(mlirContext: MLIRContext) {
6161

6262
// Track the server file in case it changes. We use `fs` here because the
6363
// server may not be in a workspace directory.
64-
const settings: string[] = [ 'server_path', 'pdll_server_path' ];
65-
for (const setting of settings) {
66-
const serverPath = config.get<string>(setting);
67-
64+
for (const serverPath of serverPathsToWatch) {
6865
// Check that the path actually exists.
6966
if (serverPath === '') {
7067
continue;

mlir/utils/vscode/src/mlirContext.ts

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import * as fs from 'fs';
2+
import * as path from 'path';
23
import * as vscode from 'vscode';
34
import * as vscodelc from 'vscode-languageclient';
45

@@ -20,31 +21,36 @@ export class MLIRContext implements vscode.Disposable {
2021
async activate(outputChannel: vscode.OutputChannel,
2122
warnOnEmptyServerPath: boolean) {
2223
// Create the language clients for mlir and pdll.
23-
this.pdllClient = this.startLanguageClient(
24+
let mlirServerPath: string, pdllServerPath: string;
25+
[this.client, mlirServerPath] = await this.startLanguageClient(
26+
outputChannel, warnOnEmptyServerPath, 'server_path', 'mlir');
27+
[this.pdllClient, pdllServerPath] = await this.startLanguageClient(
2428
outputChannel, warnOnEmptyServerPath, 'pdll_server_path', 'pdll');
25-
this.client = this.startLanguageClient(outputChannel, warnOnEmptyServerPath,
26-
'server_path', 'mlir');
2729

2830
// Watch for configuration changes.
29-
configWatcher.activate(this);
31+
const serverPathsToWatch = [ mlirServerPath, pdllServerPath ];
32+
await configWatcher.activate(this, serverPathsToWatch);
3033
}
3134

3235
/**
33-
* Start a new language client for the given language.
36+
* Start a new language client for the given language. Returns an array
37+
* containing the opened server, or null if the server could not be started,
38+
* and the resolved server path.
3439
*/
35-
startLanguageClient(outputChannel: vscode.OutputChannel,
36-
warnOnEmptyServerPath: boolean, serverSettingName: string,
37-
languageName: string): vscodelc.LanguageClient {
40+
async startLanguageClient(outputChannel: vscode.OutputChannel,
41+
warnOnEmptyServerPath: boolean,
42+
serverSettingName: string, languageName: string):
43+
Promise<[ vscodelc.LanguageClient, string ]> {
3844
const clientTitle = languageName.toUpperCase() + ' Language Client';
3945

4046
// Get the path of the lsp-server that is used to provide language
4147
// functionality.
42-
const serverPath = config.get<string>(serverSettingName);
48+
var serverPath = await this.resolveServerPath(serverSettingName);
4349

4450
// If we aren't emitting warnings on an empty server path, and the server
4551
// path is empty, bail.
4652
if (!warnOnEmptyServerPath && serverPath === '') {
47-
return null;
53+
return [ null, serverPath ];
4854
}
4955

5056
// Check that the file actually exists.
@@ -61,7 +67,7 @@ export class MLIRContext implements vscode.Disposable {
6167
{openToSide : false, query : `mlir.${serverSettingName}`});
6268
}
6369
});
64-
return null;
70+
return [ null, serverPath ];
6571
}
6672

6773
// Configure the server options.
@@ -94,7 +100,53 @@ export class MLIRContext implements vscode.Disposable {
94100
let languageClient = new vscodelc.LanguageClient(
95101
languageName + '-lsp', clientTitle, serverOptions, clientOptions);
96102
this.subscriptions.push(languageClient.start());
97-
return languageClient;
103+
return [ languageClient, serverPath ];
104+
}
105+
106+
/**
107+
* Given a server setting, return the default server path.
108+
*/
109+
static getDefaultServerFilename(serverSettingName: string): string {
110+
if (serverSettingName === 'pdll_server_path') {
111+
return 'mlir-pdll-lsp-server';
112+
}
113+
if (serverSettingName === 'server_path') {
114+
return 'mlir-lsp-server';
115+
}
116+
return '';
117+
}
118+
119+
/**
120+
* Try to resolve the path for the given server setting.
121+
*/
122+
async resolveServerPath(serverSettingName: string): Promise<string> {
123+
let configServerPath = config.get<string>(serverSettingName);
124+
let serverPath = configServerPath;
125+
126+
// If the path is already fully resolved, there is nothing to do.
127+
if (path.isAbsolute(serverPath)) {
128+
return serverPath;
129+
}
130+
131+
// If a path hasn't been set, try to use the default path.
132+
if (serverPath === '') {
133+
serverPath = MLIRContext.getDefaultServerFilename(serverSettingName);
134+
if (serverPath === '') {
135+
return serverPath;
136+
}
137+
// Fallthrough to try resolving the default path.
138+
}
139+
140+
// Try to resolve the path relative to the workspace.
141+
const foundUris: vscode.Uri[] =
142+
await vscode.workspace.findFiles('**/' + serverPath, null, 1);
143+
if (foundUris.length === 0) {
144+
// If we couldn't resolve it, just return the current configuration path
145+
// anyways. The file might not exist yet.
146+
return configServerPath;
147+
}
148+
// Otherwise, return the resolved path.
149+
return foundUris[0].fsPath;
98150
}
99151

100152
dispose() {

0 commit comments

Comments
 (0)