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'
55
66export const DIAGNOSTIC_SOURCE_STR = 'SocketSecurity'
77export const EXTENSION_PREFIX = 'socket-security'
88
9- const SEVERITY_LEVELS = [ 'low' , 'middle' , 'high' , 'critical' ] ;
9+ const SEVERITY_LEVELS = [ 'low' , 'middle' , 'high' , 'critical' ]
1010
1111export function getDiagnosticSeverity ( type : string , severity : string , enforcedRules : IssueRules , issueRules : IssueRules , socketYamlConfig : SocketYml ) : vscode . DiagnosticSeverity | null {
1212 const fullRules : IssueRules = mergeDefaults (
@@ -16,7 +16,7 @@ export function getDiagnosticSeverity(type: string, severity: string, enforcedRu
1616 const editorConfig = vscode . workspace . getConfiguration ( EXTENSION_PREFIX )
1717 const handling = ruleStrength ( fullRules [ type ] )
1818 if ( handling < 2 ) return null
19-
19+
2020 const curLevel = SEVERITY_LEVELS . indexOf ( severity )
2121 const minLevel = SEVERITY_LEVELS . indexOf ( editorConfig . get ( 'minIssueLevel' ) as string )
2222 if ( curLevel >= minLevel ) {
@@ -67,7 +67,7 @@ export function getWorkspaceFolderURI(from: vscode.Uri) {
6767 return vscode . workspace . getWorkspaceFolder ( from ) ?. uri
6868}
6969
70- type ListenerEventData < Data > = { uri : vscode . Uri , data : Data , defaulted : boolean }
70+ type ListenerEventData < Data > = { uri : vscode . Uri , data : Data , defaulted : boolean }
7171/**
7272 * Setup data to be isolated and associated with workspace folders, note: should only be used for data
7373 * 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> {
9393 try {
9494 this . onWorkspaceFolder ( folder . uri )
9595 } catch ( e ) {
96- console . error ( e ) ;
96+ console . error ( e )
9797 }
9898 }
9999 } )
@@ -104,14 +104,14 @@ export class WorkspaceData<Data> {
104104 * @param from Uri within the workspace to recalculate will be used to din the workspace
105105 */
106106 recalculateDataForUri ( from : vscode . Uri , clear : boolean = false ) {
107- const workspaceFolderURI = getWorkspaceFolderURI ( from ) ;
107+ const workspaceFolderURI = getWorkspaceFolderURI ( from )
108108 if ( ! workspaceFolderURI ) {
109- return ;
109+ return
110110 }
111111 if ( clear ) {
112- this . workspaceScopeData . delete ( workspaceFolderURI . fsPath ) ;
112+ this . workspaceScopeData . delete ( workspaceFolderURI . fsPath )
113113 }
114- this . onWorkspaceFolder ( workspaceFolderURI ) ;
114+ this . onWorkspaceFolder ( workspaceFolderURI )
115115 }
116116
117117 /**
@@ -127,7 +127,7 @@ export class WorkspaceData<Data> {
127127 try {
128128 this . onWorkspaceFolder ( folder . uri )
129129 } catch ( e ) {
130- console . error ( e ) ;
130+ console . error ( e )
131131 }
132132 }
133133 }
@@ -138,7 +138,7 @@ export class WorkspaceData<Data> {
138138 data : Data ,
139139 defaulted : boolean ,
140140 } {
141- const workspaceFolderURI = getWorkspaceFolderURI ( from ) ;
141+ const workspaceFolderURI = getWorkspaceFolderURI ( from )
142142 if ( ! workspaceFolderURI ) {
143143 return {
144144 uri : from ,
@@ -156,24 +156,24 @@ export class WorkspaceData<Data> {
156156 }
157157
158158 update ( from : vscode . Uri , value : Data | undefined ) {
159- const workspaceFolderURI = getWorkspaceFolderURI ( from ) ;
159+ const workspaceFolderURI = getWorkspaceFolderURI ( from )
160160 if ( ! workspaceFolderURI ) {
161161 return
162162 }
163163 if ( value !== undefined ) {
164- this . workspaceScopeData . set ( workspaceFolderURI . fsPath , value ) ;
164+ this . workspaceScopeData . set ( workspaceFolderURI . fsPath , value )
165165 } else {
166- this . workspaceScopeData . delete ( workspaceFolderURI . fsPath ) ;
166+ this . workspaceScopeData . delete ( workspaceFolderURI . fsPath )
167167 }
168168 this . fire ( workspaceFolderURI )
169169 }
170170
171171 fire ( uri : vscode . Uri ) {
172- const workspaceFolderURI = getWorkspaceFolderURI ( uri ) ;
172+ const workspaceFolderURI = getWorkspaceFolderURI ( uri )
173173 if ( ! workspaceFolderURI ) {
174174 return
175175 }
176- const data = this . workspaceScopeData . get ( workspaceFolderURI . fsPath ) ;
176+ const data = this . workspaceScopeData . get ( workspaceFolderURI . fsPath )
177177 for ( const listenerData of this . listeners . values ( ) ) {
178178 if ( listenerData . uri === null || ( getWorkspaceFolderURI ( listenerData . uri ) ?. fsPath === workspaceFolderURI . fsPath ) ) {
179179 listenerData . emitter . fire ( {
@@ -188,16 +188,16 @@ export class WorkspaceData<Data> {
188188 on ( from : vscode . Uri | null , fn : ( e : ListenerEventData < Data > ) => void ) : vscode . Disposable {
189189 const {
190190 listeners
191- } = this ;
191+ } = this
192192 let key = from ? from . fsPath : null
193193 let existing = listeners . get ( key ) ?? {
194194 uri : from ,
195195 refCount : 0 ,
196196 emitter : new vscode . EventEmitter ( )
197197 }
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 )
201201 return {
202202 dispose ( ) {
203203 const existing = listeners . get ( key )
@@ -215,24 +215,141 @@ export class WorkspaceData<Data> {
215215}
216216
217217export 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 ) [ ] = [ ]
219219
220220 toml . traverseNodes ( src , {
221221 enterNode ( node ) {
222222 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 ) )
224224 } else if ( node . type === 'TOMLTable' ) {
225- curPath . push ( ...node . resolvedKey ) ;
225+ curPath . push ( ...node . resolvedKey )
226226 } else if ( node . type === 'TOMLKey' ) {
227- cb ( node , curPath ) ;
227+ cb ( node , curPath )
228228 }
229229 } ,
230230 leaveNode ( node ) {
231231 if ( node . type === 'TOMLKeyValue' ) {
232- curPath . length -= node . key . keys . length ;
232+ curPath . length -= node . key . keys . length
233233 } 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 )
235347 }
236348 }
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