Skip to content

Commit 1b66cd7

Browse files
committed
Strict null checks (#60565)
1 parent 7f1108d commit 1b66cd7

File tree

11 files changed

+93
-79
lines changed

11 files changed

+93
-79
lines changed

Diff for: src/tsconfig.strictNullChecks.json

+5
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"./vs/workbench/api/electron-browser/mainThreadEditor.ts",
6464
"./vs/workbench/api/electron-browser/mainThreadEditors.ts",
6565
"./vs/workbench/api/electron-browser/mainThreadErrors.ts",
66+
"./vs/workbench/api/electron-browser/mainThreadExtensionService.ts",
6667
"./vs/workbench/api/electron-browser/mainThreadFileSystem.ts",
6768
"./vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts",
6869
"./vs/workbench/api/electron-browser/mainThreadHeapService.ts",
@@ -218,6 +219,8 @@
218219
"./vs/workbench/contrib/output/common/outputLinkComputer.ts",
219220
"./vs/workbench/contrib/output/common/outputLinkProvider.ts",
220221
"./vs/workbench/contrib/output/test/outputLinkProvider.test.ts",
222+
"./vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts",
223+
"./vs/workbench/contrib/preferences/browser/keybindingWidgets.ts",
221224
"./vs/workbench/contrib/preferences/browser/preferencesActions.ts",
222225
"./vs/workbench/contrib/preferences/browser/preferencesWidgets.ts",
223226
"./vs/workbench/contrib/preferences/browser/settingsLayout.ts",
@@ -306,8 +309,10 @@
306309
"./vs/workbench/services/extensions/common/extensionsRegistry.ts",
307310
"./vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts",
308311
"./vs/workbench/services/extensions/electron-browser/extensionHost.ts",
312+
"./vs/workbench/services/extensions/electron-browser/extensionHostProcessManager.ts",
309313
"./vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts",
310314
"./vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts",
315+
"./vs/workbench/services/extensions/electron-browser/extensionService.ts",
311316
"./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts",
312317
"./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts",
313318
"./vs/workbench/services/extensions/node/extensionHostProtocol.ts",

Diff for: src/vs/base/browser/ui/keybindingLabel/keybindingLabel.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export interface KeybindingLabelOptions {
3333
export class KeybindingLabel {
3434

3535
private domNode: HTMLElement;
36-
private keybinding: ResolvedKeybinding | undefined;
36+
private keybinding: ResolvedKeybinding | null | undefined;
3737
private matches: Matches | undefined;
3838
private didEverRender: boolean;
3939

@@ -47,7 +47,7 @@ export class KeybindingLabel {
4747
return this.domNode;
4848
}
4949

50-
set(keybinding: ResolvedKeybinding | undefined, matches?: Matches) {
50+
set(keybinding: ResolvedKeybinding | null | undefined, matches?: Matches) {
5151
if (this.didEverRender && this.keybinding === keybinding && KeybindingLabel.areSame(this.matches, matches)) {
5252
return;
5353
}

Diff for: src/vs/workbench/api/electron-browser/mainThreadExtensionService.ts

-3
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,4 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
5151
}
5252
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void {
5353
}
54-
$addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
55-
this._extensionService._addMessage(extensionId, severity, message);
56-
}
5754
}

Diff for: src/vs/workbench/api/node/extHost.protocol.ts

-1
Original file line numberDiff line numberDiff line change
@@ -577,7 +577,6 @@ export interface MainThreadExtensionServiceShape extends IDisposable {
577577
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string | null): void;
578578
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void;
579579
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void;
580-
$addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void;
581580
}
582581

583582
export interface SCMProviderFeatures {

Diff for: src/vs/workbench/api/node/extHostExtensionService.ts

-4
Original file line numberDiff line numberDiff line change
@@ -372,10 +372,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
372372
return result;
373373
}
374374

375-
public addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
376-
this._mainThreadExtensionsProxy.$addMessage(extensionId, severity, message);
377-
}
378-
379375
// --- impl
380376

