Skip to content

Commit 7e31b6e

Browse files
Construct rows using maps instead of mutating array from multiple places
1 parent cff7170 commit 7e31b6e

1 file changed

Lines changed: 189 additions & 181 deletions

File tree

extensions/ql-vscode/src/view/results/AlertTable.tsx

Lines changed: 189 additions & 181 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ export class AlertTable extends React.Component<
7373
render(): JSX.Element {
7474
const { databaseUri, resultSet } = this.props;
7575

76-
const rows: JSX.Element[] = [];
7776
const { numTruncatedResults, sourceLocationPrefix } =
7877
resultSet.interpretation;
7978

@@ -99,202 +98,211 @@ export class AlertTable extends React.Component<
9998
return <AlertTableNoResults {...this.props} />;
10099
}
101100

102-
resultSet.interpretation.data.runs[0].results.forEach(
103-
(result, resultIndex) => {
104-
const resultKey: Keys.Result = { resultIndex };
105-
const text = result.message.text || "[no text]";
106-
const msg =
107-
result.relatedLocations === undefined ? (
108-
<span key="0">{text}</span>
109-
) : (
110-
<SarifMessageWithLocations
111-
msg={text}
112-
relatedLocations={result.relatedLocations}
113-
sourceLocationPrefix={sourceLocationPrefix}
114-
databaseUri={databaseUri}
115-
onClick={updateSelectionCallback(resultKey)}
116-
/>
117-
);
101+
const rows: JSX.Element[] =
102+
resultSet.interpretation.data.runs[0].results.map(
103+
(result, resultIndex) => {
104+
const resultKey: Keys.Result = { resultIndex };
105+
const text = result.message.text || "[no text]";
106+
const msg =
107+
result.relatedLocations === undefined ? (
108+
<span key="0">{text}</span>
109+
) : (
110+
<SarifMessageWithLocations
111+
msg={text}
112+
relatedLocations={result.relatedLocations}
113+
sourceLocationPrefix={sourceLocationPrefix}
114+
databaseUri={databaseUri}
115+
onClick={updateSelectionCallback(resultKey)}
116+
/>
117+
);
118118

119-
const currentResultExpanded = this.state.expanded.has(
120-
Keys.keyToString(resultKey),
121-
);
122-
const location = result.locations !== undefined &&
123-
result.locations.length > 0 && (
124-
<SarifLocation
125-
loc={result.locations[0]}
126-
sourceLocationPrefix={sourceLocationPrefix}
127-
databaseUri={databaseUri}
128-
onClick={updateSelectionCallback(resultKey)}
129-
/>
119+
const currentResultExpanded = this.state.expanded.has(
120+
Keys.keyToString(resultKey),
130121
);
131-
const locationCells = (
132-
<td className="vscode-codeql__location-cell">{location}</td>
133-
);
134-
135-
const selectedItem = this.state.selectedItem;
136-
const resultRowIsSelected =
137-
selectedItem?.resultIndex === resultIndex &&
138-
selectedItem.pathIndex === undefined;
139-
140-
if (result.codeFlows === undefined) {
141-
rows.push(
142-
<tr
143-
ref={this.scroller.ref(resultRowIsSelected)}
144-
key={resultIndex}
145-
{...selectableZebraStripe(resultRowIsSelected, resultIndex)}
146-
>
147-
<td className="vscode-codeql__icon-cell">{info}</td>
148-
<td colSpan={3}>{msg}</td>
149-
{locationCells}
150-
</tr>,
122+
const location = result.locations !== undefined &&
123+
result.locations.length > 0 && (
124+
<SarifLocation
125+
loc={result.locations[0]}
126+
sourceLocationPrefix={sourceLocationPrefix}
127+
databaseUri={databaseUri}
128+
onClick={updateSelectionCallback(resultKey)}
129+
/>
130+
);
131+
const locationCells = (
132+
<td className="vscode-codeql__location-cell">{location}</td>
151133
);
152-
} else {
153-
const paths: Sarif.ThreadFlow[] = Keys.getAllPaths(result);
154134

155-
const indices =
156-
paths.length === 1
157-
? [resultKey, { ...resultKey, pathIndex: 0 }]
158-
: /* if there's exactly one path, auto-expand
159-
* the path when expanding the result */
160-
[resultKey];
135+
const selectedItem = this.state.selectedItem;
136+
const resultRowIsSelected =
137+
selectedItem?.resultIndex === resultIndex &&
138+
selectedItem.pathIndex === undefined;
161139

162-
rows.push(
163-
<tr
164-
ref={this.scroller.ref(resultRowIsSelected)}
165-
{...selectableZebraStripe(resultRowIsSelected, resultIndex)}
166-
key={resultIndex}
167-
>
168-
<AlertTableDropdownIndicatorCell
169-
expanded={currentResultExpanded}
170-
onClick={toggler(indices)}
171-
/>
172-
<td className="vscode-codeql__icon-cell">{listUnordered}</td>
173-
<td colSpan={2}>{msg}</td>
174-
{locationCells}
175-
</tr>,
176-
);
140+
if (result.codeFlows === undefined) {
141+
return (
142+
<tr
143+
ref={this.scroller.ref(resultRowIsSelected)}
144+
key={resultIndex}
145+
{...selectableZebraStripe(resultRowIsSelected, resultIndex)}
146+
>
147+
<td className="vscode-codeql__icon-cell">{info}</td>
148+
<td colSpan={3}>{msg}</td>
149+
{locationCells}
150+
</tr>
151+
);
152+
} else {
153+
const paths: Sarif.ThreadFlow[] = Keys.getAllPaths(result);
154+
155+
const indices =
156+
paths.length === 1
157+
? [resultKey, { ...resultKey, pathIndex: 0 }]
158+
: /* if there's exactly one path, auto-expand
159+
* the path when expanding the result */
160+
[resultKey];
177161

178-
paths.forEach((path, pathIndex) => {
179-
const pathKey = { resultIndex, pathIndex };
180-
const currentPathExpanded = this.state.expanded.has(
181-
Keys.keyToString(pathKey),
162+
const resultRow = (
163+
<tr
164+
ref={this.scroller.ref(resultRowIsSelected)}
165+
{...selectableZebraStripe(resultRowIsSelected, resultIndex)}
166+
key={resultIndex}
167+
>
168+
<AlertTableDropdownIndicatorCell
169+
expanded={currentResultExpanded}
170+
onClick={toggler(indices)}
171+
/>
172+
<td className="vscode-codeql__icon-cell">{listUnordered}</td>
173+
<td colSpan={2}>{msg}</td>
174+
{locationCells}
175+
</tr>
182176
);
183-
if (currentResultExpanded) {
184-
const isPathSpecificallySelected = Keys.equalsNotUndefined(
185-
pathKey,
186-
selectedItem,
187-
);
188-
rows.push(
189-
<tr
190-
ref={this.scroller.ref(isPathSpecificallySelected)}
191-
{...selectableZebraStripe(
192-
isPathSpecificallySelected,
193-
resultIndex,
194-
)}
195-
key={`${resultIndex}-${pathIndex}`}
196-
>
197-
<td className="vscode-codeql__icon-cell">
198-
<span className="vscode-codeql__vertical-rule"></span>
199-
</td>
200-
<AlertTableDropdownIndicatorCell
201-
expanded={currentPathExpanded}
202-
onClick={toggler([pathKey])}
203-
/>
204-
<td className="vscode-codeql__text-center" colSpan={3}>
205-
Path
206-
</td>
207-
</tr>,
208-
);
209-
}
210177

211-
if (currentResultExpanded && currentPathExpanded) {
212-
const pathNodes = path.locations;
213-
for (
214-
let pathNodeIndex = 0;
215-
pathNodeIndex < pathNodes.length;
216-
++pathNodeIndex
217-
) {
218-
const pathNodeKey: Keys.PathNode = {
219-
...pathKey,
220-
pathNodeIndex,
221-
};
222-
const step = pathNodes[pathNodeIndex];
223-
const msg =
224-
step.location !== undefined &&
225-
step.location.message !== undefined ? (
226-
<SarifLocation
227-
text={step.location.message.text}
228-
loc={step.location}
229-
sourceLocationPrefix={sourceLocationPrefix}
230-
databaseUri={databaseUri}
231-
onClick={updateSelectionCallback(pathNodeKey)}
232-
/>
233-
) : (
234-
"[no location]"
235-
);
236-
const additionalMsg =
237-
step.location !== undefined ? (
238-
<SarifLocation
239-
loc={step.location}
240-
sourceLocationPrefix={sourceLocationPrefix}
241-
databaseUri={databaseUri}
242-
onClick={updateSelectionCallback(pathNodeKey)}
243-
/>
244-
) : (
245-
""
246-
);
247-
const isSelected = Keys.equalsNotUndefined(
248-
this.state.selectedItem,
249-
pathNodeKey,
178+
const pathRows =
179+
currentResultExpanded &&
180+
paths.map((path, pathIndex) => {
181+
const pathKey = { resultIndex, pathIndex };
182+
const currentPathExpanded = this.state.expanded.has(
183+
Keys.keyToString(pathKey),
184+
);
185+
const isPathSpecificallySelected = Keys.equalsNotUndefined(
186+
pathKey,
187+
selectedItem,
250188
);
251-
const stepIndex = pathNodeIndex + 1; // Convert to 1-based
252-
const zebraIndex = resultIndex + stepIndex;
253-
rows.push(
189+
const pathRow = (
254190
<tr
255-
ref={this.scroller.ref(isSelected)}
256-
className={
257-
isSelected
258-
? "vscode-codeql__selected-path-node"
259-
: undefined
260-
}
261-
key={`${resultIndex}-${pathIndex}-${pathNodeIndex}`}
191+
ref={this.scroller.ref(isPathSpecificallySelected)}
192+
{...selectableZebraStripe(
193+
isPathSpecificallySelected,
194+
resultIndex,
195+
)}
196+
key={`${resultIndex}-${pathIndex}`}
262197
>
263198
<td className="vscode-codeql__icon-cell">
264199
<span className="vscode-codeql__vertical-rule"></span>
265200
</td>
266-
<td className="vscode-codeql__icon-cell">
267-
<span className="vscode-codeql__vertical-rule"></span>
268-
</td>
269-
<td
270-
{...selectableZebraStripe(
271-
isSelected,
272-
zebraIndex,
273-
"vscode-codeql__path-index-cell",
274-
)}
275-
>
276-
{stepIndex}
277-
</td>
278-
<td {...selectableZebraStripe(isSelected, zebraIndex)}>
279-
{msg}{" "}
280-
</td>
281-
<td
282-
{...selectableZebraStripe(
283-
isSelected,
284-
zebraIndex,
285-
"vscode-codeql__location-cell",
286-
)}
287-
>
288-
{additionalMsg}
201+
<AlertTableDropdownIndicatorCell
202+
expanded={currentPathExpanded}
203+
onClick={toggler([pathKey])}
204+
/>
205+
<td className="vscode-codeql__text-center" colSpan={3}>
206+
Path
289207
</td>
290-
</tr>,
208+
</tr>
291209
);
292-
}
293-
}
294-
});
295-
}
296-
},
297-
);
210+
211+
const pathNodeRows =
212+
currentPathExpanded &&
213+
path.locations.map((step, pathNodeIndex) => {
214+
const pathNodeKey: Keys.PathNode = {
215+
...pathKey,
216+
pathNodeIndex,
217+
};
218+
const msg =
219+
step.location !== undefined &&
220+
step.location.message !== undefined ? (
221+
<SarifLocation
222+
text={step.location.message.text}
223+
loc={step.location}
224+
sourceLocationPrefix={sourceLocationPrefix}
225+
databaseUri={databaseUri}
226+
onClick={updateSelectionCallback(pathNodeKey)}
227+
/>
228+
) : (
229+
"[no location]"
230+
);
231+
const additionalMsg =
232+
step.location !== undefined ? (
233+
<SarifLocation
234+
loc={step.location}
235+
sourceLocationPrefix={sourceLocationPrefix}
236+
databaseUri={databaseUri}
237+
onClick={updateSelectionCallback(pathNodeKey)}
238+
/>
239+
) : (
240+
""
241+
);
242+
const isSelected = Keys.equalsNotUndefined(
243+
this.state.selectedItem,
244+
pathNodeKey,
245+
);
246+
const stepIndex = pathNodeIndex + 1; // Convert to 1-based
247+
const zebraIndex = resultIndex + stepIndex;
248+
return (
249+
<tr
250+
ref={this.scroller.ref(isSelected)}
251+
className={
252+
isSelected
253+
? "vscode-codeql__selected-path-node"
254+
: undefined
255+
}
256+
key={`${resultIndex}-${pathIndex}-${pathNodeIndex}`}
257+
>
258+
<td className="vscode-codeql__icon-cell">
259+
<span className="vscode-codeql__vertical-rule"></span>
260+
</td>
261+
<td className="vscode-codeql__icon-cell">
262+
<span className="vscode-codeql__vertical-rule"></span>
263+
</td>
264+
<td
265+
{...selectableZebraStripe(
266+
isSelected,
267+
zebraIndex,
268+
"vscode-codeql__path-index-cell",
269+
)}
270+
>
271+
{stepIndex}
272+
</td>
273+
<td {...selectableZebraStripe(isSelected, zebraIndex)}>
274+
{msg}{" "}
275+
</td>
276+
<td
277+
{...selectableZebraStripe(
278+
isSelected,
279+
zebraIndex,
280+
"vscode-codeql__location-cell",
281+
)}
282+
>
283+
{additionalMsg}
284+
</td>
285+
</tr>
286+
);
287+
});
288+
289+
return (
290+
<>
291+
{pathRow}
292+
{pathNodeRows}
293+
</>
294+
);
295+
});
296+
297+
return (
298+
<>
299+
{resultRow}
300+
{pathRows}
301+
</>
302+
);
303+
}
304+
},
305+
);
298306

299307
return (
300308
<table className={className}>

0 commit comments

Comments
 (0)