1
- import type { SocketYml } from '@socketsecurity/config' ;
2
- import * as toml from 'toml-eslint-parser' ;
3
- import * as vscode from 'vscode' ;
4
- import { IssueRules , mergeDefaults , mergeRules , ruleStrength } from './data/socket-api-config' ;
1
+ import type { SocketYml } from '@socketsecurity/config'
2
+ import * as toml from 'toml-eslint-parser'
3
+ import * as vscode from 'vscode'
4
+ import { IssueRules , mergeDefaults , mergeRules , ruleStrength } from './data/socket-api-config'
5
5
6
6
export const DIAGNOSTIC_SOURCE_STR = 'SocketSecurity'
7
7
export const EXTENSION_PREFIX = 'socket-security'
8
8
9
- const SEVERITY_LEVELS = [ 'low' , 'middle' , 'high' , 'critical' ] ;
9
+ const SEVERITY_LEVELS = [ 'low' , 'middle' , 'high' , 'critical' ]
10
10
11
11
export function getDiagnosticSeverity ( type : string , severity : string , enforcedRules : IssueRules , issueRules : IssueRules , socketYamlConfig : SocketYml ) : vscode . DiagnosticSeverity | null {
12
12
const fullRules : IssueRules = mergeDefaults (
@@ -16,7 +16,7 @@ export function getDiagnosticSeverity(type: string, severity: string, enforcedRu
16
16
const editorConfig = vscode . workspace . getConfiguration ( EXTENSION_PREFIX )
17
17
const handling = ruleStrength ( fullRules [ type ] )
18
18
if ( handling < 2 ) return null
19
-
19
+
20
20
const curLevel = SEVERITY_LEVELS . indexOf ( severity )
21
21
const minLevel = SEVERITY_LEVELS . indexOf ( editorConfig . get ( 'minIssueLevel' ) as string )
22
22
if ( curLevel >= minLevel ) {
@@ -67,7 +67,7 @@ export function getWorkspaceFolderURI(from: vscode.Uri) {
67
67
return vscode . workspace . getWorkspaceFolder ( from ) ?. uri
68
68
}
69
69
70
- type ListenerEventData < Data > = { uri : vscode . Uri , data : Data , defaulted : boolean }
70
+ type ListenerEventData < Data > = { uri : vscode . Uri , data : Data , defaulted : boolean }
71
71
/**
72
72
* Setup data to be isolated and associated with workspace folders, note: should only be used for data
73
73
* DO NOT SETUP listeners inside the callbacks because things like watchers are global and not per workspace
@@ -93,7 +93,7 @@ export class WorkspaceData<Data> {
93
93
try {
94
94
this . onWorkspaceFolder ( folder . uri )
95
95
} catch ( e ) {
96
- console . error ( e ) ;
96
+ console . error ( e )
97
97
}
98
98
}
99
99
} )
@@ -104,14 +104,14 @@ export class WorkspaceData<Data> {
104
104
* @param from Uri within the workspace to recalculate will be used to din the workspace
105
105
*/
106
106
recalculateDataForUri ( from : vscode . Uri , clear : boolean = false ) {
107
- const workspaceFolderURI = getWorkspaceFolderURI ( from ) ;
107
+ const workspaceFolderURI = getWorkspaceFolderURI ( from )
108
108
if ( ! workspaceFolderURI ) {
109
- return ;
109
+ return
110
110
}
111
111
if ( clear ) {
112
- this . workspaceScopeData . delete ( workspaceFolderURI . fsPath ) ;
112
+ this . workspaceScopeData . delete ( workspaceFolderURI . fsPath )
113
113
}
114
- this . onWorkspaceFolder ( workspaceFolderURI ) ;
114
+ this . onWorkspaceFolder ( workspaceFolderURI )
115
115
}
116
116
117
117
/**
@@ -127,7 +127,7 @@ export class WorkspaceData<Data> {
127
127
try {
128
128
this . onWorkspaceFolder ( folder . uri )
129
129
} catch ( e ) {
130
- console . error ( e ) ;
130
+ console . error ( e )
131
131
}
132
132
}
133
133
}
@@ -138,7 +138,7 @@ export class WorkspaceData<Data> {
138
138
data : Data ,
139
139
defaulted : boolean ,
140
140
} {
141
- const workspaceFolderURI = getWorkspaceFolderURI ( from ) ;
141
+ const workspaceFolderURI = getWorkspaceFolderURI ( from )
142
142
if ( ! workspaceFolderURI ) {
143
143
return {
144
144
uri : from ,
@@ -156,24 +156,24 @@ export class WorkspaceData<Data> {
156
156
}
157
157
158
158
update ( from : vscode . Uri , value : Data | undefined ) {
159
- const workspaceFolderURI = getWorkspaceFolderURI ( from ) ;
159
+ const workspaceFolderURI = getWorkspaceFolderURI ( from )
160
160
if ( ! workspaceFolderURI ) {
161
161
return
162
162
}
163
163
if ( value !== undefined ) {
164
- this . workspaceScopeData . set ( workspaceFolderURI . fsPath , value ) ;
164
+ this . workspaceScopeData . set ( workspaceFolderURI . fsPath , value )
165
165
} else {
166
- this . workspaceScopeData . delete ( workspaceFolderURI . fsPath ) ;
166
+ this . workspaceScopeData . delete ( workspaceFolderURI . fsPath )
167
167
}
168
168
this . fire ( workspaceFolderURI )
169
169
}
170
170
171
171
fire ( uri : vscode . Uri ) {
172
- const workspaceFolderURI = getWorkspaceFolderURI ( uri ) ;
172
+ const workspaceFolderURI = getWorkspaceFolderURI ( uri )
173
173
if ( ! workspaceFolderURI ) {
174
174
return
175
175
}
176
- const data = this . workspaceScopeData . get ( workspaceFolderURI . fsPath ) ;
176
+ const data = this . workspaceScopeData . get ( workspaceFolderURI . fsPath )
177
177
for ( const listenerData of this . listeners . values ( ) ) {
178
178
if ( listenerData . uri === null || ( getWorkspaceFolderURI ( listenerData . uri ) ?. fsPath === workspaceFolderURI . fsPath ) ) {
179
179
listenerData . emitter . fire ( {
@@ -188,16 +188,16 @@ export class WorkspaceData<Data> {
188
188
on ( from : vscode . Uri | null , fn : ( e : ListenerEventData < Data > ) => void ) : vscode . Disposable {
189
189
const {
190
190
listeners
191
- } = this ;
191
+ } = this
192
192
let key = from ? from . fsPath : null
193
193
let existing = listeners . get ( key ) ?? {
194
194
uri : from ,
195
195
refCount : 0 ,
196
196
emitter : new vscode . EventEmitter ( )
197
197
}
198
- existing . refCount ++ ;
199
- let unwatch = existing . emitter . event ( fn ) ;
200
- listeners . set ( key , existing ) ;
198
+ existing . refCount ++
199
+ let unwatch = existing . emitter . event ( fn )
200
+ listeners . set ( key , existing )
201
201
return {
202
202
dispose ( ) {
203
203
const existing = listeners . get ( key )
@@ -215,24 +215,141 @@ export class WorkspaceData<Data> {
215
215
}
216
216
217
217
export function traverseTOMLKeys ( src : toml . AST . TOMLProgram , cb : ( key : toml . AST . TOMLKey , path : ( string | number ) [ ] ) => unknown ) {
218
- const curPath : ( string | number ) [ ] = [ ] ;
218
+ const curPath : ( string | number ) [ ] = [ ]
219
219
220
220
toml . traverseNodes ( src , {
221
221
enterNode ( node ) {
222
222
if ( node . type === 'TOMLKeyValue' ) {
223
- curPath . push ( ...node . key . keys . map ( k => k . type == 'TOMLBare' ? k . name : k . value ) ) ;
223
+ curPath . push ( ...node . key . keys . map ( k => k . type == 'TOMLBare' ? k . name : k . value ) )
224
224
} else if ( node . type === 'TOMLTable' ) {
225
- curPath . push ( ...node . resolvedKey ) ;
225
+ curPath . push ( ...node . resolvedKey )
226
226
} else if ( node . type === 'TOMLKey' ) {
227
- cb ( node , curPath ) ;
227
+ cb ( node , curPath )
228
228
}
229
229
} ,
230
230
leaveNode ( node ) {
231
231
if ( node . type === 'TOMLKeyValue' ) {
232
- curPath . length -= node . key . keys . length ;
232
+ curPath . length -= node . key . keys . length
233
233
} else if ( node . type === 'TOMLTable' ) {
234
- curPath . length -= node . resolvedKey . length ;
234
+ curPath . length -= node . resolvedKey . length
235
+ }
236
+ }
237
+ } )
238
+ }
239
+
240
+ export function flattenGlob ( glob : string ) {
241
+ type Item = Alternation | Concatenation | string
242
+ class Alternation {
243
+ alternates : Item [ ]
244
+ constructor ( items : Alternation [ 'alternates' ] = [ ] ) {
245
+ this . alternates = items
246
+ }
247
+ push ( item : Item ) {
248
+ this . alternates . push ( item )
249
+ }
250
+ explode ( ) : string [ ] {
251
+ let options : string [ ] = [ ]
252
+ for ( const alternate of this . alternates ) {
253
+ if ( typeof alternate === 'string' ) {
254
+ options . push ( alternate )
255
+ } else if ( alternate instanceof Concatenation ) {
256
+ options . push ( ...alternate . explode ( ) )
257
+ } else if ( alternate instanceof Alternation ) {
258
+ options . push ( ...alternate . explode ( ) )
259
+ }
260
+ }
261
+ return options
262
+ }
263
+ }
264
+
265
+ class Concatenation {
266
+ segments : Item [ ]
267
+ constructor ( items : Concatenation [ 'segments' ] = [ ] ) {
268
+ this . segments = items
269
+ }
270
+ push ( item : Item ) {
271
+ this . segments . push ( item )
272
+ }
273
+ explode ( ) : string [ ] {
274
+ let prefixed = [ '' ]
275
+ for ( const segment of this . segments ) {
276
+ let suffixes : string [ ]
277
+ if ( typeof segment === 'string' ) {
278
+ suffixes = [ segment ]
279
+ } else if ( segment instanceof Concatenation ) {
280
+ suffixes = segment . explode ( )
281
+ } else if ( segment instanceof Alternation ) {
282
+ suffixes = segment . explode ( )
283
+ } else {
284
+ throw new Error ( 'unreachable' )
285
+ }
286
+ if ( suffixes . length > 0 ) {
287
+ prefixed = prefixed . flatMap ( prefix => {
288
+ return suffixes . map ( suffix => `${ prefix } ${ suffix } ` )
289
+ } )
290
+ }
291
+ }
292
+ return prefixed
293
+ }
294
+ }
295
+
296
+ function explode ( str : string ) {
297
+ let finder = / \\ [ \s \S ] | [ { } , ] / g
298
+ let root = new Concatenation ( )
299
+ let stack : Array < Alternation | Concatenation > = [ root ]
300
+ let right = 0
301
+ let match = finder . exec ( str )
302
+ while ( match ) {
303
+ try {
304
+ let c = match [ 0 ]
305
+ if ( c [ 0 ] === '\\' ) {
306
+ let prefix = str . slice ( right , match . index ) + c
307
+ let current = stack . at ( - 1 ) !
308
+ current . push ( prefix )
309
+ continue
310
+ } else if ( c === '{' ) {
311
+ let prefix = str . slice ( right , match . index )
312
+ let a = new Alternation ( )
313
+ let c = new Concatenation ( )
314
+ let current = stack . at ( - 1 ) !
315
+ current . push ( prefix )
316
+ current . push ( a )
317
+ a . push ( c )
318
+ stack . push ( a )
319
+ stack . push ( c )
320
+ } else if ( c === '}' ) {
321
+ let current = stack . at ( - 1 ) !
322
+ if ( stack . length <= 1 ) {
323
+ current . push ( c )
324
+ continue
325
+ }
326
+ let tail = str . slice ( right , match . index )
327
+ let concat = stack . pop ( ) !
328
+ let alternate = stack . pop ( ) !
329
+ concat . push ( tail )
330
+ } else if ( c === ',' ) {
331
+ let current = stack . at ( - 1 ) !
332
+ if ( stack . length <= 1 ) {
333
+ current . push ( c )
334
+ continue
335
+ }
336
+ let tail = str . slice ( right , match . index )
337
+ let concat = stack . pop ( ) !
338
+ concat . push ( tail )
339
+ let next = new Concatenation ( )
340
+ stack . at ( - 1 ) ! . push ( next )
341
+ stack . push ( next )
342
+ }
343
+ }
344
+ finally {
345
+ right = finder . lastIndex
346
+ match = finder . exec ( str )
235
347
}
236
348
}
237
- } ) ;
238
- }
349
+ let tail = str . slice ( right )
350
+ stack . at ( - 1 ) ! . push ( tail )
351
+ return root . explode ( )
352
+ }
353
+
354
+ return `{${ explode ( glob ) . join ( ',' ) } }`
355
+ }
0 commit comments