Improve extension activation failure messages

This commit is contained in:
Sandeep Somavarapu
2019-03-15 10:19:21 +01:00
parent 48612205e1
commit d6058d77c0
5 changed files with 92 additions and 27 deletions

View File

@@ -36,7 +36,7 @@ import { ITreeItem, IRevealOptions } from 'vs/workbench/common/views';
import { IAdapterDescriptor, IConfig, ITerminalSettings } from 'vs/workbench/contrib/debug/common/debug';
import { ITextQueryBuilderOptions } from 'vs/workbench/contrib/search/common/queryBuilder';
import { ITerminalDimensions } from 'vs/workbench/contrib/terminal/common/terminal';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionDescription, ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
import { IRPCProtocol, createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId } from 'vs/workbench/services/extensions/node/proxyIdentifier';
import { IProgressOptions, IProgressStep } from 'vs/platform/progress/common/progress';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
@@ -575,7 +575,7 @@ export interface MainThreadExtensionServiceShape extends IDisposable {
$activateExtension(extensionId: ExtensionIdentifier, activationEvent: string | null): Promise<void>;
$onWillActivateExtension(extensionId: ExtensionIdentifier): void;
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string | null): void;
$onExtensionActivationFailed(extensionId: ExtensionIdentifier): void;
$onExtensionActivationError(extensionId: ExtensionIdentifier, error: ExtensionActivationError): Promise<void>;
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void;
}

View File

@@ -5,9 +5,9 @@
import * as nls from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import Severity from 'vs/base/common/severity';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ExtensionActivationError, MissingDependenciesError } from 'vs/workbench/services/extensions/common/extensions';
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
@@ -173,8 +173,7 @@ export class FailedExtension extends ActivatedExtension {
}
export interface IExtensionsActivatorHost {
showMessage(severity: Severity, message: string): void;
onExtensionActivationError(extensionId: ExtensionIdentifier, error: ExtensionActivationError): void;
actualActivateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension>;
}
@@ -283,7 +282,7 @@ export class ExtensionsActivator {
if (dep && dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Cannot activate extension '{0}' because it depends on extension '{1}', which failed to activate.", currentExtension.displayName || currentExtension.identifier.value, depId));
this._host.onExtensionActivationError(currentExtension.identifier, nls.localize('failedDep1', "Cannot activate extension '{0}' because it depends on extension '{1}', which failed to activate.", currentExtension.displayName || currentExtension.identifier.value, depId));
const error = new Error(`Dependency ${depId} failed to activate`);
(<any>error).detail = dep.activationFailedError;
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
@@ -306,7 +305,7 @@ export class ExtensionsActivator {
}
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Cannot activate extension '{0}' because it depends on extension '{1}', which is not installed or disabled. Please install or enable '{1}' and reload the window.", currentExtension.displayName || currentExtension.identifier.value, depId));
this._host.onExtensionActivationError(currentExtension.identifier, new MissingDependenciesError([depId]));
const error = new Error(`Unknown dependency '${depId}'`);
this._activatedExtensions.set(ExtensionIdentifier.toKey(currentExtension.identifier), new FailedExtension(error));
return;
@@ -373,7 +372,7 @@ export class ExtensionsActivator {
}
const newlyActivatingExtension = this._host.actualActivateExtension(extensionId, reason).then(undefined, (err) => {
this._host.showMessage(Severity.Error, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionId.value, err.message));
this._host.onExtensionActivationError(extensionId, nls.localize('activationError', "Activating extension '{0}' failed: {1}.", extensionId.value, err.message));
console.error('Activating extension `' + extensionId.value + '` failed: ', err.message);
console.log('Here is the error stack: ', err.stack);
// Treat the extension as being empty

View File

@@ -9,7 +9,6 @@ import { originalFSPath } from 'vs/base/common/resources';
import { Barrier } from 'vs/base/common/async';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { TernarySearchTree } from 'vs/base/common/map';
import Severity from 'vs/base/common/severity';
import { URI } from 'vs/base/common/uri';
import * as pfs from 'vs/base/node/pfs';
import { ILogService } from 'vs/platform/log/common/log';
@@ -20,7 +19,7 @@ import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionA
import { ExtHostLogService } from 'vs/workbench/api/node/extHostLogService';
import { ExtHostStorage } from 'vs/workbench/api/node/extHostStorage';
import { ExtHostWorkspace } from 'vs/workbench/api/node/extHostWorkspace';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionDescription, ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
@@ -208,19 +207,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
initData.hostExtensions.forEach((extensionId) => hostExtensions.add(ExtensionIdentifier.toKey(extensionId)));
this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, initData.hostExtensions, {
showMessage: (severity: Severity, message: string): void => {
this._mainThreadExtensionsProxy.$localShowMessage(severity, message);
switch (severity) {
case Severity.Error:
console.error(message);
break;
case Severity.Warning:
console.warn(message);
break;
default:
console.log(message);
}
onExtensionActivationError: (extensionId: ExtensionIdentifier, error: ExtensionActivationError): void => {
this._mainThreadExtensionsProxy.$onExtensionActivationError(extensionId, error);
},
actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
@@ -383,7 +371,6 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes);
return activatedExtension;
}, (err) => {
this._mainThreadExtensionsProxy.$onExtensionActivationFailed(extensionDescription.identifier);
this._logExtensionActivationTimes(extensionDescription, reason, 'failure');
throw err;
});