Skip to content

Commit 6ef5dbe

Browse files
committed
_forwardMarkers must check for empty markerData, fixes microsoft#136434
1 parent 9d092bc commit 6ef5dbe

File tree

2 files changed

+61
-6
lines changed

2 files changed

+61
-6
lines changed

src/vs/workbench/api/browser/mainThreadDiagnostics.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ export class MainThreadDiagnostics implements MainThreadDiagnosticsShape {
3737
private _forwardMarkers(resources: readonly URI[]): void {
3838
const data: [UriComponents, IMarkerData[]][] = [];
3939
for (const resource of resources) {
40-
data.push([
41-
resource,
42-
this._markerService.read({ resource }).filter(marker => !this._activeOwners.has(marker.owner))
43-
]);
40+
const markerData = this._markerService.read({ resource }).filter(marker => !this._activeOwners.has(marker.owner));
41+
if (markerData.length > 0) {
42+
data.push([resource, markerData]);
43+
}
44+
}
45+
if (data.length > 0) {
46+
this._proxy.$acceptMarkersChange(data);
4447
}
45-
this._proxy.$acceptMarkersChange(data);
4648
}
4749

4850
$changeMany(owner: string, entries: [UriComponents, IMarkerData[]][]): void {

src/vs/workbench/test/browser/api/mainThreadDiagnostics.test.ts

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,14 @@
66
import * as assert from 'assert';
77
import { MarkerService } from 'vs/platform/markers/common/markerService';
88
import { MainThreadDiagnostics } from 'vs/workbench/api/browser/mainThreadDiagnostics';
9-
import { URI } from 'vs/base/common/uri';
9+
import { URI, UriComponents } from 'vs/base/common/uri';
1010
import { IExtHostContext } from 'vs/workbench/api/common/extHost.protocol';
1111
import { mock } from 'vs/workbench/test/common/workbenchTestServices';
1212
import { IUriIdentityService } from 'vs/platform/uriIdentity/common/uriIdentity';
1313
import { ExtensionHostKind } from 'vs/workbench/services/extensions/common/extensions';
14+
import { IMarkerData } from 'vs/platform/markers/common/markers';
15+
import { runWithFakedTimers } from 'vs/base/test/common/timeTravelScheduler';
16+
import { timeout } from 'vs/base/common/async';
1417

1518

1619
suite('MainThreadDiagnostics', function () {
@@ -57,4 +60,54 @@ suite('MainThreadDiagnostics', function () {
5760
diag.dispose();
5861
assert.strictEqual(markerService.read().length, 0);
5962
});
63+
64+
test('OnDidChangeDiagnostics triggers twice on same diagnostics #136434', function () {
65+
66+
return runWithFakedTimers({}, async () => {
67+
68+
const changedData: [UriComponents, IMarkerData[]][][] = [];
69+
70+
let diag = new MainThreadDiagnostics(
71+
new class implements IExtHostContext {
72+
remoteAuthority = '';
73+
extensionHostKind = ExtensionHostKind.LocalProcess;
74+
assertRegistered() { }
75+
set(v: any): any { return null; }
76+
getProxy(): any {
77+
return {
78+
$acceptMarkersChange(data: [UriComponents, IMarkerData[]][]) {
79+
changedData.push(data);
80+
}
81+
};
82+
}
83+
drain(): any { return null; }
84+
},
85+
markerService,
86+
new class extends mock<IUriIdentityService>() {
87+
override asCanonicalUri(uri: URI) { return uri; }
88+
}
89+
);
90+
91+
const markerDataStub = {
92+
code: '666',
93+
startLineNumber: 1,
94+
startColumn: 1,
95+
endLineNumber: 1,
96+
endColumn: 1,
97+
severity: 1,
98+
source: 'me'
99+
};
100+
const target = URI.file('a');
101+
diag.$changeMany('foo', [[target, [{ ...markerDataStub, message: 'same_owner' }]]]);
102+
markerService.changeOne('bar', target, [{ ...markerDataStub, message: 'forgein_owner' }]);
103+
104+
// added one marker via the API and one via the ext host. the latter must not
105+
// trigger an event to the extension host
106+
107+
await timeout(0);
108+
assert.strictEqual(markerService.read().length, 2);
109+
assert.strictEqual(changedData.length, 1);
110+
assert.strictEqual(changedData[0][0][1][0].message, 'forgein_owner');
111+
});
112+
});
60113
});

0 commit comments

Comments
 (0)