@@ -56,6 +56,8 @@ export class SemanticHighlightingFeature implements vscodelc.StaticFeature {
56
56
scopeLookupTable : string [ ] [ ] ;
57
57
// The object that applies the highlightings clangd sends.
58
58
highlighter : Highlighter ;
59
+ // Any disposables that should be cleaned up when clangd crashes.
60
+ private subscriptions : vscode . Disposable [ ] = [ ] ;
59
61
fillClientCapabilities ( capabilities : vscodelc . ClientCapabilities ) {
60
62
// Extend the ClientCapabilities type and add semantic highlighting
61
63
// capability to the object.
@@ -88,21 +90,27 @@ export class SemanticHighlightingFeature implements vscodelc.StaticFeature {
88
90
// otherwise it could try to update the themeRuleMatcher without the
89
91
// highlighter being created.
90
92
this . highlighter = new Highlighter ( this . scopeLookupTable ) ;
93
+ this . subscriptions . push ( vscode . Disposable . from ( this . highlighter ) ) ;
91
94
this . loadCurrentTheme ( ) ;
92
95
// Event handling for handling with TextDocuments/Editors lifetimes.
93
- vscode . window . onDidChangeVisibleTextEditors (
96
+ this . subscriptions . push ( vscode . window . onDidChangeVisibleTextEditors (
94
97
( editors : vscode . TextEditor [ ] ) =>
95
98
editors . forEach ( ( e ) => this . highlighter . applyHighlights (
96
- e . document . uri . toString ( ) ) ) ) ;
97
- vscode . workspace . onDidCloseTextDocument (
98
- ( doc ) => this . highlighter . removeFileHighlightings ( doc . uri . toString ( ) ) ) ;
99
+ e . document . uri . toString ( ) ) ) ) ) ;
100
+ this . subscriptions . push ( vscode . workspace . onDidCloseTextDocument (
101
+ ( doc ) => this . highlighter . removeFileHighlightings ( doc . uri . toString ( ) ) ) ) ;
99
102
}
100
103
101
104
handleNotification ( params : SemanticHighlightingParams ) {
102
105
const lines : SemanticHighlightingLine [ ] = params . lines . map (
103
106
( line ) => ( { line : line . line , tokens : decodeTokens ( line . tokens ) } ) ) ;
104
107
this . highlighter . highlight ( params . textDocument . uri , lines ) ;
105
108
}
109
+ // Disposes of all disposable resources used by this object.
110
+ public dispose ( ) {
111
+ this . subscriptions . forEach ( ( d ) => d . dispose ( ) ) ;
112
+ this . subscriptions = [ ] ;
113
+ }
106
114
}
107
115
108
116
// Converts a string of base64 encoded tokens into the corresponding array of
@@ -138,6 +146,13 @@ export class Highlighter {
138
146
constructor ( scopeLookupTable : string [ ] [ ] ) {
139
147
this . scopeLookupTable = scopeLookupTable ;
140
148
}
149
+ public dispose ( ) {
150
+ this . files . clear ( ) ;
151
+ this . decorationTypes . forEach ( ( t ) => t . dispose ( ) ) ;
152
+ // Dispose must not be not called multiple times if initialize is
153
+ // called again.
154
+ this . decorationTypes = [ ] ;
155
+ }
141
156
// This function must be called at least once or no highlightings will be
142
157
// done. Sets the theme that is used when highlighting. Also triggers a
143
158
// recolorization for all current highlighters. Should be called whenever the
@@ -174,6 +189,27 @@ export class Highlighter {
174
189
this . applyHighlights ( fileUri ) ;
175
190
}
176
191
192
+ // Applies all the highlightings currently stored for a file with fileUri.
193
+ public applyHighlights ( fileUri : string ) {
194
+ if ( ! this . files . has ( fileUri ) )
195
+ // There are no highlightings for this file, must return early or will get
196
+ // out of bounds when applying the decorations below.
197
+ return ;
198
+ if ( ! this . decorationTypes . length )
199
+ // Can't apply any decorations when there is no theme loaded.
200
+ return ;
201
+ // This must always do a full re-highlighting due to the fact that
202
+ // TextEditorDecorationType are very expensive to create (which makes
203
+ // incremental updates infeasible). For this reason one
204
+ // TextEditorDecorationType is used per scope.
205
+ const ranges = this . getDecorationRanges ( fileUri ) ;
206
+ vscode . window . visibleTextEditors . forEach ( ( e ) => {
207
+ if ( e . document . uri . toString ( ) !== fileUri )
208
+ return ;
209
+ this . decorationTypes . forEach ( ( d , i ) => e . setDecorations ( d , ranges [ i ] ) ) ;
210
+ } ) ;
211
+ }
212
+
177
213
// Called when a text document is closed. Removes any highlighting entries for
178
214
// the text document that was closed.
179
215
public removeFileHighlightings ( fileUri : string ) {
@@ -207,27 +243,6 @@ export class Highlighter {
207
243
} ) ;
208
244
return decorations ;
209
245
}
210
-
211
- // Applies all the highlightings currently stored for a file with fileUri.
212
- public applyHighlights ( fileUri : string ) {
213
- if ( ! this . files . has ( fileUri ) )
214
- // There are no highlightings for this file, must return early or will get
215
- // out of bounds when applying the decorations below.
216
- return ;
217
- if ( ! this . decorationTypes . length )
218
- // Can't apply any decorations when there is no theme loaded.
219
- return ;
220
- // This must always do a full re-highlighting due to the fact that
221
- // TextEditorDecorationType are very expensive to create (which makes
222
- // incremental updates infeasible). For this reason one
223
- // TextEditorDecorationType is used per scope.
224
- const ranges = this . getDecorationRanges ( fileUri ) ;
225
- vscode . window . visibleTextEditors . forEach ( ( e ) => {
226
- if ( e . document . uri . toString ( ) !== fileUri )
227
- return ;
228
- this . decorationTypes . forEach ( ( d , i ) => e . setDecorations ( d , ranges [ i ] ) ) ;
229
- } ) ;
230
- }
231
246
}
232
247
233
248
// A rule for how to color TextMate scopes.
0 commit comments