[Mlir-commits] [mlir] 43c0a45 - [mlir-vscode] Add better support for multiple workspace folders

River Riddle llvmlistbot at llvm.org
Tue Apr 5 13:43:49 PDT 2022


Author: River Riddle
Date: 2022-04-05T13:41:40-07:00
New Revision: 43c0a45a79d0697f05fe4562f4f01571b11d8f85

URL: https://github.com/llvm/llvm-project/commit/43c0a45a79d0697f05fe4562f4f01571b11d8f85
DIFF: https://github.com/llvm/llvm-project/commit/43c0a45a79d0697f05fe4562f4f01571b11d8f85.diff

LOG: [mlir-vscode] Add better support for multiple workspace folders

We currently only launch one set of language clients when starting the extension,
but this has the unfortunate effect of applying the same settings to all workspace
folders. This commit adds support for multiple workspace folders by launching
a server for each folder in the workspace. This allows for having different servers
for different workspace folders, e.g. when there are multiple MLIR projects in
the same workspace.

Differential Revision: https://reviews.llvm.org/D122793

Added: 
    

Modified: 
    mlir/utils/vscode/package.json
    mlir/utils/vscode/src/config.ts
    mlir/utils/vscode/src/configWatcher.ts
    mlir/utils/vscode/src/mlirContext.ts

Removed: 
    


################################################################################
diff  --git a/mlir/utils/vscode/package.json b/mlir/utils/vscode/package.json
index 9747dd72a852b..74072d9e1858a 100644
--- a/mlir/utils/vscode/package.json
+++ b/mlir/utils/vscode/package.json
@@ -2,7 +2,7 @@
   "name": "vscode-mlir",
   "displayName": "MLIR",
   "description": "MLIR Language Extension",
-  "version": "0.0.4",
+  "version": "0.0.5",
   "publisher": "llvm-vs-code-extensions",
   "homepage": "https://mlir.llvm.org/",
   "icon": "icon.png",

diff  --git a/mlir/utils/vscode/src/config.ts b/mlir/utils/vscode/src/config.ts
index 58f45ccbc8c02..d7dd5bfb5454e 100644
--- a/mlir/utils/vscode/src/config.ts
+++ b/mlir/utils/vscode/src/config.ts
@@ -1,10 +1,11 @@
 import * as vscode from 'vscode';
 
 /**
- *  Gets the config value `mlir.<key>`.
+ *  Gets the config value `mlir.<key>`, with an optional workspace folder.
  */
-export function get<T>(key: string): T {
-  return vscode.workspace.getConfiguration('mlir').get<T>(key);
+export function get<T>(key: string,
+                       workspaceFolder: vscode.WorkspaceFolder = null): T {
+  return vscode.workspace.getConfiguration('mlir', workspaceFolder).get<T>(key);
 }
 
 /**

diff  --git a/mlir/utils/vscode/src/configWatcher.ts b/mlir/utils/vscode/src/configWatcher.ts
index a89391dca5879..180a8148fe185 100644
--- a/mlir/utils/vscode/src/configWatcher.ts
+++ b/mlir/utils/vscode/src/configWatcher.ts
@@ -38,10 +38,11 @@ async function promptRestart(settingName: string, promptMessage: string) {
 }
 
 /**
- *  Activate the watchers that track configuration changes which decide when to
- *  restart the server.
+ *  Activate watchers that track configuration changes for the given workspace
+ *  folder, or null if the workspace is top-level.
  */
 export async function activate(mlirContext: MLIRContext,
+                               workspaceFolder: vscode.WorkspaceFolder,
                                serverPathsToWatch: string[]) {
   // When a configuration change happens, check to see if we should restart the
   // server.
@@ -49,7 +50,7 @@ export async function activate(mlirContext: MLIRContext,
     const settings: string[] = [ 'server_path', 'pdll_server_path' ];
     for (const setting of settings) {
       const expandedSetting = `mlir.${setting}`;
-      if (event.affectsConfiguration(expandedSetting)) {
+      if (event.affectsConfiguration(expandedSetting, workspaceFolder)) {
         promptRestart(
             'onSettingsChanged',
             `setting '${

diff  --git a/mlir/utils/vscode/src/mlirContext.ts b/mlir/utils/vscode/src/mlirContext.ts
index ea1d0a5496b8e..521fdf0f260a7 100644
--- a/mlir/utils/vscode/src/mlirContext.ts
+++ b/mlir/utils/vscode/src/mlirContext.ts
@@ -6,30 +6,66 @@ import * as vscodelc from 'vscode-languageclient';
 import * as config from './config';
 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);
   }
 
   /**
@@ -37,7 +73,8 @@ export class MLIRContext implements vscode.Disposable {
    *  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 ]> {
@@ -45,7 +82,8 @@ export class MLIRContext implements vscode.Disposable {
 
     // 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.
@@ -84,16 +122,26 @@ export class MLIRContext implements vscode.Disposable {
       }
     };
 
+    // 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.
@@ -117,10 +165,14 @@ export class MLIRContext implements vscode.Disposable {
   }
 
   /**
-   * 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.
@@ -138,8 +190,11 @@ export class MLIRContext implements vscode.Disposable {
     }
 
     // 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.
@@ -152,5 +207,6 @@ export class MLIRContext implements vscode.Disposable {
   dispose() {
     this.subscriptions.forEach((d) => { d.dispose(); });
     this.subscriptions = [];
+    this.workspaceFolders = [];
   }
 }


        


More information about the Mlir-commits mailing list