Skip to content

Commit 377de26

Browse files
authored
Fix data race in problem view tree (#13841)
1 parent b16f49b commit 377de26

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

packages/markers/src/browser/problem/problem-composite-tree-node.ts

+6-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import { ProblemUtils } from './problem-utils';
2323

2424
export namespace ProblemCompositeTreeNode {
2525

26+
export interface Child {
27+
node: MarkerInfoNode;
28+
markers: Marker<Diagnostic>[];
29+
}
30+
2631
export function setSeverity(parent: MarkerInfoNode, markers: Marker<Diagnostic>[]): void {
2732
let maxSeverity: DiagnosticSeverity | undefined;
2833
markers.forEach(marker => {
@@ -33,7 +38,7 @@ export namespace ProblemCompositeTreeNode {
3338
parent.severity = maxSeverity;
3439
};
3540

36-
export function addChildren(parent: CompositeTreeNode, insertChildren: { node: MarkerInfoNode, markers: Marker<Diagnostic>[] }[]): void {
41+
export function addChildren(parent: CompositeTreeNode, insertChildren: ProblemCompositeTreeNode.Child[]): void {
3742
for (const { node, markers } of insertChildren) {
3843
ProblemCompositeTreeNode.setSeverity(node, markers);
3944
}

packages/markers/src/browser/problem/problem-tree-model.ts

+14-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ import debounce = require('@theia/core/shared/lodash.debounce');
2828

2929
@injectable()
3030
export class ProblemTree extends MarkerTree<Diagnostic> {
31-
protected markers: { node: MarkerInfoNode, markers: Marker<Diagnostic>[] }[] = [];
31+
32+
protected queuedMarkers = new Map<string, ProblemCompositeTreeNode.Child>();
3233

3334
constructor(
3435
@inject(ProblemManager) markerManager: ProblemManager,
@@ -79,20 +80,28 @@ export class ProblemTree extends MarkerTree<Diagnostic> {
7980
}
8081

8182
protected override insertNodeWithMarkers(node: MarkerInfoNode, markers: Marker<Diagnostic>[]): void {
82-
this.markers.push({ node, markers });
83+
// Add the element to the queue.
84+
// In case a diagnostics collection for the same file already exists, it will be replaced.
85+
this.queuedMarkers.set(node.id, { node, markers });
8386
this.doInsertNodesWithMarkers();
8487
}
8588

8689
protected doInsertNodesWithMarkers = debounce(() => {
87-
ProblemCompositeTreeNode.addChildren(this.root as MarkerRootNode, this.markers);
90+
const root = this.root;
91+
// Sanity check; This should always be of type `MarkerRootNode`
92+
if (!MarkerRootNode.is(root)) {
93+
return;
94+
}
95+
const queuedItems = Array.from(this.queuedMarkers.values());
96+
ProblemCompositeTreeNode.addChildren(root, queuedItems);
8897

89-
for (const { node, markers } of this.markers) {
98+
for (const { node, markers } of queuedItems) {
9099
const children = this.getMarkerNodes(node, markers);
91100
node.numberOfMarkers = markers.length;
92101
this.setChildren(node, children);
93102
}
94103

95-
this.markers.length = 0;
104+
this.queuedMarkers.clear();
96105
}, 50);
97106
}
98107

0 commit comments

Comments
 (0)