import * as configWatcher from './configWatcher';
/**
+ * This class represents the context of a specific workspace folder.
+ */
+class WorkspaceFolderContext {
+ constructor(mlirServer: vscodelc.LanguageClient,
+ pdllServer: vscodelc.LanguageClient) {
+ this.mlirServer = mlirServer;
+ this.pdllServer = pdllServer;
+ }
+ mlirServer!: vscodelc.LanguageClient;
+ pdllServer!: vscodelc.LanguageClient;
+}
+
+/**
* This class manages all of the MLIR extension state,
* including the language client.
*/
export class MLIRContext implements vscode.Disposable {
subscriptions: vscode.Disposable[] = [];
- client!: vscodelc.LanguageClient;
- pdllClient!: vscodelc.LanguageClient;
+ workspaceFolders: WorkspaceFolderContext[] = [];
/**
* Activate the MLIR context, and start the language clients.
*/
async activate(outputChannel: vscode.OutputChannel,
warnOnEmptyServerPath: boolean) {
- // Create the language clients for mlir and pdll.
- let mlirServerPath: string, pdllServerPath: string;
- [this.client, mlirServerPath] = await this.startLanguageClient(
- outputChannel, warnOnEmptyServerPath, 'server_path', 'mlir');
- [this.pdllClient, pdllServerPath] = await this.startLanguageClient(
- outputChannel, warnOnEmptyServerPath, 'pdll_server_path', 'pdll');
+ // Start clients for each workspace folder.
+ if (vscode.workspace.workspaceFolders &&
+ vscode.workspace.workspaceFolders.length > 0) {
+ for (const workspaceFolder of vscode.workspace.workspaceFolders) {
+ this.workspaceFolders.push(await this.activateWorkspaceFolder(
+ workspaceFolder, outputChannel, warnOnEmptyServerPath));
+ }
+ } else {
+ this.workspaceFolders.push(await this.activateWorkspaceFolder(
+ null, outputChannel, warnOnEmptyServerPath));
+ }
+ }
- // Watch for configuration changes.
+ /**
+ * Activate the context for the given workspace folder, and start the
+ * language clients.
+ */
+ async activateWorkspaceFolder(workspaceFolder: vscode.WorkspaceFolder,
+ outputChannel: vscode.OutputChannel,
+ warnOnEmptyServerPath: boolean):
+ Promise<WorkspaceFolderContext> {
+ // Create the language clients for mlir and pdll.
+ const [mlirServer, mlirServerPath] = await this.startLanguageClient(
+ workspaceFolder, outputChannel, warnOnEmptyServerPath, 'server_path',
+ 'mlir');
+ const [pdllServer, pdllServerPath] = await this.startLanguageClient(
+ workspaceFolder, outputChannel, warnOnEmptyServerPath,
+ 'pdll_server_path', 'pdll');
+
+ // Watch for configuration changes on this folder.
const serverPathsToWatch = [ mlirServerPath, pdllServerPath ];
- await configWatcher.activate(this, serverPathsToWatch);
+ await configWatcher.activate(this, workspaceFolder, serverPathsToWatch);
+
+ return new WorkspaceFolderContext(mlirServer, pdllServer);
}
/**
* containing the opened server, or null if the server could not be started,
* and the resolved server path.
*/
- async startLanguageClient(outputChannel: vscode.OutputChannel,
+ async startLanguageClient(workspaceFolder: vscode.WorkspaceFolder,
+ outputChannel: vscode.OutputChannel,
warnOnEmptyServerPath: boolean,
serverSettingName: string, languageName: string):
Promise<[ vscodelc.LanguageClient, string ]> {
// Get the path of the lsp-server that is used to provide language
// functionality.
- var serverPath = await this.resolveServerPath(serverSettingName);
+ var serverPath =
+ await this.resolveServerPath(serverSettingName, workspaceFolder);
// If we aren't emitting warnings on an empty server path, and the server
// path is empty, bail.
}
};
+ // Configure file patterns relative to the workspace folder.
+ let filePattern: vscode.GlobPattern = '**/*.' + languageName;
+ let selectorPattern: string = null;
+ if (workspaceFolder) {
+ filePattern = new vscode.RelativePattern(workspaceFolder, filePattern);
+ selectorPattern = `${workspaceFolder.uri.fsPath}/**/*`;
+ }
+
// Configure the client options.
const clientOptions: vscodelc.LanguageClientOptions = {
- documentSelector : [ {scheme : 'file', language : languageName} ],
+ documentSelector : [
+ {scheme : 'file', language : languageName, pattern : selectorPattern}
+ ],
synchronize : {
// Notify the server about file changes to language files contained in
// the workspace.
- fileEvents :
- vscode.workspace.createFileSystemWatcher('**/*.' + languageName)
+ fileEvents : vscode.workspace.createFileSystemWatcher(filePattern)
},
outputChannel : outputChannel,
+ workspaceFolder : workspaceFolder
};
// Create the language client and start the client.
}
/**
- * Try to resolve the path for the given server setting.
+ * Try to resolve the path for the given server setting, with an optional
+ * workspace folder.
*/
- async resolveServerPath(serverSettingName: string): Promise<string> {
- let configServerPath = config.get<string>(serverSettingName);
+ async resolveServerPath(serverSettingName: string,
+ workspaceFolder: vscode.WorkspaceFolder):
+ Promise<string> {
+ const configServerPath =
+ config.get<string>(serverSettingName, workspaceFolder);
let serverPath = configServerPath;
// If the path is already fully resolved, there is nothing to do.
}
// Try to resolve the path relative to the workspace.
- const foundUris: vscode.Uri[] =
- await vscode.workspace.findFiles('**/' + serverPath, null, 1);
+ let filePattern: vscode.GlobPattern = '**/' + serverPath;
+ if (workspaceFolder) {
+ filePattern = new vscode.RelativePattern(workspaceFolder, filePattern);
+ }
+ let foundUris = await vscode.workspace.findFiles(filePattern, 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.
dispose() {
this.subscriptions.forEach((d) => { d.dispose(); });
this.subscriptions = [];
+ this.workspaceFolders = [];
}
}