Merge VS Code 1.31.1 (#4283)

This commit is contained in:
Matt Irvine
2019-03-15 13:09:45 -07:00
committed by GitHub
parent 7d31575149
commit 86bac90001
1716 changed files with 53308 additions and 48375 deletions

View File

@@ -21,12 +21,13 @@ 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, checkProposedApiEnabled } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionDescription } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionDescriptionRegistry } from 'vs/workbench/services/extensions/node/extensionDescriptionRegistry';
import { connectProxyResolver } from 'vs/workbench/node/proxyResolver';
import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as errors from 'vs/base/common/errors';
import { ResolvedAuthority } from 'vs/platform/remote/common/remoteAuthorityResolver';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
class ExtensionMemento implements IExtensionMemento {
@@ -34,7 +35,7 @@ class ExtensionMemento implements IExtensionMemento {
private readonly _shared: boolean;
private readonly _storage: ExtHostStorage;
private readonly _init: Thenable<ExtensionMemento>;
private readonly _init: Promise<ExtensionMemento>;
private _value: { [n: string]: any; };
private readonly _storageListener: IDisposable;
@@ -55,7 +56,7 @@ class ExtensionMemento implements IExtensionMemento {
});
}
get whenReady(): Thenable<ExtensionMemento> {
get whenReady(): Promise<ExtensionMemento> {
return this._init;
}
@@ -67,7 +68,7 @@ class ExtensionMemento implements IExtensionMemento {
return value;
}
update(key: string, value: any): Thenable<boolean> {
update(key: string, value: any): Promise<boolean> {
this._value[key] = value;
return this._storage
.setValue(this._shared, this._id, this._value)
@@ -99,13 +100,13 @@ class ExtensionStoragePath {
workspaceValue(extension: IExtensionDescription): string {
if (this._value) {
return path.join(this._value, extension.id);
return path.join(this._value, extension.identifier.value);
}
return undefined;
}
globalValue(extension: IExtensionDescription): string {
return path.join(this._environment.globalStorageHome.fsPath, extension.id);
return path.join(this._environment.globalStorageHome.fsPath, extension.identifier.value.toLowerCase());
}
private async _getOrCreateWorkspaceStoragePath(): Promise<string> {
@@ -194,7 +195,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._registry = new ExtensionDescriptionRegistry(initData.extensions);
this._storage = new ExtHostStorage(this._extHostContext);
this._storagePath = new ExtensionStoragePath(initData.workspace, initData.environment);
this._activator = new ExtensionsActivator(this._registry, {
this._activator = new ExtensionsActivator(this._registry, initData.resolvedExtensions, {
showMessage: (severity: Severity, message: string): void => {
this._mainThreadExtensionsProxy.$localShowMessage(severity, message);
@@ -221,23 +222,30 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
this._started = false;
initializeExtensionApi(this, this._extensionApiFactory, this._registry).then(() => {
// Do this when extension service exists, but extensions are not being activated yet.
return connectProxyResolver(this._extHostWorkspace, this._extHostConfiguration, this, this._extHostLogService, this._mainThreadTelemetryProxy);
}).then(() => {
this._barrier.open();
});
this._initialize();
if (this._initData.autoStart) {
this._startExtensionHost();
}
}
private async _initialize(): Promise<void> {
try {
const configProvider = await this._extHostConfiguration.getConfigProvider();
await initializeExtensionApi(this, this._extensionApiFactory, this._registry, configProvider);
// Do this when extension service exists, but extensions are not being activated yet.
await connectProxyResolver(this._extHostWorkspace, configProvider, this, this._extHostLogService, this._mainThreadTelemetryProxy);
this._barrier.open();
} catch (err) {
errors.onUnexpectedError(err);
}
}
public async deactivateAll(): Promise<void> {
let allPromises: Thenable<void>[] = [];
let allPromises: Promise<void>[] = [];
try {
const allExtensions = this._registry.getAllExtensionDescriptions();
const allExtensionsIds = allExtensions.map(ext => ext.id);
const allExtensionsIds = allExtensions.map(ext => ext.identifier);
const activatedExtensions = allExtensionsIds.filter(id => this.isActivated(id));
allPromises = activatedExtensions.map((extensionId) => {
@@ -249,30 +257,30 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
await allPromises;
}
public isActivated(extensionId: string): boolean {
public isActivated(extensionId: ExtensionIdentifier): boolean {
if (this._barrier.isOpen()) {
return this._activator.isActivated(extensionId);
}
return false;
}
private _activateByEvent(activationEvent: string, startup: boolean): Thenable<void> {
private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
return this._activator.activateByEvent(activationEvent, reason);
}
private _activateById(extensionId: string, reason: ExtensionActivationReason): Thenable<void> {
private _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
return this._activator.activateById(extensionId, reason);
}
public activateByIdWithErrors(extensionId: string, reason: ExtensionActivationReason): Thenable<void> {
public activateByIdWithErrors(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
return this._activateById(extensionId, reason).then(() => {
const extension = this._activator.getActivatedExtension(extensionId);
if (extension.activationFailed) {
// activation failed => bubble up the error as the promise result
return Promise.reject(extension.activationFailedError);
}
return void 0;
return undefined;
});
}
@@ -280,7 +288,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return this._barrier.wait().then(_ => this._registry);
}
public getExtensionExports(extensionId: string): IExtensionAPI {
public getExtensionExports(extensionId: ExtensionIdentifier): IExtensionAPI {
if (this._barrier.isOpen()) {
return this._activator.getActivatedExtension(extensionId).exports;
} else {
@@ -303,8 +311,8 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return this._extensionPathIndex;
}
private _deactivate(extensionId: string): Thenable<void> {
let result = Promise.resolve(void 0);
private _deactivate(extensionId: ExtensionIdentifier): Promise<void> {
let result = Promise.resolve(undefined);
if (!this._barrier.isOpen()) {
return result;
@@ -322,9 +330,9 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// call deactivate if available
try {
if (typeof extension.module.deactivate === 'function') {
result = Promise.resolve(extension.module.deactivate()).then(null, (err) => {
result = Promise.resolve(extension.module.deactivate()).then(undefined, (err) => {
// TODO: Do something with err if this is not the shutdown case
return Promise.resolve(void 0);
return Promise.resolve(undefined);
});
}
} catch (err) {
@@ -341,21 +349,22 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return result;
}
public addMessage(extensionId: string, severity: Severity, message: string): void {
public addMessage(extensionId: ExtensionIdentifier, severity: Severity, message: string): void {
this._mainThreadExtensionsProxy.$addMessage(extensionId, severity, message);
}
// --- impl
private _activateExtension(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): Promise<ActivatedExtension> {
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
let activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
this._mainThreadExtensionsProxy.$onExtensionActivated(extensionDescription.id, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes);
return activatedExtension;
}, (err) => {
this._mainThreadExtensionsProxy.$onExtensionActivationFailed(extensionDescription.id);
this._mainThreadExtensionsProxy.$onExtensionActivationFailed(extensionDescription.identifier);
this._logExtensionActivationTimes(extensionDescription, reason, 'failure');
throw err;
});
@@ -394,23 +403,23 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return Promise.resolve(new EmptyExtension(ExtensionActivationTimes.NONE));
}
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.id} ${JSON.stringify(reason)}`);
this._extHostLogService.info(`ExtensionService#_doActivateExtension ${extensionDescription.identifier.value} ${JSON.stringify(reason)}`);
const activationTimesBuilder = new ExtensionActivationTimesBuilder(reason.startup);
return Promise.all<any>([
loadCommonJSModule(this._extHostLogService, extensionDescription.main, activationTimesBuilder),
this._loadExtensionContext(extensionDescription)
]).then(values => {
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.id, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
return ExtHostExtensionService._callActivate(this._extHostLogService, extensionDescription.identifier, <IExtensionModule>values[0], <IExtensionContext>values[1], activationTimesBuilder);
});
}
private _loadExtensionContext(extensionDescription: IExtensionDescription): Promise<IExtensionContext> {
let globalState = new ExtensionMemento(extensionDescription.id, true, this._storage);
let workspaceState = new ExtensionMemento(extensionDescription.id, false, this._storage);
let globalState = new ExtensionMemento(extensionDescription.identifier.value, true, this._storage);
let workspaceState = new ExtensionMemento(extensionDescription.identifier.value, false, this._storage);
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.id}`);
this._extHostLogService.trace(`ExtensionService#loadExtensionContext ${extensionDescription.identifier.value}`);
return Promise.all([
globalState.whenReady,
workspaceState.whenReady,
@@ -423,14 +432,14 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
subscriptions: [],
get extensionPath() { return extensionDescription.extensionLocation.fsPath; },
storagePath: this._storagePath.workspaceValue(extensionDescription),
get globalStoragePath(): string { checkProposedApiEnabled(extensionDescription); return that._storagePath.globalValue(extensionDescription); },
globalStoragePath: this._storagePath.globalValue(extensionDescription),
asAbsolutePath: (relativePath: string) => { return path.join(extensionDescription.extensionLocation.fsPath, relativePath); },
logPath: that._extHostLogService.getLogDirectory(extensionDescription.id)
logPath: that._extHostLogService.getLogDirectory(extensionDescription.identifier)
});
});
}
private static _callActivate(logService: ILogService, extensionId: string, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Thenable<ActivatedExtension> {
private static _callActivate(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<ActivatedExtension> {
// Make sure the extension's surface is not undefined
extensionModule = extensionModule || {
activate: undefined,
@@ -442,12 +451,12 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
});
}
private static _callActivateOptional(logService: ILogService, extensionId: string, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Thenable<IExtensionAPI> {
private static _callActivateOptional(logService: ILogService, extensionId: ExtensionIdentifier, extensionModule: IExtensionModule, context: IExtensionContext, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<IExtensionAPI> {
if (typeof extensionModule.activate === 'function') {
try {
activationTimesBuilder.activateCallStart();
logService.trace(`ExtensionService#_callActivateOptional ${extensionId}`);
const activateResult: Thenable<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
logService.trace(`ExtensionService#_callActivateOptional ${extensionId.value}`);
const activateResult: Promise<IExtensionAPI> = extensionModule.activate.apply(global, [context]);
activationTimesBuilder.activateCallStop();
activationTimesBuilder.activateResolveStart();
@@ -468,7 +477,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// Handle "eager" activation extensions
private _handleEagerExtensions(): Promise<void> {
this._activateByEvent('*', true).then(null, (err) => {
this._activateByEvent('*', true).then(undefined, (err) => {
console.error(err);
});
@@ -477,7 +486,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private _handleWorkspaceContainsEagerExtensions(workspace: IWorkspaceData): Promise<void> {
if (!workspace || workspace.folders.length === 0) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
return Promise.all(
@@ -490,15 +499,15 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private _handleWorkspaceContainsEagerExtension(workspace: IWorkspaceData, desc: IExtensionDescription): Promise<void> {
const activationEvents = desc.activationEvents;
if (!activationEvents) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
const fileNames: string[] = [];
const globPatterns: string[] = [];
for (let i = 0; i < activationEvents.length; i++) {
if (/^workspaceContains:/.test(activationEvents[i])) {
const fileNameOrGlob = activationEvents[i].substr('workspaceContains:'.length);
for (const activationEvent of activationEvents) {
if (/^workspaceContains:/.test(activationEvent)) {
const fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
globPatterns.push(fileNameOrGlob);
} else {
@@ -508,16 +517,16 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
if (fileNames.length === 0 && globPatterns.length === 0) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(workspace, desc.id, fileName))).then(() => { });
const globPatternPromise = this._activateIfGlobPatterns(desc.id, globPatterns);
const fileNamePromise = Promise.all(fileNames.map((fileName) => this._activateIfFileName(workspace, desc.identifier, fileName))).then(() => { });
const globPatternPromise = this._activateIfGlobPatterns(desc.identifier, globPatterns);
return Promise.all([fileNamePromise, globPatternPromise]).then(() => { });
}
private async _activateIfFileName(workspace: IWorkspaceData, extensionId: string, fileName: string): Promise<void> {
private async _activateIfFileName(workspace: IWorkspaceData, extensionId: ExtensionIdentifier, fileName: string): Promise<void> {
// find exact path
for (const { uri } of workspace.folders) {
@@ -525,7 +534,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// the file was found
return (
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${fileName}`))
.then(null, err => console.error(err))
.then(undefined, err => console.error(err))
);
}
}
@@ -533,11 +542,11 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
return undefined;
}
private async _activateIfGlobPatterns(extensionId: string, globPatterns: string[]): Promise<void> {
this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId}, entryPoint: workspaceContains`);
private async _activateIfGlobPatterns(extensionId: ExtensionIdentifier, globPatterns: string[]): Promise<void> {
this._extHostLogService.trace(`extensionHostMain#activateIfGlobPatterns: fileSearch, extension: ${extensionId.value}, entryPoint: workspaceContains`);
if (globPatterns.length === 0) {
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
const tokenSource = new CancellationTokenSource();
@@ -546,7 +555,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
const timer = setTimeout(async () => {
tokenSource.cancel();
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContainsTimeout:${globPatterns.join(',')}`))
.then(null, err => console.error(err));
.then(undefined, err => console.error(err));
}, ExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
let exists: boolean;
@@ -565,16 +574,28 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
// a file was found matching one of the glob patterns
return (
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${globPatterns.join(',')}`))
.then(null, err => console.error(err))
.then(undefined, err => console.error(err))
);
}
return Promise.resolve(void 0);
return Promise.resolve(undefined);
}
private _handleExtensionTests(): Promise<void> {
return this._doHandleExtensionTests().then(undefined, error => {
console.error(error); // ensure any error message makes it onto the console
return Promise.reject(error);
});
}
private _doHandleExtensionTests(): Promise<void> {
if (!this._initData.environment.extensionTestsPath || !this._initData.environment.extensionDevelopmentLocationURI) {
return Promise.resolve(null);
return Promise.resolve(undefined);
}
if (this._initData.autoStart) {
return Promise.resolve(undefined); // https://github.com/Microsoft/vscode/issues/66936
}
// Require the test runner via node require from the provided path
@@ -593,11 +614,11 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
if (error) {
e(error.toString());
} else {
c(null);
c(undefined);
}
// after tests have run, we shutdown the host
this._gracefulExit(failures && failures > 0 ? 1 /* ERROR */ : 0 /* OK */);
this._gracefulExit(error || (typeof failures === 'number' && failures > 0) ? 1 /* ERROR */ : 0 /* OK */);
});
});
}
@@ -616,7 +637,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
setTimeout(() => this._nativeExit(code), 500);
}
private _startExtensionHost(): Thenable<void> {
private _startExtensionHost(): Promise<void> {
if (this._started) {
throw new Error(`Extension host is already started!`);
}
@@ -636,17 +657,61 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
throw new Error(`Not implemented`);
}
public $startExtensionHost(enabledExtensionIds: string[]): Thenable<void> {
public $startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void> {
this._registry.keepOnly(enabledExtensionIds);
return this._startExtensionHost();
}
public $activateByEvent(activationEvent: string): Thenable<void> {
public $activateByEvent(activationEvent: string): Promise<void> {
return (
this._barrier.wait()
.then(_ => this._activateByEvent(activationEvent, false))
);
}
public $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void> {
return (
this._barrier.wait()
.then(_ => this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent)))
);
}
public async $deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void> {
toAdd.forEach((extension) => (<any>extension).extensionLocation = URI.revive(extension.extensionLocation));
const trie = await this.getExtensionPathIndex();
await Promise.all(toRemove.map(async (extensionId) => {
const extensionDescription = this._registry.getExtensionDescription(extensionId);
if (!extensionDescription) {
return;
}
const realpath = await pfs.realpath(extensionDescription.extensionLocation.fsPath);
trie.delete(URI.file(realpath).fsPath);
}));
await Promise.all(toAdd.map(async (extensionDescription) => {
const realpath = await pfs.realpath(extensionDescription.extensionLocation.fsPath);
trie.set(URI.file(realpath).fsPath, extensionDescription);
}));
this._registry.deltaExtensions(toAdd, toRemove);
return Promise.resolve(undefined);
}
public async $test_latency(n: number): Promise<number> {
return n;
}
public async $test_up(b: Buffer): Promise<number> {
return b.length;
}
public async $test_down(size: number): Promise<Buffer> {
let b = Buffer.alloc(size, Math.random() % 256);
return b;
}
}
function loadCommonJSModule<T>(logService: ILogService, modulePath: string, activationTimesBuilder: ExtensionActivationTimesBuilder): Promise<T> {
@@ -680,7 +745,7 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
}
*/
let event = {
id: extensionDescription.id,
id: extensionDescription.identifier.value,
name: extensionDescription.name,
extensionVersion: extensionDescription.version,
publisherDisplayName: extensionDescription.publisher,
@@ -690,4 +755,4 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
};
return event;
}
}