11import * as path from 'path' ;
22import * as os from 'os' ;
33import * as fs from 'fs' ;
4- import { workspace , ExtensionContext , env } from 'vscode' ;
5-
6- let patch = require ( "./patch" ) ;
7-
4+ import {
5+ workspace as Workspace ,
6+ ExtensionContext ,
7+ env as Env ,
8+ commands as Commands ,
9+ TextDocument ,
10+ WorkspaceFolder ,
11+ Uri
12+ } from 'vscode' ;
813import {
914 LanguageClient ,
1015 LanguageClientOptions ,
1116 ServerOptions ,
17+ DocumentSelector ,
1218} from 'vscode-languageclient/node' ;
13- import { commands } from 'vscode' ;
1419
15- let client : LanguageClient ;
20+ let patch = require ( "./patch" ) ;
21+
22+ let defaultClient : LanguageClient ;
23+ let clients : Map < string , LanguageClient > = new Map ( ) ;
1624
1725function registerCustomCommands ( context : ExtensionContext ) {
18- context . subscriptions . push ( commands . registerCommand ( 'lua.config' , ( data ) => {
19- let config = workspace . getConfiguration ( )
26+ context . subscriptions . push ( Commands . registerCommand ( 'lua.config' , ( data ) => {
27+ let config = Workspace . getConfiguration ( )
2028 if ( data . action == 'add' ) {
2129 let value : any [ ] = config . get ( data . key ) ;
2230 value . push ( data . value ) ;
@@ -30,24 +38,53 @@ function registerCustomCommands(context: ExtensionContext) {
3038 } ) )
3139}
3240
33- export function activate ( context : ExtensionContext ) {
34- let language = env . language ;
41+ let _sortedWorkspaceFolders : string [ ] | undefined ;
42+ function sortedWorkspaceFolders ( ) : string [ ] {
43+ if ( _sortedWorkspaceFolders === void 0 ) {
44+ _sortedWorkspaceFolders = Workspace . workspaceFolders ? Workspace . workspaceFolders . map ( folder => {
45+ let result = folder . uri . toString ( ) ;
46+ if ( result . charAt ( result . length - 1 ) !== '/' ) {
47+ result = result + '/' ;
48+ }
49+ return result ;
50+ } ) . sort (
51+ ( a , b ) => {
52+ return a . length - b . length ;
53+ }
54+ ) : [ ] ;
55+ }
56+ return _sortedWorkspaceFolders ;
57+ }
58+ Workspace . onDidChangeWorkspaceFolders ( ( ) => _sortedWorkspaceFolders = undefined ) ;
3559
60+ function getOuterMostWorkspaceFolder ( folder : WorkspaceFolder ) : WorkspaceFolder {
61+ let sorted = sortedWorkspaceFolders ( ) ;
62+ for ( let element of sorted ) {
63+ let uri = folder . uri . toString ( ) ;
64+ if ( uri . charAt ( uri . length - 1 ) !== '/' ) {
65+ uri = uri + '/' ;
66+ }
67+ if ( uri . startsWith ( element ) ) {
68+ return Workspace . getWorkspaceFolder ( Uri . parse ( element ) ) ! ;
69+ }
70+ }
71+ return folder ;
72+ }
73+
74+ function start ( context : ExtensionContext , documentSelector : DocumentSelector , folder : WorkspaceFolder ) : LanguageClient {
75+ let language = Env . language ;
3676 // Options to control the language client
3777 let clientOptions : LanguageClientOptions = {
3878 // Register the server for plain text documents
39- documentSelector : [ { scheme : 'file' , language : 'lua' } ] ,
40- synchronize : {
41- // Notify the server about file changes to '.clientrc files contained in the workspace
42- fileEvents : workspace . createFileSystemWatcher ( '**/.clientrc' )
43- }
79+ documentSelector : documentSelector ,
80+ workspaceFolder : folder ,
4481 } ;
4582
46- let beta : boolean = workspace . getConfiguration ( ) . get ( "Lua.zzzzzz.cat" ) ;
83+ let beta : boolean = Workspace . getConfiguration ( ) . get ( "Lua.zzzzzz.cat" ) ;
4784 //let beta: boolean = false;
48- let develop : boolean = workspace . getConfiguration ( ) . get ( "Lua.develop.enable" ) ;
49- let debuggerPort : number = workspace . getConfiguration ( ) . get ( "Lua.develop.debuggerPort" ) ;
50- let debuggerWait : boolean = workspace . getConfiguration ( ) . get ( "Lua.develop.debuggerWait" ) ;
85+ let develop : boolean = Workspace . getConfiguration ( ) . get ( "Lua.develop.enable" ) ;
86+ let debuggerPort : number = Workspace . getConfiguration ( ) . get ( "Lua.develop.debuggerPort" ) ;
87+ let debuggerWait : boolean = Workspace . getConfiguration ( ) . get ( "Lua.develop.debuggerWait" ) ;
5188 let command : string ;
5289 let platform : string = os . platform ( ) ;
5390 switch ( platform ) {
@@ -98,24 +135,76 @@ export function activate(context: ExtensionContext) {
98135 ]
99136 } ;
100137
101- client = new LanguageClient (
138+ let client = new LanguageClient (
102139 'Lua' ,
103140 'Lua' ,
104141 serverOptions ,
105142 clientOptions
106143 ) ;
107144
108145 client . registerProposedFeatures ( ) ;
109- registerCustomCommands ( context ) ;
110146
111147 patch . patch ( client ) ;
112148
113149 client . start ( ) ;
150+
151+ return client ;
152+ }
153+
154+ export function activate ( context : ExtensionContext ) {
155+ registerCustomCommands ( context ) ;
156+ function didOpenTextDocument ( document : TextDocument ) : void {
157+ // We are only interested in language mode text
158+ if ( document . languageId !== 'lua' || ( document . uri . scheme !== 'file' && document . uri . scheme !== 'untitled' ) ) {
159+ return ;
160+ }
161+
162+ let uri = document . uri ;
163+ // Untitled files go to a default client.
164+ if ( uri . scheme === 'untitled' && ! defaultClient ) {
165+ defaultClient = start ( context , [
166+ { scheme : 'untitled' , language : 'lua' }
167+ ] , null ) ;
168+ return ;
169+ }
170+
171+ let folder = Workspace . getWorkspaceFolder ( uri ) ;
172+ // Files outside a folder can't be handled. This might depend on the language.
173+ // Single file languages like JSON might handle files outside the workspace folders.
174+ if ( ! folder ) {
175+ return ;
176+ }
177+ // If we have nested workspace folders we only start a server on the outer most workspace folder.
178+ folder = getOuterMostWorkspaceFolder ( folder ) ;
179+
180+ if ( ! clients . has ( folder . uri . toString ( ) ) ) {
181+ let client = start ( context , [
182+ { scheme : 'file' , language : 'lua' , pattern : `${ folder . uri . fsPath } /**/*` }
183+ ] , folder ) ;
184+ clients . set ( folder . uri . toString ( ) , client ) ;
185+ }
186+ }
187+
188+ Workspace . onDidOpenTextDocument ( didOpenTextDocument ) ;
189+ Workspace . textDocuments . forEach ( didOpenTextDocument ) ;
190+ Workspace . onDidChangeWorkspaceFolders ( ( event ) => {
191+ for ( let folder of event . removed ) {
192+ let client = clients . get ( folder . uri . toString ( ) ) ;
193+ if ( client ) {
194+ clients . delete ( folder . uri . toString ( ) ) ;
195+ client . stop ( ) ;
196+ }
197+ }
198+ } ) ;
114199}
115200
116201export function deactivate ( ) : Thenable < void > | undefined {
117- if ( ! client ) {
118- return undefined ;
202+ let promises : Thenable < void > [ ] = [ ] ;
203+ if ( defaultClient ) {
204+ promises . push ( defaultClient . stop ( ) ) ;
205+ }
206+ for ( let client of clients . values ( ) ) {
207+ promises . push ( client . stop ( ) ) ;
119208 }
120- return client . stop ( ) ;
209+ return Promise . all ( promises ) . then ( ( ) => undefined ) ;
121210}
0 commit comments