@@ -2,75 +2,18 @@ import * as path from 'path';
22import * as React from 'react' ;
33import * as Sarif from 'sarif' ;
44import * as Keys from '../result-keys' ;
5- import { LocationStyle , ResolvableLocationValue } from 'semmle-bqrs' ;
5+ import { LocationStyle } from 'semmle-bqrs' ;
66import * as octicons from './octicons' ;
77import { className , renderLocation , ResultTableProps , zebraStripe , selectableZebraStripe , jumpToLocation } from './result-table-utils' ;
88import { PathTableResultSet , onNavigation , NavigationEvent } from './results' ;
9+ import { parseSarifPlainTextMessage , parseSarifLocation } from '../sarif-utils' ;
910
1011export type PathTableProps = ResultTableProps & { resultSet : PathTableResultSet } ;
1112export interface PathTableState {
1213 expanded : { [ k : string ] : boolean } ;
1314 selectedPathNode : undefined | Keys . PathNode ;
1415}
1516
16- interface SarifLink {
17- dest : number
18- text : string
19- }
20-
21- type ParsedSarifLocation =
22- | ResolvableLocationValue
23- // Resolvable locations have a `file` field, but it will sometimes include
24- // a source location prefix, which contains build-specific information the user
25- // doesn't really need to see. We ensure that `userVisibleFile` will not contain
26- // that, and is appropriate for display in the UI.
27- & { userVisibleFile : string }
28- | { t : 'NoLocation' , hint : string } ;
29-
30- type SarifMessageComponent = string | SarifLink
31-
32- /**
33- * Unescape "[", "]" and "\\" like in sarif plain text messages
34- */
35- function unescapeSarifText ( message : string ) : string {
36- return message . replace ( / \\ \[ / g, "[" ) . replace ( / \\ \] / g, "]" ) . replace ( / \\ \\ / , "\\" ) ;
37- }
38-
39- function parseSarifPlainTextMessage ( message : string ) : SarifMessageComponent [ ] {
40- let results : SarifMessageComponent [ ] = [ ] ;
41-
42- // We want something like "[linkText](4)", except that "[" and "]" may be escaped. The lookbehind asserts
43- // that the initial [ is not escaped. Then we parse a link text with "[" and "]" escaped. Then we parse the numerical target.
44- // Technically we could have any uri in the target but we don't output that yet.
45- // The possibility of escaping outside the link is not mentioned in the sarif spec but we always output sartif this way.
46- const linkRegex = / (?< = (?< ! \\ ) ( \\ \\ ) * ) \[ (?< linkText > ( [ ^ \\ \] \[ ] | \\ \\ | \\ \] | \\ \[ ) * ) \] \( (?< linkTarget > [ 0 - 9 ] + ) \) / g;
47- let result : RegExpExecArray | null ;
48- let curIndex = 0 ;
49- while ( ( result = linkRegex . exec ( message ) ) !== null ) {
50- results . push ( unescapeSarifText ( message . substring ( curIndex , result . index ) ) ) ;
51- const linkText = result . groups ! [ "linkText" ] ;
52- const linkTarget = + result . groups ! [ "linkTarget" ] ;
53- results . push ( { dest : linkTarget , text : unescapeSarifText ( linkText ) } ) ;
54- curIndex = result . index + result [ 0 ] . length ;
55- }
56- results . push ( unescapeSarifText ( message . substring ( curIndex , message . length ) ) ) ;
57- return results ;
58- }
59-
60- /**
61- * Computes a path normalized to reflect conventional normalization
62- * of windows paths into zip archive paths.
63- * @param sourceLocationPrefix The source location prefix of a database. May be
64- * unix style `/foo/bar/baz` or windows-style `C:\foo\bar\baz`.
65- * @param sarifRelativeUri A uri relative to sourceLocationPrefix.
66- * @returns A string that is valid for the `.file` field of a `FivePartLocation`:
67- * directory separators are normalized, but drive letters `C:` may appear.
68- */
69- export function getPathRelativeToSourceLocationPrefix ( sourceLocationPrefix : string , sarifRelativeUui : string ) {
70- const normalizedSourceLocationPrefix = sourceLocationPrefix . replace ( / \\ / g, '/' ) ;
71- return path . join ( normalizedSourceLocationPrefix , decodeURIComponent ( sarifRelativeUui ) ) ;
72- }
73-
7417export class PathTable extends React . Component < PathTableProps , PathTableState > {
7518 constructor ( props : PathTableProps ) {
7619 super ( props ) ;
@@ -323,64 +266,3 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
323266 onNavigation . removeListener ( this . handleNavigationEvent ) ;
324267 }
325268}
326-
327- function parseSarifLocation ( loc : Sarif . Location , sourceLocationPrefix : string ) : ParsedSarifLocation {
328- const physicalLocation = loc . physicalLocation ;
329- if ( physicalLocation === undefined )
330- return { t : 'NoLocation' , hint : 'no physical location' } ;
331- if ( physicalLocation . artifactLocation === undefined )
332- return { t : 'NoLocation' , hint : 'no artifact location' } ;
333- if ( physicalLocation . artifactLocation . uri === undefined )
334- return { t : 'NoLocation' , hint : 'artifact location has no uri' } ;
335-
336- // This is not necessarily really an absolute uri; it could either be a
337- // file uri or a relative uri.
338- const uri = physicalLocation . artifactLocation . uri ;
339-
340- const fileUriRegex = / ^ f i l e : / ;
341- const effectiveLocation = uri . match ( fileUriRegex ) ?
342- decodeURIComponent ( uri . replace ( fileUriRegex , '' ) ) :
343- getPathRelativeToSourceLocationPrefix ( sourceLocationPrefix , uri ) ;
344- const userVisibleFile = uri . match ( fileUriRegex ) ?
345- decodeURIComponent ( uri . replace ( fileUriRegex , '' ) ) :
346- uri ;
347-
348- if ( physicalLocation . region === undefined ) {
349- // If the region property is absent, the physicalLocation object refers to the entire file.
350- // Source: https://docs.oasis-open.org/sarif/sarif/v2.1.0/cs01/sarif-v2.1.0-cs01.html#_Toc16012638.
351- // TODO: Do we get here if we provide a non-filesystem URL?
352- return {
353- t : LocationStyle . WholeFile ,
354- file : effectiveLocation ,
355- userVisibleFile,
356- } ;
357- } else {
358- const region = physicalLocation . region ;
359- // We assume that the SARIF we're given always has startLine
360- // This is not mandated by the SARIF spec, but should be true of
361- // SARIF output by our own tools.
362- const lineStart = region . startLine ! ;
363-
364- // These defaults are from SARIF 2.1.0 spec, section 3.30.2, "Text Regions"
365- // https://docs.oasis-open.org/sarif/sarif/v2.1.0/cs01/sarif-v2.1.0-cs01.html#_Ref493492556
366- const lineEnd = region . endLine === undefined ? lineStart : region . endLine ;
367- const colStart = region . startColumn === undefined ? 1 : region . startColumn ;
368-
369- // We also assume that our tools will always supply `endColumn` field, which is
370- // fortunate, since the SARIF spec says that it defaults to the end of the line, whose
371- // length we don't know at this point in the code.
372- //
373- // It is off by one with respect to the way vscode counts columns in selections.
374- const colEnd = region . endColumn ! - 1 ;
375-
376- return {
377- t : LocationStyle . FivePart ,
378- file : effectiveLocation ,
379- userVisibleFile,
380- lineStart,
381- colStart,
382- lineEnd,
383- colEnd,
384- } ;
385- }
386- }
0 commit comments