提交 715b6c57 编写于 作者: C Christof Marti

Add extension id that triggered the activation event

上级 c8fa927f
......@@ -18,6 +18,7 @@ import { IWindowService } from 'vs/platform/windows/common/windows';
import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
@extHostNamedCustomer(MainContext.MainThreadExtensionService)
export class MainThreadExtensionService implements MainThreadExtensionServiceShape {
......@@ -46,14 +47,14 @@ export class MainThreadExtensionService implements MainThreadExtensionServiceSha
public dispose(): void {
}
$activateExtension(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void> {
return this._extensionService._activateById(extensionId, activationEvent);
$activateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
return this._extensionService._activateById(extensionId, reason);
}
$onWillActivateExtension(extensionId: ExtensionIdentifier): void {
this._extensionService._onWillActivateExtension(extensionId);
}
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
this._extensionService._onDidActivateExtension(extensionId, startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent);
$onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void {
this._extensionService._onDidActivateExtension(extensionId, codeLoadingTime, activateCallTime, activateResolvedTime, activationReason);
}
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, data: SerializedError): void {
const error = new Error();
......
......@@ -274,12 +274,12 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
getExtension(extensionId: string): Extension<any> | undefined {
const desc = extensionRegistry.getExtensionDescription(extensionId);
if (desc) {
return new Extension(extensionService, desc, extensionKind);
return new Extension(extensionService, extension.identifier, desc, extensionKind);
}
return undefined;
},
get all(): Extension<any>[] {
return extensionRegistry.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, desc, extensionKind));
return extensionRegistry.getAllExtensionDescriptions().map((desc) => new Extension(extensionService, extension.identifier, desc, extensionKind));
},
get onDidChange() {
return extensionRegistry.onDidChange;
......@@ -914,6 +914,7 @@ export function createApiFactoryAndRegisterActors(accessor: ServicesAccessor): I
class Extension<T> implements vscode.Extension<T> {
private _extensionService: IExtHostExtensionService;
private _originExtensionId: ExtensionIdentifier;
private _identifier: ExtensionIdentifier;
readonly id: string;
......@@ -921,8 +922,9 @@ class Extension<T> implements vscode.Extension<T> {
readonly packageJSON: IExtensionDescription;
readonly extensionKind: vscode.ExtensionKind;
constructor(extensionService: IExtHostExtensionService, description: IExtensionDescription, kind: extHostTypes.ExtensionKind) {
constructor(extensionService: IExtHostExtensionService, originExtensionId: ExtensionIdentifier, description: IExtensionDescription, kind: extHostTypes.ExtensionKind) {
this._extensionService = extensionService;
this._originExtensionId = originExtensionId;
this._identifier = description.identifier;
this.id = description.identifier.value;
this.extensionPath = path.normalize(originalFSPath(description.extensionLocation));
......@@ -942,6 +944,6 @@ class Extension<T> implements vscode.Extension<T> {
}
activate(): Thenable<T> {
return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false)).then(() => this.exports);
return this._extensionService.activateByIdWithErrors(this._identifier, new ExtensionActivatedByAPI(false, this._originExtensionId)).then(() => this.exports);
}
}
......@@ -46,6 +46,7 @@ import { ExtensionActivationError } from 'vs/workbench/services/extensions/commo
import { createExtHostContextProxyIdentifier as createExtId, createMainContextProxyIdentifier as createMainId, IRPCProtocol } from 'vs/workbench/services/extensions/common/proxyIdentifier';
import * as search from 'vs/workbench/services/search/common/search';
import { SaveReason } from 'vs/workbench/services/textfile/common/textfiles';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
export interface IEnvironment {
isExtensionDevelopmentDebug: boolean;
......@@ -645,9 +646,9 @@ export interface MainThreadTaskShape extends IDisposable {
}
export interface MainThreadExtensionServiceShape extends IDisposable {
$activateExtension(extensionId: ExtensionIdentifier, activationEvent: string | null): Promise<void>;
$activateExtension(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void>;
$onWillActivateExtension(extensionId: ExtensionIdentifier): void;
$onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string | null): void;
$onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void;
$onExtensionActivationError(extensionId: ExtensionIdentifier, error: ExtensionActivationError): Promise<void>;
$onExtensionRuntimeError(extensionId: ExtensionIdentifier, error: SerializedError): void;
$onExtensionHostExit(code: number): void;
......@@ -879,7 +880,7 @@ export interface ExtHostExtensionServiceShape {
$resolveAuthority(remoteAuthority: string, resolveAttempt: number): Promise<IResolveAuthorityResult>;
$startExtensionHost(enabledExtensionIds: ExtensionIdentifier[]): Promise<void>;
$activateByEvent(activationEvent: string): Promise<void>;
$activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<boolean>;
$activate(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean>;
$setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
$deltaExtensions(toAdd: IExtensionDescription[], toRemove: ExtensionIdentifier[]): Promise<void>;
......
......@@ -164,18 +164,22 @@ export interface IExtensionsActivatorHost {
export class ExtensionActivatedByEvent {
constructor(
public readonly startup: boolean,
public readonly extensionId: ExtensionIdentifier,
public readonly activationEvent: string
) { }
}
export class ExtensionActivatedByAPI {
constructor(
public readonly startup: boolean
public readonly startup: boolean,
public readonly extensionId: ExtensionIdentifier
) { }
}
export type ExtensionActivationReason = ExtensionActivatedByEvent | ExtensionActivatedByAPI;
type ActivationIdAndReason = { id: ExtensionIdentifier, reason: ExtensionActivationReason };
export class ExtensionsActivator {
private readonly _registry: ExtensionDescriptionRegistry;
......@@ -217,12 +221,15 @@ export class ExtensionsActivator {
return activatedExtension;
}
public activateByEvent(activationEvent: string, reason: ExtensionActivationReason): Promise<void> {
public activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
if (this._alreadyActivatedEvents[activationEvent]) {
return NO_OP_VOID_PROMISE;
}
const activateExtensions = this._registry.getExtensionDescriptionsForActivationEvent(activationEvent);
return this._activateExtensions(activateExtensions.map(e => e.identifier), reason).then(() => {
return this._activateExtensions(activateExtensions.map(e => ({
id: e.identifier,
reason: new ExtensionActivatedByEvent(startup, e.identifier, activationEvent)
}))).then(() => {
this._alreadyActivatedEvents[activationEvent] = true;
});
}
......@@ -233,20 +240,23 @@ export class ExtensionsActivator {
throw new Error('Extension `' + extensionId + '` is not known');
}
return this._activateExtensions([desc.identifier], reason);
return this._activateExtensions([{
id: desc.identifier,
reason
}]);
}
/**
* Handle semantics related to dependencies for `currentExtension`.
* semantics: `redExtensions` must wait for `greenExtensions`.
*/
private _handleActivateRequest(currentExtensionId: ExtensionIdentifier, greenExtensions: { [id: string]: ExtensionIdentifier; }, redExtensions: ExtensionIdentifier[]): void {
if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(currentExtensionId))) {
greenExtensions[ExtensionIdentifier.toKey(currentExtensionId)] = currentExtensionId;
private _handleActivateRequest(currentActivation: ActivationIdAndReason, greenExtensions: { [id: string]: ActivationIdAndReason; }, redExtensions: ActivationIdAndReason[]): void {
if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(currentActivation.id))) {
greenExtensions[ExtensionIdentifier.toKey(currentActivation.id)] = currentActivation;
return;
}
const currentExtension = this._registry.getExtensionDescription(currentExtensionId)!;
const currentExtension = this._registry.getExtensionDescription(currentActivation.id)!;
const depIds = (typeof currentExtension.extensionDependencies === 'undefined' ? [] : currentExtension.extensionDependencies);
let currentExtensionGetsGreenLight = true;
......@@ -276,7 +286,10 @@ export class ExtensionsActivator {
if (this._hostExtensionsMap.has(ExtensionIdentifier.toKey(depId))) {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[ExtensionIdentifier.toKey(depId)] = this._hostExtensionsMap.get(ExtensionIdentifier.toKey(depId))!;
greenExtensions[ExtensionIdentifier.toKey(depId)] = {
id: this._hostExtensionsMap.get(ExtensionIdentifier.toKey(depId))!,
reason: currentActivation.reason
};
continue;
}
......@@ -284,7 +297,10 @@ export class ExtensionsActivator {
if (depDesc) {
// must first wait for the dependency to activate
currentExtensionGetsGreenLight = false;
greenExtensions[ExtensionIdentifier.toKey(depId)] = depDesc.identifier;
greenExtensions[ExtensionIdentifier.toKey(depId)] = {
id: depDesc.identifier,
reason: currentActivation.reason
};
continue;
}
......@@ -296,33 +312,33 @@ export class ExtensionsActivator {
}
if (currentExtensionGetsGreenLight) {
greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentExtensionId;
greenExtensions[ExtensionIdentifier.toKey(currentExtension.identifier)] = currentActivation;
} else {
redExtensions.push(currentExtensionId);
redExtensions.push(currentActivation);
}
}
private _activateExtensions(extensionIds: ExtensionIdentifier[], reason: ExtensionActivationReason): Promise<void> {
// console.log('_activateExtensions: ', extensionIds.map(p => p.value));
if (extensionIds.length === 0) {
private _activateExtensions(extensions: ActivationIdAndReason[]): Promise<void> {
// console.log('_activateExtensions: ', extensions.map(p => p.id.value));
if (extensions.length === 0) {
return Promise.resolve(undefined);
}
extensionIds = extensionIds.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p)));
if (extensionIds.length === 0) {
extensions = extensions.filter((p) => !this._activatedExtensions.has(ExtensionIdentifier.toKey(p.id)));
if (extensions.length === 0) {
return Promise.resolve(undefined);
}
const greenMap: { [id: string]: ExtensionIdentifier; } = Object.create(null),
red: ExtensionIdentifier[] = [];
const greenMap: { [id: string]: ActivationIdAndReason; } = Object.create(null),
red: ActivationIdAndReason[] = [];
for (let i = 0, len = extensionIds.length; i < len; i++) {
this._handleActivateRequest(extensionIds[i], greenMap, red);
for (let i = 0, len = extensions.length; i < len; i++) {
this._handleActivateRequest(extensions[i], greenMap, red);
}
// Make sure no red is also green
for (let i = 0, len = red.length; i < len; i++) {
const redExtensionKey = ExtensionIdentifier.toKey(red[i]);
const redExtensionKey = ExtensionIdentifier.toKey(red[i].id);
if (greenMap[redExtensionKey]) {
delete greenMap[redExtensionKey];
}
......@@ -330,16 +346,16 @@ export class ExtensionsActivator {
const green = Object.keys(greenMap).map(id => greenMap[id]);
// console.log('greenExtensions: ', green.map(p => p.id));
// console.log('redExtensions: ', red.map(p => p.id));
// console.log('greenExtensions: ', green.map(p => p.id.value));
// console.log('redExtensions: ', red.map(p => p.id.value));
if (red.length === 0) {
// Finally reached only leafs!
return Promise.all(green.map((p) => this._activateExtension(p, reason))).then(_ => undefined);
return Promise.all(green.map((p) => this._activateExtension(p.id, p.reason))).then(_ => undefined);
}
return this._activateExtensions(green, reason).then(_ => {
return this._activateExtensions(red, reason);
return this._activateExtensions(green).then(_ => {
return this._activateExtensions(red);
});
}
......
......@@ -13,7 +13,7 @@ import { URI } from 'vs/base/common/uri';
import { ILogService } from 'vs/platform/log/common/log';
import { ExtHostExtensionServiceShape, IInitData, MainContext, MainThreadExtensionServiceShape, MainThreadTelemetryShape, MainThreadWorkspaceShape, IResolveAuthorityResult } from 'vs/workbench/api/common/extHost.protocol';
import { ExtHostConfiguration, IExtHostConfiguration } from 'vs/workbench/api/common/extHostConfiguration';
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByAPI, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
import { ActivatedExtension, EmptyExtension, ExtensionActivatedByEvent, ExtensionActivationReason, ExtensionActivationTimes, ExtensionActivationTimesBuilder, ExtensionsActivator, IExtensionAPI, IExtensionModule, HostExtension, ExtensionActivationTimesFragment } from 'vs/workbench/api/common/extHostExtensionActivator';
import { ExtHostStorage, IExtHostStorage } from 'vs/workbench/api/common/extHostStorage';
import { ExtHostWorkspace, IExtHostWorkspace } from 'vs/workbench/api/common/extHostWorkspace';
import { ExtensionActivationError } from 'vs/workbench/services/extensions/common/extensions';
......@@ -60,6 +60,7 @@ type TelemetryActivationEventFragment = {
activationEvents: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
isBuiltin: { classification: 'SystemMetaData', purpose: 'FeatureInsight', isMeasurement: true };
reason: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
reasonId: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
};
export abstract class AbstractExtHostExtensionService implements ExtHostExtensionServiceShape {
......@@ -139,8 +140,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
actualActivateExtension: async (extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<ActivatedExtension> => {
if (hostExtensions.has(ExtensionIdentifier.toKey(extensionId))) {
const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
await this._mainThreadExtensionsProxy.$activateExtension(extensionId, activationEvent);
await this._mainThreadExtensionsProxy.$activateExtension(extensionId, reason);
return new HostExtension();
}
const extensionDescription = this._registry.getExtensionDescription(extensionId)!;
......@@ -195,8 +195,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
}
private _activateByEvent(activationEvent: string, startup: boolean): Promise<void> {
const reason = new ExtensionActivatedByEvent(startup, activationEvent);
return this._activator.activateByEvent(activationEvent, reason);
return this._activator.activateByEvent(activationEvent, startup);
}
private _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
......@@ -285,8 +284,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
this._mainThreadExtensionsProxy.$onWillActivateExtension(extensionDescription.identifier);
return this._doActivateExtension(extensionDescription, reason).then((activatedExtension) => {
const activationTimes = activatedExtension.activationTimes;
const activationEvent = (reason instanceof ExtensionActivatedByEvent ? reason.activationEvent : null);
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.startup, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, activationEvent);
this._mainThreadExtensionsProxy.$onDidActivateExtension(extensionDescription.identifier, activationTimes.codeLoadingTime, activationTimes.activateCallTime, activationTimes.activateResolvedTime, reason);
this._logExtensionActivationTimes(extensionDescription, reason, 'success', activationTimes);
return activatedExtension;
}, (err) => {
......@@ -467,7 +465,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
if (await this._hostUtils.exists(path.join(URI.revive(uri).fsPath, fileName))) {
// the file was found
return (
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${fileName}`))
this._activateById(extensionId, new ExtensionActivatedByEvent(true, extensionId, `workspaceContains:${fileName}`))
.then(undefined, err => console.error(err))
);
}
......@@ -488,7 +486,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
const timer = setTimeout(async () => {
tokenSource.cancel();
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContainsTimeout:${globPatterns.join(',')}`))
this._activateById(extensionId, new ExtensionActivatedByEvent(true, extensionId, `workspaceContainsTimeout:${globPatterns.join(',')}`))
.then(undefined, err => console.error(err));
}, AbstractExtHostExtensionService.WORKSPACE_CONTAINS_TIMEOUT);
......@@ -507,7 +505,7 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
if (exists) {
// a file was found matching one of the glob patterns
return (
this._activateById(extensionId, new ExtensionActivatedByEvent(true, `workspaceContains:${globPatterns.join(',')}`))
this._activateById(extensionId, new ExtensionActivatedByEvent(true, extensionId, `workspaceContains:${globPatterns.join(',')}`))
.then(undefined, err => console.error(err))
);
}
......@@ -681,13 +679,13 @@ export abstract class AbstractExtHostExtensionService implements ExtHostExtensio
);
}
public async $activate(extensionId: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
public async $activate(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean> {
await this._readyToRunExtensions.wait();
if (!this._registry.getExtensionDescription(extensionId)) {
// unknown extension => ignore
return false;
}
await this._activateById(extensionId, new ExtensionActivatedByEvent(false, activationEvent));
await this._activateById(extensionId, reason);
return true;
}
......@@ -743,12 +741,11 @@ type TelemetryActivationEvent = {
activationEvents: string | null;
isBuiltin: boolean;
reason: string;
reasonId: string;
};
function getTelemetryActivationEvent(extensionDescription: IExtensionDescription, reason: ExtensionActivationReason): TelemetryActivationEvent {
const reasonStr = reason instanceof ExtensionActivatedByEvent ? reason.activationEvent :
reason instanceof ExtensionActivatedByAPI ? 'api' :
'';
const reasonStr = 'activationEvent' in reason ? reason.activationEvent : 'api';
const event = {
id: extensionDescription.identifier.value,
name: extensionDescription.name,
......@@ -756,7 +753,8 @@ function getTelemetryActivationEvent(extensionDescription: IExtensionDescription
publisherDisplayName: extensionDescription.publisher,
activationEvents: extensionDescription.activationEvents ? extensionDescription.activationEvents.join(',') : null,
isBuiltin: extensionDescription.isBuiltin,
reason: reasonStr
reason: reasonStr,
reasonId: reason.extensionId.value,
};
return event;
......
......@@ -308,7 +308,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
const activationTimes = element.status.activationTimes!;
let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime;
data.activationTime.textContent = activationTimes.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
data.actionbar.clear();
if (element.unresponsiveProfile) {
......@@ -319,43 +319,45 @@ export class RuntimeExtensionsEditor extends BaseEditor {
}
let title: string;
if (activationTimes.activationEvent === '*') {
title = nls.localize('starActivation', "Activated on start-up");
} else if (/^workspaceContains:/.test(activationTimes.activationEvent)) {
let fileNameOrGlob = activationTimes.activationEvent.substr('workspaceContains:'.length);
const activationId = activationTimes.activationReason.extensionId.value;
const activationEvent = 'activationEvent' in activationTimes.activationReason ? activationTimes.activationReason.activationEvent : 'api';
if (activationEvent === '*') {
title = nls.localize('starActivation', "Activated by {0} on start-up", activationId);
} else if (/^workspaceContains:/.test(activationEvent)) {
let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
title = nls.localize({
key: 'workspaceContainsGlobActivation',
comment: [
'{0} will be a glob pattern'
]
}, "Activated because a file matching {0} exists in your workspace", fileNameOrGlob);
}, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId);
} else {
title = nls.localize({
key: 'workspaceContainsFileActivation',
comment: [
'{0} will be a file name'
]
}, "Activated because file {0} exists in your workspace", fileNameOrGlob);
}, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId);
}
} else if (/^workspaceContainsTimeout:/.test(activationTimes.activationEvent)) {
const glob = activationTimes.activationEvent.substr('workspaceContainsTimeout:'.length);
} else if (/^workspaceContainsTimeout:/.test(activationEvent)) {
const glob = activationEvent.substr('workspaceContainsTimeout:'.length);
title = nls.localize({
key: 'workspaceContainsTimeout',
comment: [
'{0} will be a glob pattern'
]
}, "Activated because searching for {0} took too long", glob);
} else if (/^onLanguage:/.test(activationTimes.activationEvent)) {
let language = activationTimes.activationEvent.substr('onLanguage:'.length);
title = nls.localize('languageActivation', "Activated because you opened a {0} file", language);
}, "Activated by {1} because searching for {0} took too long", glob, activationId);
} else if (/^onLanguage:/.test(activationEvent)) {
let language = activationEvent.substr('onLanguage:'.length);
title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId);
} else {
title = nls.localize({
key: 'workspaceGenericActivation',
comment: [
'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.'
]
}, "Activated on {0}", activationTimes.activationEvent);
}, "Activated by {1} on {0}", activationEvent, activationId);
}
data.activationTime.title = title;
......
......@@ -177,10 +177,11 @@ class PerfModelContentProvider implements ITextModelContentProvider {
if (!times) {
continue;
}
if (times.startup) {
eager.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
const event = 'activationEvent' in times.activationReason ? times.activationReason.activationEvent : 'api';
if (times.activationReason.startup) {
eager.push([id, times.activationReason.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, event, times.activationReason.extensionId.value]);
} else {
normal.push([id, times.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, times.activationEvent]);
normal.push([id, times.activationReason.startup, times.codeLoadingTime, times.activateCallTime, times.activateResolvedTime, event, times.activationReason.extensionId.value]);
}
}
......@@ -188,7 +189,7 @@ class PerfModelContentProvider implements ITextModelContentProvider {
if (table.length > 0) {
md.heading(2, 'Extension Activation Stats');
md.table(
['Extension', 'Eager', 'Load Code', 'Call Activate', 'Finish Activate', 'Event'],
['Extension', 'Eager', 'Load Code', 'Call Activate', 'Finish Activate', 'Event', 'By'],
table
);
}
......
......@@ -24,6 +24,7 @@ import { ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensio
import { IFileService } from 'vs/platform/files/common/files';
import { parseExtensionDevOptions } from 'vs/workbench/services/extensions/common/extensionDevOptions';
import { IProductService } from 'vs/platform/product/common/productService';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
const hasOwnProperty = Object.hasOwnProperty;
const NO_OP_VOID_PROMISE = Promise.resolve<void>(undefined);
......@@ -406,9 +407,9 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
}
}
public async _activateById(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void> {
public async _activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void> {
const results = await Promise.all(
this._extensionHostProcessManagers.map(manager => manager.activate(extensionId, activationEvent))
this._extensionHostProcessManagers.map(manager => manager.activate(extensionId, reason))
);
const activated = results.some(e => e);
if (!activated) {
......@@ -420,8 +421,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
this._extensionHostActiveExtensions.set(ExtensionIdentifier.toKey(extensionId), extensionId);
}
public _onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void {
this._extensionHostProcessActivationTimes.set(ExtensionIdentifier.toKey(extensionId), new ActivationTimes(startup, codeLoadingTime, activateCallTime, activateResolvedTime, activationEvent));
public _onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void {
this._extensionHostProcessActivationTimes.set(ExtensionIdentifier.toKey(extensionId), new ActivationTimes(codeLoadingTime, activateCallTime, activateResolvedTime, activationReason));
this._onDidChangeExtensionsStatus.fire([extensionId]);
}
......
......@@ -26,6 +26,7 @@ import { IUntitledResourceInput } from 'vs/workbench/common/editor';
import { StopWatch } from 'vs/base/common/stopwatch';
import { VSBuffer } from 'vs/base/common/buffer';
import { IExtensionHostStarter } from 'vs/workbench/services/extensions/common/extensions';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
// Enable to see detailed message communication between window and extension host
const LOG_EXTENSION_HOST_COMMUNICATION = false;
......@@ -213,12 +214,12 @@ export class ExtensionHostProcessManager extends Disposable {
return this._extensionHostProcessRPCProtocol.getProxy(ExtHostContext.ExtHostExtensionService);
}
public async activate(extension: ExtensionIdentifier, activationEvent: string): Promise<boolean> {
public async activate(extension: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<boolean> {
const proxy = await this._getExtensionHostProcessProxy();
if (!proxy) {
return false;
}
return proxy.$activate(extension, activationEvent);
return proxy.$activate(extension, reason);
}
public activateByEvent(activationEvent: string): Promise<void> {
......
......@@ -11,6 +11,7 @@ import { IExtensionPoint } from 'vs/workbench/services/extensions/common/extensi
import { ExtensionIdentifier, IExtension, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
import { ExtensionActivationReason } from 'vs/workbench/api/common/extHostExtensionActivator';
export const nullExtensionDescription = Object.freeze(<IExtensionDescription>{
identifier: new ExtensionIdentifier('nullExtensionDescription'),
......@@ -99,11 +100,10 @@ export type ProfileSegmentId = string | 'idle' | 'program' | 'gc' | 'self';
export class ActivationTimes {
constructor(
public readonly startup: boolean,
public readonly codeLoadingTime: number,
public readonly activateCallTime: number,
public readonly activateResolvedTime: number,
public readonly activationEvent: string
public readonly activationReason: ExtensionActivationReason
) {
}
}
......@@ -226,9 +226,9 @@ export interface IExtensionService {
setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void>;
_logOrShowMessage(severity: Severity, msg: string): void;
_activateById(extensionId: ExtensionIdentifier, activationEvent: string): Promise<void>;
_activateById(extensionId: ExtensionIdentifier, reason: ExtensionActivationReason): Promise<void>;
_onWillActivateExtension(extensionId: ExtensionIdentifier): void;
_onDidActivateExtension(extensionId: ExtensionIdentifier, startup: boolean, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationEvent: string): void;
_onDidActivateExtension(extensionId: ExtensionIdentifier, codeLoadingTime: number, activateCallTime: number, activateResolvedTime: number, activationReason: ExtensionActivationReason): void;
_onExtensionRuntimeError(extensionId: ExtensionIdentifier, err: Error): void;
_onExtensionHostExit(code: number): void;
}
......@@ -276,9 +276,9 @@ export class NullExtensionService implements IExtensionService {
canAddExtension(): boolean { return false; }
canRemoveExtension(): boolean { return false; }
_logOrShowMessage(_severity: Severity, _msg: string): void { }
_activateById(_extensionId: ExtensionIdentifier, _activationEvent: string): Promise<void> { return Promise.resolve(); }
_activateById(_extensionId: ExtensionIdentifier, _reason: ExtensionActivationReason): Promise<void> { return Promise.resolve(); }
_onWillActivateExtension(_extensionId: ExtensionIdentifier): void { }
_onDidActivateExtension(_extensionId: ExtensionIdentifier, _startup: boolean, _codeLoadingTime: number, _activateCallTime: number, _activateResolvedTime: number, _activationEvent: string): void { }
_onDidActivateExtension(_extensionId: ExtensionIdentifier, _codeLoadingTime: number, _activateCallTime: number, _activateResolvedTime: number, _activationReason: ExtensionActivationReason): void { }
_onExtensionRuntimeError(_extensionId: ExtensionIdentifier, _err: Error): void { }
_onExtensionHostExit(code: number): void { }
}
......@@ -37,6 +37,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
import { Logger } from 'vs/workbench/services/extensions/common/extensionPoints';
import { flatten } from 'vs/base/common/arrays';
import { IStaticExtensionsService } from 'vs/workbench/services/extensions/common/staticExtensions';
import { ExtensionActivatedByEvent } from 'vs/workbench/api/common/extHostExtensionActivator';
class DeltaExtensionsQueueItem {
constructor(
......@@ -322,7 +323,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
if (shouldActivate) {
await Promise.all(
this._extensionHostProcessManagers.map(extHostManager => extHostManager.activate(extensionDescription.identifier, shouldActivateReason!))
this._extensionHostProcessManagers.map(extHostManager => extHostManager.activate(extensionDescription.identifier, new ExtensionActivatedByEvent(false, extensionDescription.identifier, shouldActivateReason!)))
).then(() => { });
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册