提交 1b66cd7f 编写于 作者: A Alex Dima

Strict null checks (#60565)

上级 7f1108d7
......@@ -63,6 +63,7 @@
"./vs/workbench/api/electron-browser/mainThreadEditor.ts",
"./vs/workbench/api/electron-browser/mainThreadEditors.ts",
"./vs/workbench/api/electron-browser/mainThreadErrors.ts",
"./vs/workbench/api/electron-browser/mainThreadExtensionService.ts",
"./vs/workbench/api/electron-browser/mainThreadFileSystem.ts",
"./vs/workbench/api/electron-browser/mainThreadFileSystemEventService.ts",
"./vs/workbench/api/electron-browser/mainThreadHeapService.ts",
......@@ -218,6 +219,8 @@
"./vs/workbench/contrib/output/common/outputLinkComputer.ts",
"./vs/workbench/contrib/output/common/outputLinkProvider.ts",
"./vs/workbench/contrib/output/test/outputLinkProvider.test.ts",
"./vs/workbench/contrib/preferences/browser/keybindingsEditorContribution.ts",
"./vs/workbench/contrib/preferences/browser/keybindingWidgets.ts",
"./vs/workbench/contrib/preferences/browser/preferencesActions.ts",
"./vs/workbench/contrib/preferences/browser/preferencesWidgets.ts",
"./vs/workbench/contrib/preferences/browser/settingsLayout.ts",
......@@ -306,8 +309,10 @@
"./vs/workbench/services/extensions/common/extensionsRegistry.ts",
"./vs/workbench/services/extensions/electron-browser/cachedExtensionScanner.ts",
"./vs/workbench/services/extensions/electron-browser/extensionHost.ts",
"./vs/workbench/services/extensions/electron-browser/extensionHostProcessManager.ts",
"./vs/workbench/services/extensions/electron-browser/extensionHostProfiler.ts",
"./vs/workbench/services/extensions/electron-browser/extensionManagementServerService.ts",
"./vs/workbench/services/extensions/electron-browser/extensionService.ts",
"./vs/workbench/services/extensions/electron-browser/inactiveExtensionUrlHandler.ts",
"./vs/workbench/services/extensions/node/extensionDescriptionRegistry.ts",
"./vs/workbench/services/extensions/node/extensionHostProtocol.ts",
......
......@@ -33,7 +33,7 @@ export interface KeybindingLabelOptions {
export class KeybindingLabel {
private domNode: HTMLElement;
private keybinding: ResolvedKeybinding | undefined;
private keybinding: ResolvedKeybinding | null | undefined;
private matches: Matches | undefined;
private didEverRender: boolean;
......@@ -47,7 +47,7 @@ export class KeybindingLabel {
return this.domNode;
}
set(keybinding: ResolvedKeybinding | undefined, matches?: Matches) {
set(keybinding: ResolvedKeybinding | null | undefined, matches?: Matches) {
if (this.didEverRender && this.keybinding === keybinding && KeybindingLabel.areSame(this.matches, matches)) {
return;
}
......
......@@ -51,7 +51,4 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
}
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void {
}
$addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
this._extensionService._addMessage(extensionId, severity, message);
}
}
......@@ -577,7 +577,6 @@ export interface MainThreadExtensionServiceShape extends IDisposable {
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string | null): void;
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void;
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void;
$addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void;
}
export interface SCMProviderFeatures {
......
......@@ -372,10 +372,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return result;
}
public addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
this._mainThreadExtensionsProxy.$addMessage(extensionId, severity, message);
}
// --- impl
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
......
......@@ -303,7 +303,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
data.name.textContent = element.marketplaceInfo ? element.marketplaceInfo.displayName : element.description.displayName || '';
const activationTimes = element.status.activationTimes;
const activationTimes = element.status.activationTimes!;
let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime;
data.activationTime.textContent = activationTimes.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
......
......@@ -31,14 +31,14 @@ export interface KeybindingsSearchOptions extends SearchOptions {
export class KeybindingsSearchWidget extends SearchWidget {
private _firstPart: ResolvedKeybinding;
private _chordPart: ResolvedKeybinding;
private _firstPart: ResolvedKeybinding | null;
private _chordPart: ResolvedKeybinding | null;
private _inputValue: string;
private recordDisposables: IDisposable[] = [];
private _onKeybinding = this._register(new Emitter<[ResolvedKeybinding, ResolvedKeybinding]>());
readonly onKeybinding: Event<[ResolvedKeybinding, ResolvedKeybinding]> = this._onKeybinding.event;
private _onKeybinding = this._register(new Emitter<[ResolvedKeybinding | null, ResolvedKeybinding | null]>());
readonly onKeybinding: Event<[ResolvedKeybinding | null, ResolvedKeybinding | null]> = this._onKeybinding.event;
private _onEnter = this._register(new Emitter<void>());
readonly onEnter: Event<void> = this._onEnter.event;
......@@ -125,7 +125,7 @@ export class KeybindingsSearchWidget extends SearchWidget {
let value = '';
if (this._firstPart) {
value = this._firstPart.getUserSettingsLabel();
value = (this._firstPart.getUserSettingsLabel() || '');
}
if (this._chordPart) {
value = value + ' ' + this._chordPart.getUserSettingsLabel();
......@@ -153,11 +153,11 @@ export class DefineKeybindingWidget extends Widget {
private _onHide = this._register(new Emitter<void>());
private _onDidChange = this._register(new Emitter<String>());
onDidChange: Event<String> = this._onDidChange.event;
private _onDidChange = this._register(new Emitter<string>());
onDidChange: Event<string> = this._onDidChange.event;
private _onShowExistingKeybindings = this._register(new Emitter<String>());
readonly onShowExistingKeybidings: Event<String> = this._onShowExistingKeybindings.event;
private _onShowExistingKeybindings = this._register(new Emitter<string | null>());
readonly onShowExistingKeybidings: Event<string | null> = this._onShowExistingKeybindings.event;
constructor(
parent: HTMLElement,
......@@ -175,9 +175,9 @@ export class DefineKeybindingWidget extends Widget {
return this._domNode.domNode;
}
define(): Promise<string> {
define(): Promise<string | null> {
this._keybindingInputWidget.clear();
return new Promise<string>((c) => {
return new Promise<string | null>((c) => {
if (!this._isVisible) {
this._isVisible = true;
this._domNode.setDisplay('block');
......@@ -251,7 +251,7 @@ export class DefineKeybindingWidget extends Widget {
this._showExistingKeybindingsNode = dom.append(this._domNode.domNode, dom.$('.existing'));
}
private onKeybinding(keybinding: [ResolvedKeybinding, ResolvedKeybinding]): void {
private onKeybinding(keybinding: [ResolvedKeybinding | null, ResolvedKeybinding | null]): void {
const [firstPart, chordPart] = keybinding;
this._firstPart = firstPart;
this._chordPart = chordPart;
......@@ -268,8 +268,8 @@ export class DefineKeybindingWidget extends Widget {
}
}
private getUserSettingsLabel(): string {
let label = null;
private getUserSettingsLabel(): string | null {
let label: string | null = null;
if (this._firstPart) {
label = this._firstPart.getUserSettingsLabel();
if (this._chordPart) {
......@@ -326,8 +326,10 @@ export class DefineKeybindingOverlayWidget extends Disposable implements IOverla
super.dispose();
}
start(): Promise<string> {
this._editor.revealPositionInCenterIfOutsideViewport(this._editor.getPosition(), ScrollType.Smooth);
start(): Promise<string | null> {
if (this._editor.hasModel()) {
this._editor.revealPositionInCenterIfOutsideViewport(this._editor.getPosition(), ScrollType.Smooth);
}
const layoutInfo = this._editor.getLayoutInfo();
this._widget.layout(new dom.Dimension(layoutInfo.width, layoutInfo.height));
return this._widget.define();
......
......@@ -135,7 +135,7 @@ export class KeybindingWidgetRenderer extends Disposable {
this._defineWidget.start().then(keybinding => this._onAccepted(keybinding));
}
private _onAccepted(keybinding: string): void {
private _onAccepted(keybinding: string | null): void {
this._editor.focus();
if (keybinding && this._editor.hasModel()) {
const regexp = new RegExp(/\\/g);
......
......@@ -42,7 +42,7 @@ export interface IMessage {
export interface IExtensionsStatus {
messages: IMessage[];
activationTimes: ActivationTimes;
activationTimes: ActivationTimes | undefined;
runtimeErrors: Error[];
}
......
......@@ -45,13 +45,13 @@ export class ExtensionHostProcessManager extends Disposable {
* A map of already activated events to speed things up if the same activation event is triggered multiple times.
*/
private readonly _extensionHostProcessFinishedActivateEvents: { [activationEvent: string]: boolean; };
private _extensionHostProcessRPCProtocol: RPCProtocol;
private _extensionHostProcessRPCProtocol: RPCProtocol | null;
private readonly _extensionHostProcessCustomers: IDisposable[];
private readonly _extensionHostProcessWorker: IExtensionHostStarter;
/**
* winjs believes a proxy is a promise because it has a `then` method, so wrap the result in an object.
*/
private _extensionHostProcessProxy: Promise<{ value: ExtHostExtensionServiceShape; }>;
private _extensionHostProcessProxy: Promise<{ value: ExtHostExtensionServiceShape; } | null> | null;
constructor(
extensionHostProcessWorker: IExtensionHostStarter,
......@@ -67,7 +67,7 @@ export class ExtensionHostProcessManager extends Disposable {
this._extensionHostProcessWorker = extensionHostProcessWorker;
this.onDidCrash = this._extensionHostProcessWorker.onCrashed;
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start().then(
this._extensionHostProcessProxy = this._extensionHostProcessWorker.start()!.then(
(protocol) => {
return { value: this._createExtensionHostCustomers(protocol) };
},
......@@ -105,10 +105,14 @@ export class ExtensionHostProcessManager extends Disposable {
super.dispose();
}
private async measure(): Promise<ExtHostLatencyResult> {
const latency = await this._measureLatency();
const down = await this._measureDown();
const up = await this._measureUp();
private async measure(): Promise<ExtHostLatencyResult | null> {
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
return null;
}
const latency = await this._measureLatency(proxy);
const down = await this._measureDown(proxy);
const up = await this._measureUp(proxy);
return {
remoteAuthority: this._remoteAuthority,
latency,
......@@ -117,10 +121,20 @@ export class ExtensionHostProcessManager extends Disposable {
};
}
private async _measureLatency(): Promise<number> {
private async _getExtensionHostProcessProxy(): Promise<ExtHostExtensionServiceShape | null> {
if (!this._extensionHostProcessProxy) {
return null;
}
const p = await this._extensionHostProcessProxy;
if (!p) {
return null;
}
return p.value;
}
private async _measureLatency(proxy: ExtHostExtensionServiceShape): Promise<number> {
const COUNT = 10;
const { value: proxy } = await this._extensionHostProcessProxy;
let sum = 0;
for (let i = 0; i < COUNT; i++) {
const sw = StopWatch.create(true);
......@@ -135,10 +149,9 @@ export class ExtensionHostProcessManager extends Disposable {
return (byteCount * 1000 * 8) / elapsedMillis;
}
private async _measureUp(): Promise<number> {
private async _measureUp(proxy: ExtHostExtensionServiceShape): Promise<number> {
const SIZE = 10 * 1024 * 1024; // 10MB
const { value: proxy } = await this._extensionHostProcessProxy;
let b = Buffer.alloc(SIZE, Math.random() % 256);
const sw = StopWatch.create(true);
await proxy.$test_up(b);
......@@ -146,10 +159,9 @@ export class ExtensionHostProcessManager extends Disposable {
return ExtensionHostProcessManager._convert(SIZE, sw.elapsed());
}
private async _measureDown(): Promise<number> {
private async _measureDown(proxy: ExtHostExtensionServiceShape): Promise<number> {
const SIZE = 10 * 1024 * 1024; // 10MB
const { value: proxy } = await this._extensionHostProcessProxy;
const sw = StopWatch.create(true);
await proxy.$test_down(SIZE);
sw.stop();
......@@ -171,9 +183,9 @@ export class ExtensionHostProcessManager extends Disposable {
this._register(this._extensionHostProcessRPCProtocol.onDidChangeResponsiveState((responsiveState: ResponsiveState) => this._onDidChangeResponsiveState.fire(responsiveState)));
const extHostContext: IExtHostContext = {
remoteAuthority: this._remoteAuthority,
getProxy: <T>(identifier: ProxyIdentifier<T>): T => this._extensionHostProcessRPCProtocol.getProxy(identifier),
set: <T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R => this._extensionHostProcessRPCProtocol.set(identifier, instance),
assertRegistered: (identifiers: ProxyIdentifier<any>[]): void => this._extensionHostProcessRPCProtocol.assertRegistered(identifiers),
getProxy: <T>(identifier: ProxyIdentifier<T>): T => this._extensionHostProcessRPCProtocol!.getProxy(identifier),
set: <T, R extends T>(identifier: ProxyIdentifier<T>, instance: R): R => this._extensionHostProcessRPCProtocol!.set(identifier, instance),
assertRegistered: (identifiers: ProxyIdentifier<any>[]): void => this._extensionHostProcessRPCProtocol!.assertRegistered(identifiers),
};
// Named customers
......@@ -199,10 +211,12 @@ export class ExtensionHostProcessManager extends Disposable {
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
}
public activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
return this._extensionHostProcessProxy.then((proxy) => {
return proxy.value.$activate(extension, activationEvent);
});
public async activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
return false;
}
return proxy.$activate(extension, activationEvent);
}
public activateByEvent(activationEvent: string): Promise<void> {
......@@ -241,7 +255,7 @@ export class ExtensionHostProcessManager extends Disposable {
return 0;
}
public resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority> {
public async resolveAuthority(remoteAuthority: string): Promise<ResolvedAuthority> {
const authorityPlusIndex = remoteAuthority.indexOf('+');
if (authorityPlusIndex === -1) {
// This authority does not need to be resolved, simply parse the port number
......@@ -252,15 +266,27 @@ export class ExtensionHostProcessManager extends Disposable {
port: parseInt(pieces[1], 10)
});
}
return this._extensionHostProcessProxy.then(proxy => proxy.value.$resolveAuthority(remoteAuthority));
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
throw new Error(`Cannot resolve authority`);
}
return proxy.$resolveAuthority(remoteAuthority);
}
public start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
return this._extensionHostProcessProxy.then(proxy => proxy.value.$startExtensionHost(enabledExtensionIds));
public async start(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
return;
}
return proxy.$startExtensionHost(enabledExtensionIds);
}
public deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
return this._extensionHostProcessProxy.then(proxy => proxy.value.$deltaExtensions(toAdd, toRemove));
public async deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
return;
}
return proxy.$deltaExtensions(toAdd, toRemove);
}
}
......@@ -328,7 +354,7 @@ interface ExtHostLatencyResult {
}
interface ExtHostLatencyProvider {
measure(): Promise<ExtHostLatencyResult>;
measure(): Promise<ExtHostLatencyResult | null>;
}
let providers: ExtHostLatencyProvider[] = [];
......
......@@ -62,7 +62,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
public _serviceBrand: any;
private readonly _extensionHostLogsLocation: URI;
private _registry: ExtensionDescriptionRegistry;
private readonly _registry: ExtensionDescriptionRegistry;
private readonly _installedExtensionsReady: Barrier;
private readonly _isDev: boolean;
private readonly _extensionsMessages: Map<string, IMessage[]>;
......@@ -103,7 +103,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
) {
super();
this._extensionHostLogsLocation = URI.file(path.join(this._environmentService.logsPath, `exthost${this._windowService.getCurrentWindowId()}`));
this._registry = null;
this._registry = new ExtensionDescriptionRegistry([]);
this._installedExtensionsReady = new Barrier();
this._isDev = !this._environmentService.isBuilt || this._environmentService.isExtensionDevelopment;
this._extensionsMessages = new Map<string, IMessage[]>();
......@@ -354,7 +354,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
if (shouldActivate) {
await Promise.all(
this._extensionHostProcessManagers.map(extHostManager => extHostManager.activate(extensionDescription.identifier, shouldActivateReason))
this._extensionHostProcessManagers.map(extHostManager => extHostManager.activate(extensionDescription.identifier, shouldActivateReason!))
).then(() => { });
}
}
......@@ -550,9 +550,9 @@ export class ExtensionService extends Disposable implements IExtensionService {
for (const extension of extensions) {
const extensionKey = ExtensionIdentifier.toKey(extension.identifier);
result[extension.identifier.value] = {
messages: this._extensionsMessages.get(extensionKey),
messages: this._extensionsMessages.get(extensionKey) || [],
activationTimes: this._extensionHostProcessActivationTimes.get(extensionKey),
runtimeErrors: this._extensionHostExtensionRuntimeErrors.get(extensionKey),
runtimeErrors: this._extensionHostExtensionRuntimeErrors.get(extensionKey) || [],
};
}
}
......@@ -613,7 +613,6 @@ export class ExtensionService extends Disposable implements IExtensionService {
}
private _handleExtensionPoints(allExtensions: IExtensionDescription[]): void {
this._registry = new ExtensionDescriptionRegistry([]);
const result = this._registry.deltaExtensions(allExtensions, []);
if (result.removedDueToLooping.length > 0) {
this._logOrShowMessage(Severity.Error, nls.localize('looping', "The following extensions contain dependency loops and have been disabled: {0}", result.removedDueToLooping.map(e => `'${e.identifier.value}'`).join(', ')));
......@@ -668,7 +667,11 @@ export class ExtensionService extends Disposable implements IExtensionService {
(enableProposedApiFor.length === 0 && 'enable-proposed-api' in this._environmentService.args);
for (const extension of allExtensions) {
const isExtensionUnderDevelopment = this._environmentService.isExtensionDevelopment && isEqualOrParent(extension.extensionLocation, this._environmentService.extensionDevelopmentLocationURI);
const isExtensionUnderDevelopment = (
this._environmentService.isExtensionDevelopment
&& this._environmentService.extensionDevelopmentLocationURI
&& isEqualOrParent(extension.extensionLocation, this._environmentService.extensionDevelopmentLocationURI)
);
// Do not disable extensions under development
if (!isExtensionUnderDevelopment) {
if (disabledExtensions.some(disabled => areSameExtensions(disabled, { id: extension.identifier.value }))) {
......@@ -730,7 +733,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
if (!this._extensionsMessages.has(extensionKey)) {
this._extensionsMessages.set(extensionKey, []);
}
this._extensionsMessages.get(extensionKey).push(msg);
this._extensionsMessages.get(extensionKey)!.push(msg);
const extension = this._registry.getExtensionDescription(msg.extensionId);
const strMsg = `[${msg.extensionId.value}]: ${msg.message}`;
......@@ -826,21 +829,7 @@ export class ExtensionService extends Disposable implements IExtensionService {
if (!this._extensionHostExtensionRuntimeErrors.has(extensionKey)) {
this._extensionHostExtensionRuntimeErrors.set(extensionKey, []);
}
this._extensionHostExtensionRuntimeErrors.get(extensionKey).push(err);
this._onDidChangeExtensionsStatus.fire([extensionId]);
}
public _addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
const extensionKey = ExtensionIdentifier.toKey(extensionId);
if (!this._extensionsMessages.has(extensionKey)) {
this._extensionsMessages.set(extensionKey, []);
}
this._extensionsMessages.get(extensionKey)!.push({
type: severity,
message: message,
extensionId: null,
extensionPointId: null
});
this._extensionHostExtensionRuntimeErrors.get(extensionKey)!.push(err);
this._onDidChangeExtensionsStatus.fire([extensionId]);
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册