@@ -6,46 +6,84 @@ import * as vscodelc from 'vscode-languageclient';
6
6
import * as config from './config' ;
7
7
import * as configWatcher from './configWatcher' ;
8
8
9
+ /**
10
+ * This class represents the context of a specific workspace folder.
11
+ */
12
+ class WorkspaceFolderContext {
13
+ constructor ( mlirServer : vscodelc . LanguageClient ,
14
+ pdllServer : vscodelc . LanguageClient ) {
15
+ this . mlirServer = mlirServer ;
16
+ this . pdllServer = pdllServer ;
17
+ }
18
+ mlirServer ! : vscodelc . LanguageClient ;
19
+ pdllServer ! : vscodelc . LanguageClient ;
20
+ }
21
+
9
22
/**
10
23
* This class manages all of the MLIR extension state,
11
24
* including the language client.
12
25
*/
13
26
export class MLIRContext implements vscode . Disposable {
14
27
subscriptions : vscode . Disposable [ ] = [ ] ;
15
- client ! : vscodelc . LanguageClient ;
16
- pdllClient ! : vscodelc . LanguageClient ;
28
+ workspaceFolders : WorkspaceFolderContext [ ] = [ ] ;
17
29
18
30
/**
19
31
* Activate the MLIR context, and start the language clients.
20
32
*/
21
33
async activate ( outputChannel : vscode . OutputChannel ,
22
34
warnOnEmptyServerPath : boolean ) {
23
- // Create the language clients for mlir and pdll.
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 (
28
- outputChannel , warnOnEmptyServerPath , 'pdll_server_path' , 'pdll' ) ;
35
+ // Start clients for each workspace folder.
36
+ if ( vscode . workspace . workspaceFolders &&
37
+ vscode . workspace . workspaceFolders . length > 0 ) {
38
+ for ( const workspaceFolder of vscode . workspace . workspaceFolders ) {
39
+ this . workspaceFolders . push ( await this . activateWorkspaceFolder (
40
+ workspaceFolder , outputChannel , warnOnEmptyServerPath ) ) ;
41
+ }
42
+ } else {
43
+ this . workspaceFolders . push ( await this . activateWorkspaceFolder (
44
+ null , outputChannel , warnOnEmptyServerPath ) ) ;
45
+ }
46
+ }
29
47
30
- // Watch for configuration changes.
48
+ /**
49
+ * Activate the context for the given workspace folder, and start the
50
+ * language clients.
51
+ */
52
+ async activateWorkspaceFolder ( workspaceFolder : vscode . WorkspaceFolder ,
53
+ outputChannel : vscode . OutputChannel ,
54
+ warnOnEmptyServerPath : boolean ) :
55
+ Promise < WorkspaceFolderContext > {
56
+ // Create the language clients for mlir and pdll.
57
+ const [ mlirServer , mlirServerPath ] = await this . startLanguageClient (
58
+ workspaceFolder , outputChannel , warnOnEmptyServerPath , 'server_path' ,
59
+ 'mlir' ) ;
60
+ const [ pdllServer , pdllServerPath ] = await this . startLanguageClient (
61
+ workspaceFolder , outputChannel , warnOnEmptyServerPath ,
62
+ 'pdll_server_path' , 'pdll' ) ;
63
+
64
+ // Watch for configuration changes on this folder.
31
65
const serverPathsToWatch = [ mlirServerPath , pdllServerPath ] ;
32
- await configWatcher . activate ( this , serverPathsToWatch ) ;
66
+ await configWatcher . activate ( this , workspaceFolder , serverPathsToWatch ) ;
67
+
68
+ return new WorkspaceFolderContext ( mlirServer , pdllServer ) ;
33
69
}
34
70
35
71
/**
36
72
* Start a new language client for the given language. Returns an array
37
73
* containing the opened server, or null if the server could not be started,
38
74
* and the resolved server path.
39
75
*/
40
- async startLanguageClient ( outputChannel : vscode . OutputChannel ,
76
+ async startLanguageClient ( workspaceFolder : vscode . WorkspaceFolder ,
77
+ outputChannel : vscode . OutputChannel ,
41
78
warnOnEmptyServerPath : boolean ,
42
79
serverSettingName : string , languageName : string ) :
43
80
Promise < [ vscodelc . LanguageClient , string ] > {
44
81
const clientTitle = languageName . toUpperCase ( ) + ' Language Client' ;
45
82
46
83
// Get the path of the lsp-server that is used to provide language
47
84
// functionality.
48
- var serverPath = await this . resolveServerPath ( serverSettingName ) ;
85
+ var serverPath =
86
+ await this . resolveServerPath ( serverSettingName , workspaceFolder ) ;
49
87
50
88
// If we aren't emitting warnings on an empty server path, and the server
51
89
// path is empty, bail.
@@ -84,16 +122,26 @@ export class MLIRContext implements vscode.Disposable {
84
122
}
85
123
} ;
86
124
125
+ // Configure file patterns relative to the workspace folder.
126
+ let filePattern : vscode . GlobPattern = '**/*.' + languageName ;
127
+ let selectorPattern : string = null ;
128
+ if ( workspaceFolder ) {
129
+ filePattern = new vscode . RelativePattern ( workspaceFolder , filePattern ) ;
130
+ selectorPattern = `${ workspaceFolder . uri . fsPath } /**/*` ;
131
+ }
132
+
87
133
// Configure the client options.
88
134
const clientOptions : vscodelc . LanguageClientOptions = {
89
- documentSelector : [ { scheme : 'file' , language : languageName } ] ,
135
+ documentSelector : [
136
+ { scheme : 'file' , language : languageName , pattern : selectorPattern }
137
+ ] ,
90
138
synchronize : {
91
139
// Notify the server about file changes to language files contained in
92
140
// the workspace.
93
- fileEvents :
94
- vscode . workspace . createFileSystemWatcher ( '**/*.' + languageName )
141
+ fileEvents : vscode . workspace . createFileSystemWatcher ( filePattern )
95
142
} ,
96
143
outputChannel : outputChannel ,
144
+ workspaceFolder : workspaceFolder
97
145
} ;
98
146
99
147
// Create the language client and start the client.
@@ -117,10 +165,14 @@ export class MLIRContext implements vscode.Disposable {
117
165
}
118
166
119
167
/**
120
- * Try to resolve the path for the given server setting.
168
+ * Try to resolve the path for the given server setting, with an optional
169
+ * workspace folder.
121
170
*/
122
- async resolveServerPath ( serverSettingName : string ) : Promise < string > {
123
- let configServerPath = config . get < string > ( serverSettingName ) ;
171
+ async resolveServerPath ( serverSettingName : string ,
172
+ workspaceFolder : vscode . WorkspaceFolder ) :
173
+ Promise < string > {
174
+ const configServerPath =
175
+ config . get < string > ( serverSettingName , workspaceFolder ) ;
124
176
let serverPath = configServerPath ;
125
177
126
178
// If the path is already fully resolved, there is nothing to do.
@@ -138,8 +190,11 @@ export class MLIRContext implements vscode.Disposable {
138
190
}
139
191
140
192
// Try to resolve the path relative to the workspace.
141
- const foundUris : vscode . Uri [ ] =
142
- await vscode . workspace . findFiles ( '**/' + serverPath , null , 1 ) ;
193
+ let filePattern : vscode . GlobPattern = '**/' + serverPath ;
194
+ if ( workspaceFolder ) {
195
+ filePattern = new vscode . RelativePattern ( workspaceFolder , filePattern ) ;
196
+ }
197
+ let foundUris = await vscode . workspace . findFiles ( filePattern , null , 1 ) ;
143
198
if ( foundUris . length === 0 ) {
144
199
// If we couldn't resolve it, just return the current configuration path
145
200
// anyways. The file might not exist yet.
@@ -152,5 +207,6 @@ export class MLIRContext implements vscode.Disposable {
152
207
dispose ( ) {
153
208
this . subscriptions . forEach ( ( d ) => { d . dispose ( ) ; } ) ;
154
209
this . subscriptions = [ ] ;
210
+ this . workspaceFolders = [ ] ;
155
211
}
156
212
}
0 commit comments