@@ -5,7 +5,7 @@ import * as Keys from '../../pure/result-keys';
55import * as octicons from './octicons' ;
66import { className , renderLocation , ResultTableProps , zebraStripe , selectableZebraStripe , jumpToLocation , nextSortDirection , emptyQueryResultsMessage } from './result-table-utils' ;
77import { onNavigation , NavigationEvent } from './results' ;
8- import { InterpretedResultSet , SarifInterpretationData } from '../../pure/interface-types' ;
8+ import { InterpretedResultSet , NavigateAlertMsg , NavigatePathMsg , SarifInterpretationData } from '../../pure/interface-types' ;
99import {
1010 parseSarifPlainTextMessage ,
1111 parseSarifLocation ,
@@ -18,13 +18,13 @@ import { isWholeFileLoc, isLineColumnLoc } from '../../pure/bqrs-utils';
1818export type PathTableProps = ResultTableProps & { resultSet : InterpretedResultSet < SarifInterpretationData > } ;
1919export interface PathTableState {
2020 expanded : { [ k : string ] : boolean } ;
21- selectedPathNode : undefined | Keys . PathNode ;
21+ selectedItem : undefined | Keys . PathNode | Keys . Result ;
2222}
2323
2424export class PathTable extends React . Component < PathTableProps , PathTableState > {
2525 constructor ( props : PathTableProps ) {
2626 super ( props ) ;
27- this . state = { expanded : { } , selectedPathNode : undefined } ;
27+ this . state = { expanded : { } , selectedItem : undefined } ;
2828 this . handleNavigationEvent = this . handleNavigationEvent . bind ( this ) ;
2929 }
3030
@@ -96,7 +96,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
9696 const rows : JSX . Element [ ] = [ ] ;
9797 const { numTruncatedResults, sourceLocationPrefix } = resultSet . interpretation ;
9898
99- function renderRelatedLocations ( msg : string , relatedLocations : Sarif . Location [ ] ) : JSX . Element [ ] {
99+ function renderRelatedLocations ( msg : string , relatedLocations : Sarif . Location [ ] , resultKey : Keys . PathNode | Keys . Result | undefined ) : JSX . Element [ ] {
100100 const relatedLocationsById : { [ k : string ] : Sarif . Location } = { } ;
101101 for ( const loc of relatedLocations ) {
102102 relatedLocationsById [ loc . id ! ] = loc ;
@@ -110,7 +110,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
110110 return < span key = { i } > { part } </ span > ;
111111 } else {
112112 const renderedLocation = renderSarifLocationWithText ( part . text , relatedLocationsById [ part . dest ] ,
113- undefined ) ;
113+ resultKey ) ;
114114 return < span key = { i } > { renderedLocation } </ span > ;
115115 }
116116 } ) ;
@@ -122,16 +122,16 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
122122 return < span title = { locationHint } > { msg } </ span > ;
123123 }
124124
125- const updateSelectionCallback = ( pathNodeKey : Keys . PathNode | undefined ) => {
125+ const updateSelectionCallback = ( resultKey : Keys . PathNode | Keys . Result | undefined ) => {
126126 return ( ) => {
127127 this . setState ( previousState => ( {
128128 ...previousState ,
129- selectedPathNode : pathNodeKey
129+ selectedItem : resultKey
130130 } ) ) ;
131131 } ;
132132 } ;
133133
134- function renderSarifLocationWithText ( text : string | undefined , loc : Sarif . Location , pathNodeKey : Keys . PathNode | undefined ) : JSX . Element | undefined {
134+ function renderSarifLocationWithText ( text : string | undefined , loc : Sarif . Location , resultKey : Keys . PathNode | Keys . Result | undefined ) : JSX . Element | undefined {
135135 const parsedLoc = parseSarifLocation ( loc , sourceLocationPrefix ) ;
136136 if ( 'hint' in parsedLoc ) {
137137 return renderNonLocation ( text , parsedLoc . hint ) ;
@@ -141,7 +141,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
141141 text ,
142142 databaseUri ,
143143 undefined ,
144- updateSelectionCallback ( pathNodeKey )
144+ updateSelectionCallback ( resultKey )
145145 ) ;
146146 } else {
147147 return undefined ;
@@ -154,7 +154,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
154154 */
155155 function renderSarifLocation (
156156 loc : Sarif . Location ,
157- pathNodeKey : Keys . PathNode | undefined
157+ pathNodeKey : Keys . PathNode | Keys . Result | undefined
158158 ) : JSX . Element | undefined {
159159 const parsedLoc = parseSarifLocation ( loc , sourceLocationPrefix ) ;
160160 if ( 'hint' in parsedLoc ) {
@@ -195,21 +195,25 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
195195 let expansionIndex = 0 ;
196196
197197 resultSet . interpretation . data . runs [ 0 ] . results . forEach ( ( result , resultIndex ) => {
198+ const resultKey : Keys . Result = { resultIndex } ;
198199 const text = result . message . text || '[no text]' ;
199200 const msg : JSX . Element [ ] =
200201 result . relatedLocations === undefined ?
201202 [ < span key = "0" > { text } </ span > ] :
202- renderRelatedLocations ( text , result . relatedLocations ) ;
203+ renderRelatedLocations ( text , result . relatedLocations , resultKey ) ;
203204
204205 const currentResultExpanded = this . state . expanded [ expansionIndex ] ;
205206 const indicator = currentResultExpanded ? octicons . chevronDown : octicons . chevronRight ;
206207 const location = result . locations !== undefined && result . locations . length > 0 &&
207- renderSarifLocation ( result . locations [ 0 ] , Keys . none ) ;
208+ renderSarifLocation ( result . locations [ 0 ] , resultKey ) ;
208209 const locationCells = < td className = "vscode-codeql__location-cell" > { location } </ td > ;
209210
211+ const selectedItem = this . state . selectedItem ;
212+ const resultRowIsSelected = selectedItem ?. resultIndex === resultIndex && selectedItem . pathIndex === undefined ;
213+
210214 if ( result . codeFlows === undefined ) {
211215 rows . push (
212- < tr key = { resultIndex } { ...zebraStripe ( resultIndex ) } >
216+ < tr key = { resultIndex } { ...selectableZebraStripe ( resultRowIsSelected , resultIndex ) } >
213217 < td className = "vscode-codeql__icon-cell" > { octicons . info } </ td >
214218 < td colSpan = { 3 } > { msg } </ td >
215219 { locationCells }
@@ -225,7 +229,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
225229 [ expansionIndex ] ;
226230
227231 rows . push (
228- < tr { ...zebraStripe ( resultIndex ) } key = { resultIndex } >
232+ < tr { ...selectableZebraStripe ( resultRowIsSelected , resultIndex ) } key = { resultIndex } >
229233 < td className = "vscode-codeql__icon-cell vscode-codeql__dropdown-cell" onMouseDown = { toggler ( indices ) } >
230234 { indicator }
231235 </ td >
@@ -268,7 +272,7 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
268272 const additionalMsg = step . location !== undefined ?
269273 renderSarifLocation ( step . location , pathNodeKey ) :
270274 '' ;
271- const isSelected = Keys . equalsNotUndefined ( this . state . selectedPathNode , pathNodeKey ) ;
275+ const isSelected = Keys . equalsNotUndefined ( this . state . selectedItem , pathNodeKey ) ;
272276 const stepIndex = pathNodeIndex + 1 ; // Convert to 1-based
273277 const zebraIndex = resultIndex + stepIndex ;
274278 rows . push (
@@ -303,14 +307,33 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
303307 }
304308
305309 private handleNavigationEvent ( event : NavigationEvent ) {
310+ switch ( event . t ) {
311+ case 'navigatePath' : {
312+ this . handleNavigatePathStepEvent ( event ) ;
313+ break ;
314+ }
315+ case 'navigateAlert' : {
316+ this . handleNavigateAlertEvent ( event ) ;
317+ break ;
318+ }
319+ }
320+ }
321+
322+ private handleNavigatePathStepEvent ( event : NavigatePathMsg ) {
306323 this . setState ( prevState => {
307- const { selectedPathNode } = prevState ;
308- if ( selectedPathNode === undefined ) return prevState ;
324+ const { selectedItem } = prevState ;
325+ if ( selectedItem === undefined ) return prevState ;
309326
310- const path = Keys . getPath ( this . props . resultSet . interpretation . data , selectedPathNode ) ;
327+ const selectedPath = selectedItem . pathIndex !== undefined
328+ ? selectedItem
329+ : { ...selectedItem , pathIndex : 0 } ;
330+
331+ const path = Keys . getPath ( this . props . resultSet . interpretation . data , selectedPath ) ;
311332 if ( path === undefined ) return prevState ;
312333
313- const nextIndex = selectedPathNode . pathNodeIndex + event . direction ;
334+ const nextIndex = selectedItem . pathNodeIndex !== undefined
335+ ? ( selectedItem . pathNodeIndex + event . direction )
336+ : 0 ;
314337 if ( nextIndex < 0 || nextIndex >= path . locations . length ) return prevState ;
315338
316339 const sarifLoc = path . locations [ nextIndex ] . location ;
@@ -324,8 +347,35 @@ export class PathTable extends React.Component<PathTableProps, PathTableState> {
324347 }
325348
326349 jumpToLocation ( loc , this . props . databaseUri ) ;
327- const newSelection = { ...selectedPathNode , pathNodeIndex : nextIndex } ;
328- return { ...prevState , selectedPathNode : newSelection } ;
350+ const newSelection = { ...selectedPath , pathNodeIndex : nextIndex } ;
351+ return { ...prevState , selectedItem : newSelection } ;
352+ } ) ;
353+ }
354+
355+ private handleNavigateAlertEvent ( event : NavigateAlertMsg ) {
356+ this . setState ( prevState => {
357+ const { selectedItem } = prevState ;
358+ if ( selectedItem === undefined ) return prevState ;
359+
360+ const nextIndex = selectedItem . resultIndex + event . direction ;
361+ const nextSelection = { resultIndex : nextIndex } ;
362+ const result = Keys . getResult ( this . props . resultSet . interpretation . data , nextSelection ) ;
363+ if ( result === undefined ) {
364+ return prevState ;
365+ }
366+
367+ const sarifLoc = result . locations ?. [ 0 ] ;
368+ if ( sarifLoc === undefined ) {
369+ return prevState ;
370+ }
371+
372+ const loc = parseSarifLocation ( sarifLoc , this . props . resultSet . interpretation . sourceLocationPrefix ) ;
373+ if ( isNoLocation ( loc ) ) {
374+ return prevState ;
375+ }
376+
377+ jumpToLocation ( loc , this . props . databaseUri ) ;
378+ return { ...prevState , selectedItem : nextSelection } ;
329379 } ) ;
330380 }
331381
0 commit comments