1- import { basename } from "path" ;
21import * as React from "react" ;
32import * as Sarif from "sarif" ;
43import * as Keys from "./result-keys" ;
54import { chevronDown , chevronRight , info , listUnordered } from "./octicons" ;
65import {
76 className ,
8- renderLocation ,
97 ResultTableProps ,
108 selectableZebraStripe ,
119 jumpToLocation ,
@@ -18,15 +16,11 @@ import {
1816 NavigationDirection ,
1917 SarifInterpretationData ,
2018} from "../../common/interface-types" ;
21- import {
22- parseSarifPlainTextMessage ,
23- parseSarifLocation ,
24- isNoLocation ,
25- } from "../../common/sarif-utils" ;
26- import { isWholeFileLoc , isLineColumnLoc } from "../../common/bqrs-utils" ;
19+ import { parseSarifLocation , isNoLocation } from "../../common/sarif-utils" ;
2720import { ScrollIntoViewHelper } from "./scroll-into-view-helper" ;
2821import { sendTelemetry } from "../common/telemetry" ;
2922import { AlertTableHeader } from "./alert-table-header" ;
23+ import { SarifLocation , SarifMessageWithLocations } from "./locations" ;
3024
3125export type AlertTableProps = ResultTableProps & {
3226 resultSet : InterpretedResultSet < SarifInterpretationData > ;
@@ -100,41 +94,6 @@ export class AlertTable extends React.Component<
10094 const { numTruncatedResults, sourceLocationPrefix } =
10195 resultSet . interpretation ;
10296
103- function renderRelatedLocations (
104- msg : string ,
105- relatedLocations : Sarif . Location [ ] ,
106- resultKey : Keys . PathNode | Keys . Result | undefined ,
107- ) : JSX . Element [ ] {
108- const relatedLocationsById : { [ k : string ] : Sarif . Location } = { } ;
109- for ( const loc of relatedLocations ) {
110- relatedLocationsById [ loc . id ! ] = loc ;
111- }
112-
113- // match things like `[link-text](related-location-id)`
114- const parts = parseSarifPlainTextMessage ( msg ) ;
115-
116- return parts . map ( ( part , i ) => {
117- if ( typeof part === "string" ) {
118- return < span key = { i } > { part } </ span > ;
119- } else {
120- const renderedLocation = renderSarifLocationWithText (
121- part . text ,
122- relatedLocationsById [ part . dest ] ,
123- resultKey ,
124- ) ;
125- return < span key = { i } > { renderedLocation } </ span > ;
126- }
127- } ) ;
128- }
129-
130- function renderNonLocation (
131- msg : string | undefined ,
132- locationHint : string ,
133- ) : JSX . Element | undefined {
134- if ( msg === undefined ) return undefined ;
135- return < span title = { locationHint } > { msg } </ span > ;
136- }
137-
13897 const updateSelectionCallback = (
13998 resultKey : Keys . PathNode | Keys . Result | undefined ,
14099 ) => {
@@ -147,65 +106,6 @@ export class AlertTable extends React.Component<
147106 } ;
148107 } ;
149108
150- function renderSarifLocationWithText (
151- text : string | undefined ,
152- loc : Sarif . Location ,
153- resultKey : Keys . PathNode | Keys . Result | undefined ,
154- ) : JSX . Element | undefined {
155- const parsedLoc = parseSarifLocation ( loc , sourceLocationPrefix ) ;
156- if ( "hint" in parsedLoc ) {
157- return renderNonLocation ( text , parsedLoc . hint ) ;
158- } else if ( isWholeFileLoc ( parsedLoc ) || isLineColumnLoc ( parsedLoc ) ) {
159- return renderLocation (
160- parsedLoc ,
161- text ,
162- databaseUri ,
163- undefined ,
164- updateSelectionCallback ( resultKey ) ,
165- ) ;
166- } else {
167- return undefined ;
168- }
169- }
170-
171- /**
172- * Render sarif location as a link with the text being simply a
173- * human-readable form of the location itself.
174- */
175- function renderSarifLocation (
176- loc : Sarif . Location ,
177- pathNodeKey : Keys . PathNode | Keys . Result | undefined ,
178- ) : JSX . Element | undefined {
179- const parsedLoc = parseSarifLocation ( loc , sourceLocationPrefix ) ;
180- if ( "hint" in parsedLoc ) {
181- return renderNonLocation ( "[no location]" , parsedLoc . hint ) ;
182- } else if ( isWholeFileLoc ( parsedLoc ) ) {
183- const shortLocation = `${ basename ( parsedLoc . userVisibleFile ) } ` ;
184- const longLocation = `${ parsedLoc . userVisibleFile } ` ;
185- return renderLocation (
186- parsedLoc ,
187- shortLocation ,
188- databaseUri ,
189- longLocation ,
190- updateSelectionCallback ( pathNodeKey ) ,
191- ) ;
192- } else if ( isLineColumnLoc ( parsedLoc ) ) {
193- const shortLocation = `${ basename ( parsedLoc . userVisibleFile ) } :${
194- parsedLoc . startLine
195- } :${ parsedLoc . startColumn } `;
196- const longLocation = `${ parsedLoc . userVisibleFile } ` ;
197- return renderLocation (
198- parsedLoc ,
199- shortLocation ,
200- databaseUri ,
201- longLocation ,
202- updateSelectionCallback ( pathNodeKey ) ,
203- ) ;
204- } else {
205- return undefined ;
206- }
207- }
208-
209109 const toggler : ( keys : Keys . ResultKey [ ] ) => ( e : React . MouseEvent ) => void = (
210110 indices ,
211111 ) => {
@@ -220,19 +120,32 @@ export class AlertTable extends React.Component<
220120 ( result , resultIndex ) => {
221121 const resultKey : Keys . Result = { resultIndex } ;
222122 const text = result . message . text || "[no text]" ;
223- const msg : JSX . Element [ ] =
224- result . relatedLocations === undefined
225- ? [ < span key = "0" > { text } </ span > ]
226- : renderRelatedLocations ( text , result . relatedLocations , resultKey ) ;
123+ const msg =
124+ result . relatedLocations === undefined ? (
125+ < span key = "0" > { text } </ span >
126+ ) : (
127+ < SarifMessageWithLocations
128+ msg = { text }
129+ relatedLocations = { result . relatedLocations }
130+ sourceLocationPrefix = { sourceLocationPrefix }
131+ databaseUri = { databaseUri }
132+ jumpToLocationCallback = { updateSelectionCallback ( resultKey ) }
133+ />
134+ ) ;
227135
228136 const currentResultExpanded = this . state . expanded . has (
229137 Keys . keyToString ( resultKey ) ,
230138 ) ;
231139 const indicator = currentResultExpanded ? chevronDown : chevronRight ;
232- const location =
233- result . locations !== undefined &&
234- result . locations . length > 0 &&
235- renderSarifLocation ( result . locations [ 0 ] , resultKey ) ;
140+ const location = result . locations !== undefined &&
141+ result . locations . length > 0 && (
142+ < SarifLocation
143+ loc = { result . locations [ 0 ] }
144+ sourceLocationPrefix = { sourceLocationPrefix }
145+ databaseUri = { databaseUri }
146+ jumpToLocationCallback = { updateSelectionCallback ( resultKey ) }
147+ />
148+ ) ;
236149 const locationCells = (
237150 < td className = "vscode-codeql__location-cell" > { location } </ td >
238151 ) ;
@@ -342,17 +255,32 @@ export class AlertTable extends React.Component<
342255 const step = pathNodes [ pathNodeIndex ] ;
343256 const msg =
344257 step . location !== undefined &&
345- step . location . message !== undefined
346- ? renderSarifLocationWithText (
347- step . location . message . text ,
348- step . location ,
258+ step . location . message !== undefined ? (
259+ < SarifLocation
260+ text = { step . location . message . text }
261+ loc = { step . location }
262+ sourceLocationPrefix = { sourceLocationPrefix }
263+ databaseUri = { databaseUri }
264+ jumpToLocationCallback = { updateSelectionCallback (
349265 pathNodeKey ,
350- )
351- : "[no location]" ;
266+ ) }
267+ />
268+ ) : (
269+ "[no location]"
270+ ) ;
352271 const additionalMsg =
353- step . location !== undefined
354- ? renderSarifLocation ( step . location , pathNodeKey )
355- : "" ;
272+ step . location !== undefined ? (
273+ < SarifLocation
274+ loc = { step . location }
275+ sourceLocationPrefix = { sourceLocationPrefix }
276+ databaseUri = { databaseUri }
277+ jumpToLocationCallback = { updateSelectionCallback (
278+ pathNodeKey ,
279+ ) }
280+ />
281+ ) : (
282+ ""
283+ ) ;
356284 const isSelected = Keys . equalsNotUndefined (
357285 this . state . selectedItem ,
358286 pathNodeKey ,
0 commit comments