Skip to content

Commit

Permalink
#48430 Do not activate optional dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
sandy081 committed Jul 10, 2018
1 parent 183c33a commit ca44075
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 25 deletions.
48 changes: 26 additions & 22 deletions src/vs/workbench/api/node/extHostExtensionActivator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -237,35 +237,39 @@ export class ExtensionsActivator {
* semantics: `redExtensions` must wait for `greenExtensions`.
*/
private _handleActivateRequest(currentExtension: IExtensionDescription, greenExtensions: { [id: string]: IExtensionDescription; }, redExtensions: IExtensionDescription[]): void {
let depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies);
let dependencies = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies);
let currentExtensionGetsGreenLight = true;

for (let j = 0, lenJ = depIds.length; j < lenJ; j++) {
let depId = depIds[j];
let depDesc = this._registry.getExtensionDescription(depId);
for (let j = 0, lenJ = dependencies.length; j < lenJ; j++) {
const dependency = dependencies[j];
const depId: string = typeof dependency === 'string' ? dependency : dependency.optional ? null : dependency.id;

if (!depDesc) {
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Extension '{1}' failed to activate. Reason: unknown dependency '{0}'.", depId, currentExtension.id));
const error = new Error(`Unknown dependency '${depId}'`);
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
return;
}
if (depId) {
let depDesc = this._registry.getExtensionDescription(depId);

if (hasOwnProperty.call(this._activatedExtensions, depId)) {
let dep = this._activatedExtensions[depId];
if (dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Extension '{1}' failed to activate. Reason: dependency '{0}' failed to activate.", depId, currentExtension.id));
const error = new Error(`Dependency ${depId} failed to activate`);
(<any>error).detail = dep.activationFailedError;
if (!depDesc) {
// Error condition 1: unknown dependency
this._host.showMessage(Severity.Error, nls.localize('unknownDep', "Extension '{1}' failed to activate. Reason: unknown dependency '{0}'.", depId, currentExtension.id));
const error = new Error(`Unknown dependency '${depId}'`);
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
return;
}
} else {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[depId] = depDesc;

if (hasOwnProperty.call(this._activatedExtensions, depId)) {
let dep = this._activatedExtensions[depId];
if (dep.activationFailed) {
// Error condition 2: a dependency has already failed activation
this._host.showMessage(Severity.Error, nls.localize('failedDep1', "Extension '{1}' failed to activate. Reason: dependency '{0}' failed to activate.", depId, currentExtension.id));
const error = new Error(`Dependency ${depId} failed to activate`);
(<any>error).detail = dep.activationFailedError;
this._activatedExtensions[currentExtension.id] = new FailedExtension(error);
return;
}
} else {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[depId] = depDesc;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/vs/workbench/services/extensions/common/extensions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export interface IExtensionDescription {
readonly isBuiltin: boolean;
readonly isUnderDevelopment: boolean;
readonly extensionLocation: URI;
readonly extensionDependencies?: string[];
readonly extensionDependencies?: Array<string | { id: string, optional?: boolean }>;
readonly activationEvents?: string[];
readonly engines: {
vscode: string;
Expand Down
24 changes: 22 additions & 2 deletions src/vs/workbench/services/extensions/node/extensionPoints.ts
Original file line number Diff line number Diff line change
Expand Up @@ -387,8 +387,8 @@ class ExtensionManifestValidator extends ExtensionManifestHandler {
return false;
}
if (typeof extensionDescription.extensionDependencies !== 'undefined') {
if (!ExtensionManifestValidator._isStringArray(extensionDescription.extensionDependencies)) {
notices.push(nls.localize('extensionDescription.extensionDependencies', "property `{0}` can be omitted or must be of type `string[]`", 'extensionDependencies'));
if (!ExtensionManifestValidator._isExtensionDependencyArray(extensionDescription.extensionDependencies)) {
notices.push(nls.localize('extensionDescription.extensionDependencies', "property `{0}` can be omitted or must be an array of type `string` or `{id: string, optional: boolean}`", 'extensionDependencies'));
return false;
}
}
Expand Down Expand Up @@ -433,6 +433,26 @@ class ExtensionManifestValidator extends ExtensionManifestHandler {
}
return true;
}

private static _isExtensionDependencyArray(arr: any[]): boolean {
if (!Array.isArray(arr)) {
return false;
}
for (let i = 0, len = arr.length; i < len; i++) {
if (typeof arr[i] !== 'string') {
if (typeof arr[i] !== 'object') {
return false;
}
if (typeof arr[i]['id'] !== 'string') {
return false;
}
if (typeof arr[i]['optional'] !== 'undefined' && typeof arr[i]['optional'] !== 'boolean') {
return false;
}
}
}
return true;
}
}

export class ExtensionScannerInput {
Expand Down

0 comments on commit ca44075

Please sign in to comment.