99 * ------------------------------------------------------------------------------------------ */
1010'use strict' ;
1111
12- import { env , languages , commands , workspace , window , ExtensionContext , Memento , IndentAction , Diagnostic , DiagnosticCollection , Range , Disposable , Uri , MessageItem , TextEditor } from 'vscode' ;
12+ import { env , languages , commands , workspace , window , ExtensionContext , Memento , IndentAction , Diagnostic , DiagnosticCollection , Range , Disposable , Uri , MessageItem , TextEditor , FileSystemWatcher } from 'vscode' ;
1313
1414// This must be the first statement otherwise modules might got loaded with
1515// the wrong locale.
@@ -86,6 +86,7 @@ export function activate(context: ExtensionContext): void {
8686 configFile : 'jsconfig.json'
8787 }
8888 ] , context . storagePath , context . globalState , context . workspaceState ) ;
89+ context . subscriptions . push ( clientHost ) ;
8990
9091 const client = clientHost . serviceClient ;
9192
@@ -139,10 +140,10 @@ const validateSetting = 'validate.enable';
139140
140141class LanguageProvider {
141142
142- private extensions : ObjectMap < boolean > ;
143+ private readonly extensions : ObjectMap < boolean > ;
143144 private syntaxDiagnostics : ObjectMap < Diagnostic [ ] > ;
144- private currentDiagnostics : DiagnosticCollection ;
145- private bufferSyncSupport : BufferSyncSupport ;
145+ private readonly currentDiagnostics : DiagnosticCollection ;
146+ private readonly bufferSyncSupport : BufferSyncSupport ;
146147
147148 private completionItemProvider : CompletionItemProvider ;
148149 private formattingProvider : FormattingProvider ;
@@ -152,6 +153,8 @@ class LanguageProvider {
152153
153154 private _validate : boolean = true ;
154155
156+ private readonly disposables : Disposable [ ] = [ ] ;
157+
155158 constructor (
156159 private readonly client : TypeScriptServiceClient ,
157160 private readonly description : LanguageDescription
@@ -170,7 +173,7 @@ class LanguageProvider {
170173 this . typingsStatus = new TypingsStatus ( client ) ;
171174 new AtaProgressReporter ( client ) ;
172175
173- workspace . onDidChangeConfiguration ( this . configurationChanged , this ) ;
176+ workspace . onDidChangeConfiguration ( this . configurationChanged , this , this . disposables ) ;
174177 this . configurationChanged ( ) ;
175178
176179 client . onReady ( ) . then ( ( ) => {
@@ -181,51 +184,68 @@ class LanguageProvider {
181184 } ) ;
182185 }
183186
187+ public dispose ( ) : void {
188+ if ( this . formattingProviderRegistration ) {
189+ this . formattingProviderRegistration . dispose ( ) ;
190+ }
191+
192+ while ( this . disposables . length ) {
193+ const obj = this . disposables . pop ( ) ;
194+ if ( obj ) {
195+ obj . dispose ( ) ;
196+ }
197+ }
198+
199+ this . typingsStatus . dispose ( ) ;
200+ this . currentDiagnostics . dispose ( ) ;
201+ this . bufferSyncSupport . dispose ( ) ;
202+ }
203+
184204 private registerProviders ( client : TypeScriptServiceClient ) : void {
185205 const selector = this . description . modeIds ;
186206 const config = workspace . getConfiguration ( this . id ) ;
187207
188208 this . completionItemProvider = new CompletionItemProvider ( client , this . typingsStatus ) ;
189209 this . completionItemProvider . updateConfiguration ( ) ;
190- languages . registerCompletionItemProvider ( selector , this . completionItemProvider , '.' ) ;
210+ this . disposables . push ( languages . registerCompletionItemProvider ( selector , this . completionItemProvider , '.' ) ) ;
191211
192212 this . formattingProvider = new FormattingProvider ( client ) ;
193213 this . formattingProvider . updateConfiguration ( config ) ;
194- languages . registerOnTypeFormattingEditProvider ( selector , this . formattingProvider , ';' , '}' , '\n' ) ;
214+ this . disposables . push ( languages . registerOnTypeFormattingEditProvider ( selector , this . formattingProvider , ';' , '}' , '\n' ) ) ;
195215 if ( this . formattingProvider . isEnabled ( ) ) {
196216 this . formattingProviderRegistration = languages . registerDocumentRangeFormattingEditProvider ( selector , this . formattingProvider ) ;
197217 }
198218
199- languages . registerHoverProvider ( selector , new HoverProvider ( client ) ) ;
200- languages . registerDefinitionProvider ( selector , new DefinitionProvider ( client ) ) ;
201- languages . registerDocumentHighlightProvider ( selector , new DocumentHighlightProvider ( client ) ) ;
202- languages . registerReferenceProvider ( selector , new ReferenceProvider ( client ) ) ;
203- languages . registerDocumentSymbolProvider ( selector , new DocumentSymbolProvider ( client ) ) ;
204- languages . registerSignatureHelpProvider ( selector , new SignatureHelpProvider ( client ) , '(' , ',' ) ;
205- languages . registerRenameProvider ( selector , new RenameProvider ( client ) ) ;
219+ this . disposables . push ( languages . registerHoverProvider ( selector , new HoverProvider ( client ) ) ) ;
220+ this . disposables . push ( languages . registerDefinitionProvider ( selector , new DefinitionProvider ( client ) ) ) ;
221+ this . disposables . push ( languages . registerDocumentHighlightProvider ( selector , new DocumentHighlightProvider ( client ) ) ) ;
222+ this . disposables . push ( languages . registerReferenceProvider ( selector , new ReferenceProvider ( client ) ) ) ;
223+ this . disposables . push ( languages . registerDocumentSymbolProvider ( selector , new DocumentSymbolProvider ( client ) ) ) ;
224+ this . disposables . push ( languages . registerSignatureHelpProvider ( selector , new SignatureHelpProvider ( client ) , '(' , ',' ) ) ;
225+ this . disposables . push ( languages . registerRenameProvider ( selector , new RenameProvider ( client ) ) ) ;
206226
207227 if ( client . apiVersion . has206Features ( ) ) {
208228 this . referenceCodeLensProvider = new ReferenceCodeLensProvider ( client ) ;
209229 this . referenceCodeLensProvider . updateConfiguration ( ) ;
210- languages . registerCodeLensProvider ( selector , this . referenceCodeLensProvider ) ;
230+ this . disposables . push ( languages . registerCodeLensProvider ( selector , this . referenceCodeLensProvider ) ) ;
211231 }
212232
213233 if ( client . apiVersion . has213Features ( ) ) {
214- languages . registerCodeActionsProvider ( selector , new CodeActionProvider ( client , this . description . id ) ) ;
234+ this . disposables . push ( languages . registerCodeActionsProvider ( selector , new CodeActionProvider ( client , this . description . id ) ) ) ;
215235 }
216236
217237 if ( client . apiVersion . has220Features ( ) ) {
218- languages . registerImplementationProvider ( selector , new ImplementationProvider ( client ) ) ;
238+ this . disposables . push ( languages . registerImplementationProvider ( selector , new ImplementationProvider ( client ) ) ) ;
219239 }
220240
221241 if ( client . apiVersion . has213Features ( ) ) {
222- languages . registerTypeDefinitionProvider ( selector , new TypeDefintionProvider ( client ) ) ;
242+ this . disposables . push ( languages . registerTypeDefinitionProvider ( selector , new TypeDefintionProvider ( client ) ) ) ;
223243 }
224244
225245 this . description . modeIds . forEach ( modeId => {
226- languages . registerWorkspaceSymbolProvider ( new WorkspaceSymbolProvider ( client , modeId ) ) ;
246+ this . disposables . push ( languages . registerWorkspaceSymbolProvider ( new WorkspaceSymbolProvider ( client , modeId ) ) ) ;
227247
228- languages . setLanguageConfiguration ( modeId , {
248+ this . disposables . push ( languages . setLanguageConfiguration ( modeId , {
229249 indentationRules : {
230250 // ^(.*\*/)?\s*\ }.*$
231251 decreaseIndentPattern : / ^ ( .* \* \/ ) ? \s * \} .* $ / ,
@@ -258,11 +278,11 @@ class LanguageProvider {
258278 action : { indentAction : IndentAction . None , removeText : 1 }
259279 }
260280 ]
261- } ) ;
281+ } ) ) ;
262282
263283 const EMPTY_ELEMENTS : string [ ] = [ 'area' , 'base' , 'br' , 'col' , 'embed' , 'hr' , 'img' , 'input' , 'keygen' , 'link' , 'menuitem' , 'meta' , 'param' , 'source' , 'track' , 'wbr' ] ;
264284
265- languages . setLanguageConfiguration ( 'jsx-tags' , {
285+ this . disposables . push ( languages . setLanguageConfiguration ( 'jsx-tags' , {
266286 wordPattern : / ( - ? \d * \. \d \w * ) | ( [ ^ \` \~ \! \@ \$ \^ \& \* \( \) \= \+ \[ \{ \] \} \\ \| \; \: \' \" \, \. \< \> \/ \s ] + ) / g,
267287 onEnterRules : [
268288 {
@@ -275,7 +295,7 @@ class LanguageProvider {
275295 action : { indentAction : IndentAction . Indent }
276296 }
277297 ] ,
278- } ) ;
298+ } ) ) ;
279299 } ) ;
280300 }
281301
@@ -364,6 +384,8 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
364384 private client : TypeScriptServiceClient ;
365385 private languages : LanguageProvider [ ] ;
366386 private languagePerId : ObjectMap < LanguageProvider > ;
387+ private configFileWatcher : FileSystemWatcher ;
388+ private readonly disposables : Disposable [ ] = [ ] ;
367389
368390 constructor (
369391 descriptions : LanguageDescription [ ] ,
@@ -380,19 +402,31 @@ class TypeScriptServiceClientHost implements ITypescriptServiceClientHost {
380402 this . triggerAllDiagnostics ( ) ;
381403 } , 1500 ) ;
382404 } ;
383- const watcher = workspace . createFileSystemWatcher ( '**/[tj]sconfig.json' ) ;
384- watcher . onDidCreate ( handleProjectCreateOrDelete ) ;
385- watcher . onDidDelete ( handleProjectCreateOrDelete ) ;
386- watcher . onDidChange ( handleProjectChange ) ;
405+ const configFileWatcher = workspace . createFileSystemWatcher ( '**/[tj]sconfig.json' ) ;
406+ this . disposables . push ( configFileWatcher ) ;
407+ configFileWatcher . onDidCreate ( handleProjectCreateOrDelete , this , this . disposables ) ;
408+ configFileWatcher . onDidDelete ( handleProjectCreateOrDelete , this , this . disposables ) ;
409+ configFileWatcher . onDidChange ( handleProjectChange , this , this . disposables ) ;
387410
388411 this . client = new TypeScriptServiceClient ( this , storagePath , globalState , workspaceState ) ;
389412 this . languages = [ ] ;
390413 this . languagePerId = Object . create ( null ) ;
391- descriptions . forEach ( description => {
414+ for ( const description of descriptions ) {
392415 const manager = new LanguageProvider ( this . client , description ) ;
393416 this . languages . push ( manager ) ;
417+ this . disposables . push ( manager ) ;
394418 this . languagePerId [ description . id ] = manager ;
395- } ) ;
419+ }
420+ }
421+
422+ public dispose ( ) : void {
423+ while ( this . disposables . length ) {
424+ const obj = this . disposables . pop ( ) ;
425+ if ( obj ) {
426+ obj . dispose ( ) ;
427+ }
428+ }
429+ this . configFileWatcher . dispose ( ) ;
396430 }
397431
398432 public get serviceClient ( ) : TypeScriptServiceClient {
0 commit comments