@@ -7,14 +7,16 @@ import { logger } from './extension';
7
7
import { GnatTaskProvider } from './gnatTaskProvider' ;
8
8
import { initializeTesting } from './gnattest' ;
9
9
import { GprTaskProvider } from './gprTaskProvider' ;
10
- import { TERMINAL_ENV_SETTING_NAME } from './helpers' ;
10
+ import { getArgValue , TERMINAL_ENV_SETTING_NAME } from './helpers' ;
11
11
import {
12
+ SimpleTaskDef ,
12
13
SimpleTaskProvider ,
13
14
TASK_TYPE_ADA ,
14
15
TASK_TYPE_SPARK ,
15
16
createAdaTaskProvider ,
16
17
createSparkTaskProvider ,
17
18
} from './taskProviders' ;
19
+ import { isAbsolute } from 'path' ;
18
20
19
21
/**
20
22
* This class encapsulates all state that should be maintained throughout the
@@ -36,7 +38,7 @@ export class ExtensionState {
36
38
} ;
37
39
public readonly initialDebugConfigProvider : AdaInitialDebugConfigProvider ;
38
40
39
- private registeredTaskProviders : Disposable [ ] ;
41
+ private taskDisposables : Disposable [ ] ;
40
42
41
43
public readonly codelensProvider = new AdaCodeLensProvider ( ) ;
42
44
public readonly testController : vscode . TestController ;
@@ -78,7 +80,7 @@ export class ExtensionState {
78
80
[ ] ,
79
81
'**/.{adb,ads,adc,ada}'
80
82
) ;
81
- this . registeredTaskProviders = [ ] ;
83
+ this . taskDisposables = [ ] ;
82
84
const result = initializeDebugging ( this . context ) ;
83
85
this . initialDebugConfigProvider = result . providerInitial ;
84
86
this . dynamicDebugConfigProvider = result . providerDynamic ;
@@ -87,36 +89,51 @@ export class ExtensionState {
87
89
88
90
public start = async ( ) => {
89
91
await Promise . all ( [ this . gprClient . start ( ) , this . adaClient . start ( ) ] ) ;
90
- this . registerTaskProviders ( ) ;
92
+ this . registerTaskDisposables ( ) ;
91
93
this . context . subscriptions . push (
92
94
vscode . languages . registerCodeLensProvider ( 'ada' , this . codelensProvider )
93
95
) ;
94
96
} ;
95
97
96
98
public dispose = ( ) => {
97
- this . unregisterTaskProviders ( ) ;
99
+ this . unregisterTaskDisposables ( ) ;
98
100
} ;
99
101
100
- public registerTaskProviders = ( ) : void => {
102
+ /**
103
+ * Register all the task disposables needed by the extension (e.g: task providers,
104
+ * listeners...).
105
+ */
106
+ public registerTaskDisposables = ( ) : void => {
101
107
this . adaTaskProvider = createAdaTaskProvider ( ) ;
102
108
this . sparkTaskProvider = createSparkTaskProvider ( ) ;
103
109
104
- this . registeredTaskProviders = [
110
+ this . taskDisposables = [
105
111
vscode . tasks . registerTaskProvider ( GnatTaskProvider . gnatType , new GnatTaskProvider ( ) ) ,
106
112
vscode . tasks . registerTaskProvider (
107
113
GprTaskProvider . gprTaskType ,
108
114
new GprTaskProvider ( this . adaClient )
109
115
) ,
110
116
vscode . tasks . registerTaskProvider ( TASK_TYPE_ADA , this . adaTaskProvider ) ,
111
117
vscode . tasks . registerTaskProvider ( TASK_TYPE_SPARK , this . sparkTaskProvider ) ,
118
+
119
+ // Add a listener on tasks to open the SARIF Viewer when the
120
+ // task that ends outputs a SARIF file.
121
+ vscode . tasks . onDidEndTaskProcess ( async ( e ) => {
122
+ const task = e . execution . task ;
123
+ await openSARIFViewerIfNeeded ( task ) ;
124
+ } ) ,
112
125
] ;
113
126
} ;
114
127
115
- public unregisterTaskProviders = ( ) : void => {
116
- for ( const item of this . registeredTaskProviders ) {
128
+ /**
129
+ * Unregister all the task disposables needed by the extension (e.g: task providers,
130
+ * listeners...).
131
+ */
132
+ public unregisterTaskDisposables = ( ) : void => {
133
+ for ( const item of this . taskDisposables ) {
117
134
item . dispose ( ) ;
118
135
}
119
- this . registeredTaskProviders = [ ] ;
136
+ this . taskDisposables = [ ] ;
120
137
} ;
121
138
122
139
/**
@@ -150,8 +167,8 @@ export class ExtensionState {
150
167
) {
151
168
logger . info ( 'project related settings have changed: clearing caches for tasks' ) ;
152
169
this . clearALSCache ( ) ;
153
- this . unregisterTaskProviders ( ) ;
154
- this . registerTaskProviders ( ) ;
170
+ this . unregisterTaskDisposables ( ) ;
171
+ this . registerTaskDisposables ( ) ;
155
172
}
156
173
157
174
// React to changes made in the environment variables, showing
@@ -239,3 +256,62 @@ export class ExtensionState {
239
256
return this . sparkTaskProvider ;
240
257
}
241
258
}
259
+
260
+ /**
261
+ *
262
+ * Open the SARIF Viewer if the given task outputs its results in
263
+ * a SARIF file (e.g: GNAT SAS Report task).
264
+ */
265
+ async function openSARIFViewerIfNeeded ( task : vscode . Task ) {
266
+ const definition : SimpleTaskDef = task . definition ;
267
+
268
+ if ( definition ) {
269
+ const args = definition . args ;
270
+
271
+ if ( args ?. some ( ( arg ) => getArgValue ( arg ) . includes ( 'sarif' ) ) ) {
272
+ const execution = task . execution ;
273
+ let cwd = undefined ;
274
+
275
+ if ( execution && execution instanceof vscode . ShellExecution ) {
276
+ cwd = execution . options ?. cwd ;
277
+ }
278
+
279
+ if ( ! cwd && vscode . workspace . workspaceFolders ) {
280
+ cwd = vscode . workspace . workspaceFolders [ 0 ] . uri . fsPath ;
281
+ }
282
+
283
+ const sarifExt = vscode . extensions . getExtension ( 'ms-sarifvscode.sarif-viewer' ) ;
284
+
285
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
286
+ const sarifExtAPI = sarifExt ? await sarifExt . activate ( ) : undefined ;
287
+
288
+ if ( cwd && sarifExtAPI ) {
289
+ const cwdURI = vscode . Uri . file ( cwd ) ;
290
+ const outputFilePathArgRaw = args . find ( ( arg ) =>
291
+ getArgValue ( arg ) . includes ( '.sarif' )
292
+ ) ;
293
+
294
+ if ( outputFilePathArgRaw ) {
295
+ // Convert the raw argument into a string
296
+ const outputFilePathArg = getArgValue ( outputFilePathArgRaw ) ;
297
+
298
+ // The SARIF output file can be specified as '--output=path/to/file.sarif':
299
+ // split the argument on '=' if that's the case, to retrieve only the file path
300
+ const outputFilePath = outputFilePathArg . includes ( '=' )
301
+ ? outputFilePathArg . split ( '=' ) . pop ( )
302
+ : outputFilePathArg ;
303
+
304
+ if ( outputFilePath ) {
305
+ const sarifFileURI = isAbsolute ( outputFilePath )
306
+ ? vscode . Uri . file ( outputFilePath )
307
+ : vscode . Uri . joinPath ( cwdURI , outputFilePath ) ;
308
+
309
+ // eslint-disable-next-line max-len
310
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
311
+ await sarifExtAPI . openLogs ( [ sarifFileURI ] ) ;
312
+ }
313
+ }
314
+ }
315
+ }
316
+ }
317
+ }
0 commit comments