381377
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {

Diff for: src/vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
303303

304304
data.name.textContent = element.marketplaceInfo ? element.marketplaceInfo.displayName : element.description.displayName || '';
305305

306-
const activationTimes = element.status.activationTimes;
306+
const activationTimes = element.status.activationTimes!;
307307
let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime;
308308
data.activationTime.textContent = activationTimes.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
309309

Diff for: src/vs/workbench/contrib/preferences/browser/keybindingWidgets.ts

+18-16
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,14 @@ export interface KeybindingsSearchOptions extends SearchOptions {
3131

3232
export class KeybindingsSearchWidget extends SearchWidget {
3333

34-
private _firstPart: ResolvedKeybinding;
35-
private _chordPart: ResolvedKeybinding;
34+
private _firstPart: ResolvedKeybinding | null;
35+
private _chordPart: ResolvedKeybinding | null;
3636
private _inputValue: string;
3737

3838
private recordDisposables: IDisposable[] = [];
3939

40-
private _onKeybinding = this._register(new Emitter<[ResolvedKeybinding, ResolvedKeybinding]>());
41-
readonly onKeybinding: Event<[ResolvedKeybinding, ResolvedKeybinding]> = this._onKeybinding.event;
40+
private _onKeybinding = this._register(new Emitter<[ResolvedKeybinding | null, ResolvedKeybinding | null]>());
41+
readonly onKeybinding: Event<[ResolvedKeybinding | null, ResolvedKeybinding | null]> = this._onKeybinding.event;
4242

4343
private _onEnter = this._register(new Emitter<void>());
4444
readonly onEnter: Event<void> = this._onEnter.event;
@@ -125,7 +125,7 @@ export class KeybindingsSearchWidget extends SearchWidget {
125125

126126
let value = '';
127127
if (this._firstPart) {
128-
value = this._firstPart.getUserSettingsLabel();
128+
value = (this._firstPart.getUserSettingsLabel() || '');
129129
}
130130
if (this._chordPart) {
131131
value = value + ' ' + this._chordPart.getUserSettingsLabel();
@@ -153,11 +153,11 @@ export class DefineKeybindingWidget extends Widget {
153153

154154
private _onHide = this._register(new Emitter<void>());
155155

156-
private _onDidChange = this._register(new Emitter<String>());
157-
onDidChange: Event<String> = this._onDidChange.event;
156+
private _onDidChange = this._register(new Emitter<string>());
157+
onDidChange: Event<string> = this._onDidChange.event;
158158

159-
private _onShowExistingKeybindings = this._register(new Emitter<String>());
160-
readonly onShowExistingKeybidings: Event<String> = this._onShowExistingKeybindings.event;
159+
private _onShowExistingKeybindings = this._register(new Emitter<string | null>());
160+
readonly onShowExistingKeybidings: Event<string | null> = this._onShowExistingKeybindings.event;
161161

162162
constructor(
163163
parent: HTMLElement,
@@ -175,9 +175,9 @@ export class DefineKeybindingWidget extends Widget {
175175
return this._domNode.domNode;
176176
}
177177

178-
define(): Promise<string> {
178+
define(): Promise<string | null> {
179179
this._keybindingInputWidget.clear();
180-
return new Promise<string>((c) => {
180+
return new Promise<string | null>((c) => {
181181
if (!this._isVisible) {
182182
this._isVisible = true;
183183
this._domNode.setDisplay('block');
@@ -251,7 +251,7 @@ export class DefineKeybindingWidget extends Widget {
251251
this._showExistingKeybindingsNode = dom.append(this._domNode.domNode, dom.$('.existing'));
252252
}
253253

254-
private onKeybinding(keybinding: [ResolvedKeybinding, ResolvedKeybinding]): void {
254+
private onKeybinding(keybinding: [ResolvedKeybinding | null, ResolvedKeybinding | null]): void {
255255
const [firstPart, chordPart] = keybinding;
256256
this._firstPart = firstPart;
257257
this._chordPart = chordPart;
@@ -268,8 +268,8 @@ export class DefineKeybindingWidget extends Widget {
268268
}
269269
}
270270

271-
private getUserSettingsLabel(): string {
272-
let label = null;
271+
private getUserSettingsLabel(): string | null {
272+
let label: string | null = null;
273273
if (this._firstPart) {
274274
label = this._firstPart.getUserSettingsLabel();
275275
if (this._chordPart) {
@@ -326,8 +326,10 @@ export class DefineKeybindingOverlayWidget extends Disposable implements IOverla
326326
super.dispose();
327327
}
328328

329-
start(): Promise<string> {
330-
this._editor.revealPositionInCenterIfOutsideViewport(this._editor.getPosition(), ScrollType.Smooth);
329+
start(): Promise<string | null> {
330+
if (this._editor.hasModel()) {
331+
this._editor.revealPositionInCenterIfOutsideViewport(this._editor.getPosition(), ScrollType.Smooth);
332+
}
331333
const layoutInfo = this._editor.getLayoutInfo();
332334
this._widget.layout(new dom.Dimension(layoutInfo.width, layoutInfo.height));
333335
return this._widget.define();

Diff for: src/vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ export class KeybindingWidgetRenderer extends Disposable {
135135
this._defineWidget.start().then(keybinding => this._onAccepted(keybinding));
136136
}
137137

138-
private _onAccepted(keybinding: string): void {
138+
private _onAccepted(keybinding: string | null): void {
139139
this._editor.focus();
140140
if (keybinding && this._editor.hasModel()) {
141141
const regexp = new RegExp(/\\/g);

Diff for: src/vs/workbench/services/extensions/common/extensions.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ export interface IMessage {
4242

4343
export interface IExtensionsStatus {
4444
messages: IMessage[];
45-
activationTimes: ActivationTimes;
45+
activationTimes: ActivationTimes | undefined;
4646
runtimeErrors: Error[];
4747
}
4848

Diff for: src/vs/workbench/services/extensions/electron-browser/extensionHostProcessManager.ts

+53-27
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,13 @@ export class ExtensionHostProcessManager extends Disposable {
4545
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
4646
*/
4747
private readonly _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; };
48-
private _extensionHostProcessRPCProtocol: RPCProtocol;
48+
private _extensionHostProcessRPCProtocol: RPCProtocol | null;
4949
private readonly _extensionHostProcessCustomers: IDisposable[];
5050
private readonly _extensionHostProcessWorker: IExtensionHostStarter;
5151
/**
5252
* winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object.
5353
*/
54-
private _extensionHostProcessProxy: Promise<{ value: ExtHostExtensionServiceShape; }>;
54+
private _extensionHostProcessProxy: Promise<{ value: ExtHostExtensionServiceShape; } | null> | null;
5555

5656
constructor(
5757
extensionHostProcessWorker: IExtensionHostStarter,
@@ -67,7 +67,7 @@ export class ExtensionHostProcessManager extends Disposable {
6767

6868
this._extensionHostProcessWorker = extensionHostProcessWorker;
6969
this.onDidCrash = this._extensionHostProcessWorker.onCrashed;
70-
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start().then(
70+
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start()!.then(
7171
(protocol) => {
7272
return { value: this._createExtensionHostCustomers(protocol) };
7373
},
@@ -105,10 +105,14 @@ export class ExtensionHostProcessManager extends Disposable {
105105
super.dispose();
106106
}
107107

108-
private async measure(): Promise<ExtHostLatencyResult> {
109-
const latency = await this._measureLatency();
110-
const down = await this._measureDown();
111-
const up = await this._measureUp();
108+
private async measure(): Promise<ExtHostLatencyResult | null> {
109+
const proxy = await this._getExtensionHostProcessProxy();
110+
if (!proxy) {
111+
return null;
112+
}
113+
const latency = await this._measureLatency(proxy);
114+
const down = await this._measureDown(proxy);
115+
const up = await this._measureUp(proxy);
112116
return {
113117
remoteAuthority: this._remoteAuthority,
114118
latency,
@@ -117,10 +121,20 @@ export class ExtensionHostProcessManager extends Disposable {
117121
};
118122
}
119123

120-
private async _measureLatency(): Promise<number> {
124+
private async _getExtensionHostProcessProxy(): Promise<ExtHostExtensionServiceShape | null> {
125+
if (!this._extensionHostProcessProxy) {
126+
return null;
127+
}
128+
const p = await this._extensionHostProcessProxy;
129+
if (!p) {
130+
return null;
131+
}
132+
return p.value;
133+
}
134+
135+
private async _measureLatency(proxy: ExtHostExtensionServiceShape): Promise<number> {
121136
const COUNT = 10;
122137

123-
const { value: proxy } = await this._extensionHostProcessProxy;
124138
let sum = 0;
125139
for (let i = 0; i < COUNT; i++) {
126140
const sw = StopWatch.create(true);
@@ -135,21 +149,19 @@ export class ExtensionHostProcessManager extends Disposable {
135149
return (byteCount * 1000 * 8) / elapsedMillis;
136150
}
137151

138-
private async _measureUp(): Promise<number> {
152+
private async _measureUp(proxy: ExtHostExtensionServiceShape): Promise<number> {
139153
const SIZE = 10 * 1024 * 1024; // 10MB
140154

141-
const { value: proxy } = await this._extensionHostProcessProxy;
142155
let b = Buffer.alloc(SIZE, Math.random() % 256);
143156
const sw = StopWatch.create(true);
144157
await proxy.$test_up(b);
145158
sw.stop();
146159
return ExtensionHostProcessManager._convert(SIZE, sw.elapsed());
147160
}
148161

149-
private async _measureDown(): Promise<number> {
162+
private async _measureDown(proxy: ExtHostExtensionServiceShape): Promise<number> {
150163
const SIZE = 10 * 1024 * 1024; // 10MB
151164

152-
const { value: proxy } = await this._extensionHostProcessProxy;
153165
const sw = StopWatch.create(true);
154166
await proxy.$test_down(SIZE);
155167
sw.stop();
@@ -171,9 +183,9 @@ export class ExtensionHostProcessManager extends Disposable {
171183
this._register(this._extensionHostProcessRPCProtocol.onDidChangeResponsiveState((responsiveState: ResponsiveState) => this._onDidChangeResponsiveState.fire(responsiveState)));
172184
const extHostContext: IExtHostContext = {
173185
remoteAuthority: this._remoteAuthority,
174-
getProxy: <T>(identifier: ProxyIdentifier<T>): T => this._extensionHostProcessRPCProtocol.getProxy(identifier),
175-
set: <T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R => this._extensionHostProcessRPCProtocol.set(identifier, instance),
176-
assertRegistered: (identifiers: ProxyIdentifier<any>[]): void => this._extensionHostProcessRPCProtocol.assertRegistered(identifiers),
186+
getProxy: <T>(identifier: ProxyIdentifier<T>): T => this._extensionHostProcessRPCProtocol!.getProxy(identifier),
187+
set: <T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R => this._extensionHostProcessRPCProtocol!.set(identifier, instance),
188+
assertRegistered: (identifiers: ProxyIdentifier<any>[]): void => this._extensionHostProcessRPCProtocol!.assertRegistered(identifiers),
177189
};
178190

179191
// Named customers
@@ -199,10 +211,12 @@ export class ExtensionHostProcessManager extends Disposable {
199211
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
200212
}
201213

202-
public activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
203-
return this._extensionHostProcessProxy.then((proxy) => {
204-
return proxy.value.$activate(extension, activationEvent);
205-
});
214+
public async activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
215+
const proxy = await this._getExtensionHostProcessProxy();
216+
if (!proxy) {
217+
return false;
218+
}
219+
return proxy.$activate(extension, activationEvent);
206220
}
207221

208222
public activateByEvent(activationEvent: string): Promise<void> {
@@ -241,7 +255,7 @@ export class ExtensionHostProcessManager extends Disposable {
241255
return 0;
242256
}
243257

244-
public resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority> {
258+
public async resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority> {
245259
const authorityPlusIndex = remoteAuthority.indexOf('+');
246260
if (authorityPlusIndex === -1) {
247261
// This authority does not need to be resolved, simply parse the port number
@@ -252,15 +266,27 @@ export class ExtensionHostProcessManager extends Disposable {
252266
port: parseInt(pieces[1], 10)
253267
});
254268
}
255-
return this._extensionHostProcessProxy.then(proxy => proxy.value.$resolveAuthority(remoteAuthority));
269+
const proxy = await this._getExtensionHostProcessProxy();
270+
if (!proxy) {
271+
throw new Error(`Cannot resolve authority`);
272+
}
273+
return proxy.$resolveAuthority(remoteAuthority);
256274
}
257275

258-
public start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
259-
return this._extensionHostProcessProxy.then(proxy => proxy.value.$startExtensionHost(enabledExtensionIds));
276+
public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
277+
const proxy = await this._getExtensionHostProcessProxy();
278+
if (!proxy) {
279+
return;
280+
}
281+
return proxy.$startExtensionHost(enabledExtensionIds);
260282
}
261283

262-
public deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
263-
return this._extensionHostProcessProxy.then(proxy => proxy.value.$deltaExtensions(toAdd, toRemove));
284+
public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
285+
const proxy = await this._getExtensionHostProcessProxy();
286+
if (!proxy) {
287+
return;
288+
}
289+
return proxy.$deltaExtensions(toAdd, toRemove);
264290
}
265291
}
266292

@@ -328,7 +354,7 @@ interface ExtHostLatencyResult {
328354
}
329355

330356
interface ExtHostLatencyProvider {
331-
measure(): Promise<ExtHostLatencyResult>;
357+
measure(): Promise<ExtHostLatencyResult | null>;
332358
}
333359

334360
let providers: ExtHostLatencyProvider[] = [];

0 commit comments

Comments
 (0)