Merge from vscode 3d67364fbfcf676d93be64f949e9b33e7f1b969e (#5028)

This commit is contained in:
Anthony Dresser
2019-04-14 22:29:14 -07:00
committed by GitHub
parent 6dbf757385
commit 57242a2e13
210 changed files with 4898 additions and 3018 deletions

View File

@@ -28,7 +28,7 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
import { EditorOptions } from 'vs/workbench/common/editor';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, RemoteInstallAction, SystemDisabledLabelAction, SystemDisabledWarningAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, RemoteInstallAction, DisabledLabelAction, SystemDisabledWarningAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
@@ -395,7 +395,7 @@ export class ExtensionEditor extends BaseEditor {
this.instantiationService.createInstance(RemoteInstallAction),
combinedInstallAction,
systemDisabledWarningAction,
this.instantiationService.createInstance(SystemDisabledLabelAction, systemDisabledWarningAction),
this.instantiationService.createInstance(DisabledLabelAction, systemDisabledWarningAction),
this.instantiationService.createInstance(MaliciousStatusLabelAction, true),
];
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
@@ -623,9 +623,9 @@ export class ExtensionEditor extends BaseEditor {
renderDashboardContributions(content, manifest, layout)
];
const isEmpty = !renders.reduce((v, r) => r || v, false);
scrollableContent.scanDomNode();
const isEmpty = !renders.some(x => x);
if (isEmpty) {
append(content, $('p.nocontent')).textContent = localize('noContributions', "No Contributions");
append(this.content, content);

View File

@@ -21,6 +21,7 @@ import { randomPort } from 'vs/base/node/ports';
import product from 'vs/platform/product/node/product';
import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput';
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler';
export class ExtensionHostProfileService extends Disposable implements IExtensionHostProfileService {
@@ -76,7 +77,8 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
return null;
}
if (!this._extensionService.canProfileExtensionHost()) {
const inspectPort = this._extensionService.getInspectPort();
if (!inspectPort) {
return this._dialogService.confirm({
type: 'info',
message: nls.localize('restart1', "Profile Extensions"),
@@ -92,7 +94,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
this._setState(ProfileSessionState.Starting);
return this._extensionService.startExtensionHostProfile().then((value) => {
return this._instantiationService.createInstance(ExtensionHostProfiler, inspectPort).start().then((value) => {
this._profileSession = value;
this._setState(ProfileSessionState.Running);
}, (err) => {

View File

@@ -251,6 +251,11 @@ Registry.as<IConfigurationRegistry>(ConfigurationExtensions.Configuration)
description: localize('extensionsPolicy', "Sets the security policy for downloading extensions."),
scope: ConfigurationScope.APPLICATION,
default: ExtensionsPolicy.allowAll
},
'extensions.showInstalledExtensionsByDefault': {
type: 'boolean',
description: localize('extensions.showInstalledExtensionsByDefault', "When enabled, extensions view shows installed extensions view by default."),
default: false
}
}
});

View File

@@ -16,7 +16,7 @@ import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
// {{SQL CARBON EDIT}}
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewlet, AutoUpdateConfigurationKey, IExtensionContainer, EXTENSIONS_CONFIG, ExtensionsPolicy, ExtensionsPolicyKey } from 'vs/workbench/contrib/extensions/common/extensions';
import { ExtensionsConfigurationInitialContent } from 'vs/workbench/contrib/extensions/common/extensionsFileTemplate';
import { IExtensionEnablementService, IExtensionTipsService, EnablementState, ExtensionsLabel, IExtensionRecommendation, IGalleryExtension, IExtensionsConfigContent, IExtensionGalleryService, INSTALL_ERROR_MALICIOUS, INSTALL_ERROR_INCOMPATIBLE, IGalleryExtensionVersion, ILocalExtension, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService, IExtensionTipsService, EnablementState, ExtensionsLabel, IExtensionRecommendation, IGalleryExtension, IExtensionsConfigContent, IExtensionGalleryService, INSTALL_ERROR_MALICIOUS, INSTALL_ERROR_INCOMPATIBLE, IGalleryExtensionVersion, ILocalExtension, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionType, ExtensionIdentifier, IExtensionDescription, IExtensionManifest } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
@@ -60,6 +60,7 @@ import { ILabelService } from 'vs/platform/label/common/label';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { isUIExtension } from 'vs/workbench/services/extensions/node/extensionsUtil';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
// {{SQL CARBON EDIT}}
@@ -183,7 +184,7 @@ export class InstallAction extends ExtensionAction {
return;
}
this.enabled = this.extensionsWorkbenchService.canInstall(this.extension) && this.extension.state === ExtensionState.Uninstalled;
this.enabled = this.extensionsWorkbenchService.canInstall(this.extension) && !this.extensionsWorkbenchService.local.some(e => areSameExtensions(e.identifier, this.extension.identifier));
this.class = this.extension.state === ExtensionState.Installing ? InstallAction.InstallingClass : InstallAction.Class;
this.updateLabel();
}
@@ -720,7 +721,7 @@ export class ManageExtensionAction extends ExtensionDropDownAction {
]);
groups.push([this.instantiationService.createInstance(UninstallAction)]);
groups.push([this.instantiationService.createInstance(InstallAnotherVersionAction)]);
groups.push([this.instantiationService.createInstance(ExtensionInfoAction)]);
groups.push([this.instantiationService.createInstance(ExtensionInfoAction), this.instantiationService.createInstance(ExtensionSettingsAction)]);
groups.forEach(group => group.forEach(extensionAction => extensionAction.extension = this.extension));
@@ -829,6 +830,27 @@ export class ExtensionInfoAction extends ExtensionAction {
}
}
export class ExtensionSettingsAction extends ExtensionAction {
static readonly ID = 'extensions.extensionSettings';
static readonly LABEL = localize('extensionSettingsAction', "Configure Extension Settings");
constructor(
@IPreferencesService private readonly preferencesService: IPreferencesService
) {
super(ExtensionSettingsAction.ID, ExtensionSettingsAction.LABEL);
this.update();
}
update(): void {
this.enabled = !!this.extension;
}
run(): Promise<any> {
this.preferencesService.openSettings(false, `@ext:${this.extension.identifier.id}`);
return Promise.resolve();
}
}
export class EnableForWorkspaceAction extends ExtensionAction {
static readonly ID = 'extensions.enableForWorkspace';
@@ -1195,9 +1217,10 @@ export class ReloadAction extends ExtensionAction {
}
const isUninstalled = this.extension.state === ExtensionState.Uninstalled;
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier))[0];
const isSameExtensionRunning = runningExtension && this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation);
if (isUninstalled) {
if (runningExtension) {
if (isSameExtensionRunning) {
this.enabled = true;
this.label = localize('reloadRequired', "Reload Required");
// {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
@@ -1210,7 +1233,6 @@ export class ReloadAction extends ExtensionAction {
const isEnabled = this.extensionEnablementService.isEnabled(this.extension.local);
if (runningExtension) {
// Extension is running
const isSameExtensionRunning = this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation);
const isSameVersionRunning = isSameExtensionRunning && this.extension.version === runningExtension.version;
if (isEnabled) {
if (!isSameVersionRunning && !this.extensionService.canAddExtension(toExtensionDescription(this.extension.local))) {
@@ -2484,6 +2506,7 @@ export class StatusLabelAction extends Action implements IExtensionContainer {
return canAddExtension() ? this.initialStatus === ExtensionState.Installed ? localize('updated', "Updated") : localize('installed', "Installed") : null;
}
if (currentStatus === ExtensionState.Uninstalling && this.status === ExtensionState.Uninstalled) {
this.initialStatus = this.status;
return canRemoveExtension() ? localize('uninstalled', "Uninstalled") : null;
}
}
@@ -2533,7 +2556,7 @@ export class MaliciousStatusLabelAction extends ExtensionAction {
}
}
export class SystemDisabledLabelAction extends ExtensionAction {
export class DisabledLabelAction extends ExtensionAction {
private static readonly Class = 'disable-status';
@@ -2542,19 +2565,26 @@ export class SystemDisabledLabelAction extends ExtensionAction {
constructor(
private readonly warningAction: SystemDisabledWarningAction,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
) {
super('extensions.systemDisabledLabel', warningAction.tooltip, `${SystemDisabledLabelAction.Class} hide`, false);
super('extensions.disabledLabel', warningAction.tooltip, `${DisabledLabelAction.Class} hide`, false);
warningAction.onDidChange(() => this.update(), this, this.disposables);
}
update(): void {
this.enabled = this.warningAction.enabled;
if (this.enabled) {
this.class = SystemDisabledLabelAction.Class;
this.class = `${DisabledLabelAction.Class} hide`;
this.label = '';
if (this.warningAction.enabled) {
this.enabled = true;
this.class = DisabledLabelAction.Class;
this.label = this.warningAction.tooltip;
} else {
this.class = `${SystemDisabledLabelAction.Class} hide`;
this.label = '';
return;
}
if (this.extension && this.extension.local && !this.extensionEnablementService.isEnabled(this.extension.local)) {
this.enabled = true;
this.class = DisabledLabelAction.Class;
this.label = localize('disabled by user', "This extension is disabled by the user.");
return;
}
}
@@ -2599,27 +2629,42 @@ export class SystemDisabledWarningAction extends ExtensionAction {
this.enabled = false;
this.class = `${SystemDisabledWarningAction.Class} hide`;
this.tooltip = '';
if (this.extension && this.extension.local && this._runningExtensions) {
if (this.extension && this.extension.local && this.extension.server && this._runningExtensions && this.workbenchEnvironmentService.configuration.remoteAuthority && this.extensionManagementServerService.remoteExtensionManagementServer) {
if (
// Remote Window
this.workbenchEnvironmentService.configuration.remoteAuthority
// Local Workspace Extension
&& this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.configurationService)
// Extension does not exist in remote
&& !this.extensionsWorkbenchService.local.some(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.extensionManagementServerService.remoteExtensionManagementServer)
this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.configurationService)
) {
this.enabled = true;
this.class = `${SystemDisabledWarningAction.Class}`;
const host = this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.workbenchEnvironmentService.configuration.remoteAuthority) || localize('remote', "Remote");
this.tooltip = localize('disabled workspace Extension', "This extension is disabled because it cannot run in a window connected to the remote server.", host, host);
if (this.extensionsWorkbenchService.canInstall(this.extension)) {
this.tooltip = `${this.tooltip} ${localize('Install in remote server', "Install it in '{0}' server to enable.", host)}`;
this.tooltip = localize('disabled workspace Extension', "This extension from {0} server is disabled because it cannot run in a window connected to the remote server.", this.getServerLabel(this.extensionManagementServerService.localExtensionManagementServer));
if (!this.extensionsWorkbenchService.local.some(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.extensionManagementServerService.remoteExtensionManagementServer)
&& this.extensionsWorkbenchService.canInstall(this.extension)
) {
// Extension does not exist in remote
this.tooltip = `${this.tooltip} ${localize('Install in remote server', "Install it in {0} server to enable.", this.getServerLabel(this.extensionManagementServerService.remoteExtensionManagementServer))}`;
}
return;
}
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier))[0];
const runningExtensionServer = runningExtension ? this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation) : null;
if (
// Not same as running extension
runningExtensionServer && this.extension.server !== runningExtensionServer
) {
this.enabled = true;
this.class = `${SystemDisabledWarningAction.Class}`;
this.tooltip = localize('disabled because running in another server', "This extension from {0} server is disabled because another instance of same extension from {1} server is enabled.", this.getServerLabel(this.extension.server), this.getServerLabel(runningExtensionServer));
return;
}
}
}
private getServerLabel(server: IExtensionManagementServer): string {
if (server === this.extensionManagementServerService.remoteExtensionManagementServer) {
return this.labelService.getHostLabel(REMOTE_HOST_SCHEME, this.workbenchEnvironmentService.configuration.remoteAuthority) || localize('remote', "Remote");
}
return server.label;
}
run(): Promise<any> {
return Promise.resolve(null);
}

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IExtensionService, IResponsiveStateChangeEvent, ICpuProfilerTarget, IExtensionHostProfile, ProfileSession } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionService, IResponsiveStateChangeEvent, IExtensionHostProfile, ProfileSession } from 'vs/workbench/services/extensions/common/extensions';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { Disposable } from 'vs/base/common/lifecycle';
import { ILogService } from 'vs/platform/log/common/log';
@@ -21,11 +21,12 @@ import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { createSlowExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsSlowActions';
import { ExtensionHostProfiler } from 'vs/workbench/services/extensions/electron-browser/extensionHostProfiler';
export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchContribution {
private readonly _session = new Map<ICpuProfilerTarget, CancellationTokenSource>();
private readonly _blame = new Set<string>();
private _session: CancellationTokenSource | undefined;
constructor(
@IExtensionService private readonly _extensionService: IExtensionService,
@@ -41,26 +42,29 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont
}
private async _onDidChangeResponsiveChange(event: IResponsiveStateChangeEvent): Promise<void> {
const { target } = event;
if (!target.canProfileExtensionHost()) {
const port = this._extensionService.getInspectPort();
if (!port) {
return;
}
if (event.isResponsive && this._session.has(target)) {
if (event.isResponsive && this._session) {
// stop profiling when responsive again
this._session.get(target)!.cancel();
this._session.cancel();
} else if (!event.isResponsive && !this._session.has(target)) {
} else if (!event.isResponsive && !this._session) {
// start profiling if not yet profiling
const token = new CancellationTokenSource();
this._session.set(target, token);
const cts = new CancellationTokenSource();
this._session = cts;
let session: ProfileSession;
try {
session = await target.startExtensionHostProfile();
session = await this._instantiationService.createInstance(ExtensionHostProfiler, port).start();
} catch (err) {
this._session.delete(target);
this._session = undefined;
// fail silent as this is often
// caused by another party being
// connected already
@@ -69,7 +73,7 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont
// wait 5 seconds or until responsive again
await new Promise(resolve => {
token.token.onCancellationRequested(resolve);
cts.token.onCancellationRequested(resolve);
setTimeout(resolve, 5e3);
});
@@ -79,7 +83,7 @@ export class ExtensionsAutoProfiler extends Disposable implements IWorkbenchCont
} catch (err) {
onUnexpectedError(err);
} finally {
this._session.delete(target);
this._session = undefined;
}
}
}

View File

@@ -13,9 +13,9 @@ import { IPagedRenderer } from 'vs/base/browser/ui/list/listPaging';
import { Event } from 'vs/base/common/event';
import { domEvent } from 'vs/base/browser/event';
import { IExtension, ExtensionContainers, ExtensionState, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -88,13 +88,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
});
actionbar.onDidRun(({ error }) => error && this.notificationService.error(error));
const widgets = [
recommendationWidget,
badgeWidget,
this.instantiationService.createInstance(Label, version, (e: IExtension) => e.version),
this.instantiationService.createInstance(InstallCountWidget, installCount, true),
this.instantiationService.createInstance(RatingsWidget, ratings, true)
];
const systemDisabledWarningAction = this.instantiationService.createInstance(SystemDisabledWarningAction);
const actions = [
this.instantiationService.createInstance(StatusLabelAction),
this.instantiationService.createInstance(UpdateAction),
@@ -102,10 +96,20 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
this.instantiationService.createInstance(InstallAction),
this.instantiationService.createInstance(RemoteInstallAction),
this.instantiationService.createInstance(MaliciousStatusLabelAction, false),
this.instantiationService.createInstance(SystemDisabledWarningAction),
systemDisabledWarningAction,
this.instantiationService.createInstance(ManageExtensionAction)
];
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets]);
const disabledLabelAction = this.instantiationService.createInstance(DisabledLabelAction, systemDisabledWarningAction);
const tooltipWidget = this.instantiationService.createInstance(TooltipWidget, root, disabledLabelAction, recommendationWidget);
const widgets = [
recommendationWidget,
badgeWidget,
tooltipWidget,
this.instantiationService.createInstance(Label, version, (e: IExtension) => e.version),
this.instantiationService.createInstance(InstallCountWidget, installCount, true),
this.instantiationService.createInstance(RatingsWidget, ratings, true)
];
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, disabledLabelAction]);
actionbar.push(actions, actionOptions);
const disposables = [...actions, ...widgets, actionbar, extensionContainers];

View File

@@ -53,7 +53,6 @@ import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { Registry } from 'vs/platform/registry/common/platform';
import { RemoteAuthorityContext as RemoteAuthorityContext } from 'vs/workbench/common/contextkeys';
import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsViewlet';
interface SearchInputEvent extends Event {
@@ -64,7 +63,10 @@ interface SearchInputEvent extends Event {
const NonEmptyWorkspaceContext = new RawContextKey<boolean>('nonEmptyWorkspace', false);
const DefaultViewsContext = new RawContextKey<boolean>('defaultExtensionViews', true);
const SearchMarketplaceExtensionsContext = new RawContextKey<boolean>('searchMarketplaceExtensions', false);
const SearchServerExtensionsContext = new RawContextKey<boolean>('searchServerExtensions', false);
const SearchIntalledExtensionsContext = new RawContextKey<boolean>('searchInstalledExtensions', false);
const SearchOutdatedExtensionsContext = new RawContextKey<boolean>('searchOutdatedExtensions', false);
const SearchEnabledExtensionsContext = new RawContextKey<boolean>('searchEnabledExtensions', false);
const SearchDisabledExtensionsContext = new RawContextKey<boolean>('searchDisabledExtensions', false);
const HasInstalledExtensionsContext = new RawContextKey<boolean>('hasInstalledExtensions', true);
const SearchBuiltInExtensionsContext = new RawContextKey<boolean>('searchBuiltInExtensions', false);
const RecommendedExtensionsContext = new RawContextKey<boolean>('recommendedExtensions', false);
@@ -72,10 +74,12 @@ const DefaultRecommendedExtensionsContext = new RawContextKey<boolean>('defaultR
const viewIdNameMappings: { [id: string]: string } = {
'extensions.listView': localize('marketPlace', "Marketplace"),
'extensions.enabledExtensionList': localize('enabledExtensions', "Enabled"),
'extensions.enabledExtensionList2': localize('enabledExtensions', "Enabled"),
'extensions.disabledExtensionList': localize('disabledExtensions', "Disabled"),
'extensions.disabledExtensionList2': localize('disabledExtensions', "Disabled"),
// {{SQL CARBON EDIT}}
// 'extensions.popularExtensionsList': localize('popularExtensions', "Popular"),
'extensions.recommendedList': localize('recommendedExtensions', "Marketplace"),
'extensions.recommendedList': localize('recommendedExtensions', "Recommended"),
'extensions.otherrecommendedList': localize('otherRecommendedExtensions', "Other Recommendations"),
'extensions.workspaceRecommendedList': localize('workspaceRecommendedExtensions', "Workspace Recommendations"),
'extensions.builtInExtensionsList': localize('builtInExtensions', "Features"),
@@ -98,6 +102,8 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
viewDescriptors.push(this.createDefaultDisabledExtensionsListViewDescriptor());
// {{SQL CARBON EDIT}}
// viewDescriptors.push(this.createDefaultPopularExtensionsListViewDescriptor());
viewDescriptors.push(this.createEnabledExtensionsListViewDescriptor());
viewDescriptors.push(this.createDisabledExtensionsListViewDescriptor());
viewDescriptors.push(this.createBuiltInExtensionsListViewDescriptor());
viewDescriptors.push(this.createBuiltInBasicsExtensionsListViewDescriptor());
viewDescriptors.push(this.createBuiltInThemesExtensionsListViewDescriptor());
@@ -133,7 +139,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
id,
name: viewIdNameMappings[id],
ctorDescriptor: { ctor: EnabledExtensionsView },
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), RemoteAuthorityContext.isEqualTo('')),
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), ContextKeyExpr.not('config.extensions.showInstalledExtensionsByDefault')),
weight: 40,
canToggleVisibility: true,
order: 1
@@ -148,7 +154,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
id,
name: viewIdNameMappings[id],
ctorDescriptor: { ctor: DisabledExtensionsView },
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), RemoteAuthorityContext.isEqualTo('')),
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), ContextKeyExpr.not('config.extensions.showInstalledExtensionsByDefault')),
weight: 10,
canToggleVisibility: true,
order: 3,
@@ -175,15 +181,21 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
private createExtensionsViewDescriptorsForServer(server: IExtensionManagementServer): IViewDescriptor[] {
return [{
id: `extensions.${server.authority}.installed`,
name: server.label,
name: localize('installed', "Installed"),
ctorDescriptor: { ctor: ServerExtensionsView, arguments: [server] },
when: ContextKeyExpr.and(ContextKeyExpr.has('searchServerExtensions')),
when: ContextKeyExpr.and(ContextKeyExpr.has('searchInstalledExtensions')),
weight: 100
}, {
id: `extensions.${server.authority}.outdated`,
name: localize('outdated', "Outdated"),
ctorDescriptor: { ctor: ServerExtensionsView, arguments: [server] },
when: ContextKeyExpr.and(ContextKeyExpr.has('searchOutdatedExtensions')),
weight: 100
}, {
id: `extensions.${server.authority}.default`,
name: server.label,
name: localize('installed', "Installed"),
ctorDescriptor: { ctor: ServerExtensionsView, arguments: [server] },
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), RemoteAuthorityContext.notEqualsTo('')),
when: ContextKeyExpr.and(ContextKeyExpr.has('defaultExtensionViews'), ContextKeyExpr.has('hasInstalledExtensions'), ContextKeyExpr.has('config.extensions.showInstalledExtensionsByDefault')),
weight: 40,
order: 1
}];
@@ -235,6 +247,33 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
};
}
private createEnabledExtensionsListViewDescriptor(): IViewDescriptor {
const id = 'extensions.enabledExtensionList2';
return {
id,
name: viewIdNameMappings[id],
ctorDescriptor: { ctor: EnabledExtensionsView },
when: ContextKeyExpr.and(ContextKeyExpr.has('searchEnabledExtensions')),
weight: 40,
canToggleVisibility: true,
order: 1
};
}
private createDisabledExtensionsListViewDescriptor(): IViewDescriptor {
const id = 'extensions.disabledExtensionList2';
return {
id,
name: viewIdNameMappings[id],
ctorDescriptor: { ctor: DisabledExtensionsView },
when: ContextKeyExpr.and(ContextKeyExpr.has('searchDisabledExtensions')),
weight: 10,
canToggleVisibility: true,
order: 3,
collapsed: true
};
}
private createBuiltInExtensionsListViewDescriptor(): IViewDescriptor {
const id = 'extensions.builtInExtensionsList';
return {
@@ -278,7 +317,10 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private nonEmptyWorkspaceContextKey: IContextKey<boolean>;
private defaultViewsContextKey: IContextKey<boolean>;
private searchMarketplaceExtensionsContextKey: IContextKey<boolean>;
private searchServerExtensionsContextKey: IContextKey<boolean>;
private searchInstalledExtensionsContextKey: IContextKey<boolean>;
private searchOutdatedExtensionsContextKey: IContextKey<boolean>;
private searchEnabledExtensionsContextKey: IContextKey<boolean>;
private searchDisabledExtensionsContextKey: IContextKey<boolean>;
private hasInstalledExtensionsContextKey: IContextKey<boolean>;
private searchBuiltInExtensionsContextKey: IContextKey<boolean>;
private recommendedExtensionsContextKey: IContextKey<boolean>;
@@ -317,7 +359,10 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.nonEmptyWorkspaceContextKey = NonEmptyWorkspaceContext.bindTo(contextKeyService);
this.defaultViewsContextKey = DefaultViewsContext.bindTo(contextKeyService);
this.searchMarketplaceExtensionsContextKey = SearchMarketplaceExtensionsContext.bindTo(contextKeyService);
this.searchServerExtensionsContextKey = SearchServerExtensionsContext.bindTo(contextKeyService);
this.searchInstalledExtensionsContextKey = SearchIntalledExtensionsContext.bindTo(contextKeyService);
this.searchOutdatedExtensionsContextKey = SearchOutdatedExtensionsContext.bindTo(contextKeyService);
this.searchEnabledExtensionsContextKey = SearchEnabledExtensionsContext.bindTo(contextKeyService);
this.searchDisabledExtensionsContextKey = SearchDisabledExtensionsContext.bindTo(contextKeyService);
this.hasInstalledExtensionsContextKey = HasInstalledExtensionsContext.bindTo(contextKeyService);
this.searchBuiltInExtensionsContextKey = SearchBuiltInExtensionsContext.bindTo(contextKeyService);
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
@@ -457,7 +502,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
protected saveState(): void {
const value = this.searchBox.getValue();
if (ExtensionsListView.isInstalledExtensionsQuery(value)) {
if (ExtensionsListView.isLocalExtensionsQuery(value)) {
this.searchViewletState['query.value'] = value;
} else {
this.searchViewletState['query.value'] = '';
@@ -468,13 +513,14 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private doSearch(): Promise<void> {
const value = this.normalizedQuery();
this.defaultViewsContextKey.set(!value);
const isServerExtensionsQuery = ExtensionsListView.isServerExtensionsQuery(value);
const isBuiltInExtensionsQuery = ExtensionsListView.isBuiltInExtensionsQuery(value);
const isRecommendedExtensionsQuery = ExtensionsListView.isRecommendedExtensionsQuery(value);
this.searchServerExtensionsContextKey.set(isServerExtensionsQuery);
this.searchBuiltInExtensionsContextKey.set(isBuiltInExtensionsQuery);
this.searchInstalledExtensionsContextKey.set(ExtensionsListView.isInstalledExtensionsQuery(value));
this.searchOutdatedExtensionsContextKey.set(ExtensionsListView.isOutdatedExtensionsQuery(value));
this.searchEnabledExtensionsContextKey.set(ExtensionsListView.isEnabledExtensionsQuery(value));
this.searchDisabledExtensionsContextKey.set(ExtensionsListView.isDisabledExtensionsQuery(value));
this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value));
this.recommendedExtensionsContextKey.set(isRecommendedExtensionsQuery);
this.searchMarketplaceExtensionsContextKey.set(!!value && !isServerExtensionsQuery && !isBuiltInExtensionsQuery && !isRecommendedExtensionsQuery);
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery);
this.nonEmptyWorkspaceContextKey.set(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY);
return this.progress(Promise.all(this.panels.map(view =>

View File

@@ -9,7 +9,7 @@ import { assign } from 'vs/base/common/objects';
import { Event, Emitter } from 'vs/base/common/event';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { PagedModel, IPagedModel, IPager, DelayedPagedModel } from 'vs/base/common/paging';
import { SortBy, SortOrder, IQueryOptions, IExtensionTipsService, IExtensionRecommendation, IExtensionManagementServer } from 'vs/platform/extensionManagement/common/extensionManagement';
import { SortBy, SortOrder, IQueryOptions, IExtensionTipsService, IExtensionRecommendation, IExtensionManagementServer, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -41,7 +41,7 @@ import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IAction } from 'vs/base/common/actions';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ExtensionType, ExtensionIdentifier, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import product from 'vs/platform/product/node/product';
import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
@@ -96,7 +96,8 @@ export class ExtensionsListView extends ViewletPanel {
@IConfigurationService configurationService: IConfigurationService,
@IWorkspaceContextService protected contextService: IWorkspaceContextService,
@IExperimentService private readonly experimentService: IExperimentService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService
) {
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService);
this.server = options.server;
@@ -234,7 +235,7 @@ export class ExtensionsListView extends ViewletPanel {
if (ids.length) {
return this.queryByIds(ids, options, token);
}
if (ExtensionsListView.isInstalledExtensionsQuery(query.value) || /@builtin/.test(query.value)) {
if (ExtensionsListView.isLocalExtensionsQuery(query.value) || /@builtin/.test(query.value)) {
return this.queryLocal(query, options);
}
return this.queryGallery(query, options, token);
@@ -329,7 +330,23 @@ export class ExtensionsListView extends ViewletPanel {
&& (e.name.toLowerCase().indexOf(value) > -1 || e.displayName.toLowerCase().indexOf(value) > -1)
&& (!categories.length || categories.some(category => (e.local && e.local.manifest.categories || []).some(c => c.toLowerCase() === category))));
return this.getPagedModel(this.sortExtensions(result, options));
if (options.sortBy !== undefined) {
result = this.sortExtensions(result, options);
} else {
const runningExtensions = await this.extensionService.getExtensions();
const runningExtensionsById = runningExtensions.reduce((result, e) => { result.set(ExtensionIdentifier.toKey(e.identifier.value), e); return result; }, new Map<string, IExtensionDescription>());
result = result.sort((e1, e2) => {
const running1 = runningExtensionsById.get(ExtensionIdentifier.toKey(e1.identifier.id));
const isE1Running = running1 && this.extensionManagementServerService.getExtensionManagementServer(running1.extensionLocation) === e1.server;
const running2 = runningExtensionsById.get(ExtensionIdentifier.toKey(e2.identifier.id));
const isE2Running = running2 && this.extensionManagementServerService.getExtensionManagementServer(running2.extensionLocation) === e2.server;
if ((isE1Running && isE2Running) || (!isE1Running && !isE2Running)) {
return e1.displayName.localeCompare(e2.displayName);
}
return isE1Running ? -1 : 1;
});
}
return this.getPagedModel(result);
}
@@ -785,12 +802,28 @@ export class ExtensionsListView extends ViewletPanel {
return /^\s*@builtin\s*$/i.test(query);
}
static isInstalledExtensionsQuery(query: string): boolean {
return /@installed|@outdated|@enabled|@disabled/i.test(query);
static isLocalExtensionsQuery(query: string): boolean {
return this.isInstalledExtensionsQuery(query)
|| this.isOutdatedExtensionsQuery(query)
|| this.isEnabledExtensionsQuery(query)
|| this.isDisabledExtensionsQuery(query)
|| this.isBuiltInExtensionsQuery(query);
}
static isServerExtensionsQuery(query: string): boolean {
return /@installed|@outdated/i.test(query);
static isInstalledExtensionsQuery(query: string): boolean {
return /@installed/i.test(query);
}
static isOutdatedExtensionsQuery(query: string): boolean {
return /@outdated/i.test(query);
}
static isEnabledExtensionsQuery(query: string): boolean {
return /@enabled/i.test(query);
}
static isDisabledExtensionsQuery(query: string): boolean {
return /@disabled/i.test(query);
}
static isRecommendedExtensionsQuery(query: string): boolean {
@@ -827,8 +860,12 @@ export class ExtensionsListView extends ViewletPanel {
}
}
function getServerLabel(server: IExtensionManagementServer, labelService: ILabelService, workbenchEnvironmentService: IWorkbenchEnvironmentService): string {
return workbenchEnvironmentService.configuration.remoteAuthority === server.authority ? labelService.getHostLabel(REMOTE_HOST_SCHEME, server.authority) || server.label : server.label;
function getViewTitleForServer(viewTitle: string, server: IExtensionManagementServer, labelService: ILabelService, workbenchEnvironmentService: IWorkbenchEnvironmentService): string {
const serverLabel = workbenchEnvironmentService.configuration.remoteAuthority === server.authority ? labelService.getHostLabel(REMOTE_HOST_SCHEME, server.authority) || server.label : server.label;
if (viewTitle && workbenchEnvironmentService.configuration.remoteAuthority) {
return `${serverLabel} - ${viewTitle}`;
}
return viewTitle ? viewTitle : serverLabel;
}
export class ServerExtensionsView extends ExtensionsListView {
@@ -852,17 +889,19 @@ export class ServerExtensionsView extends ExtensionsListView {
@IWorkbenchThemeService workbenchThemeService: IWorkbenchThemeService,
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
@ILabelService labelService: ILabelService,
@IWorkbenchEnvironmentService workbenchEnvironmentService: IWorkbenchEnvironmentService
@IWorkbenchEnvironmentService workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService
) {
options.title = getServerLabel(server, labelService, workbenchEnvironmentService);
const viewTitle = options.title;
options.title = getViewTitleForServer(viewTitle, server, labelService, workbenchEnvironmentService);
options.server = server;
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, modeService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService);
this.disposables.push(labelService.onDidChangeFormatters(() => this.updateTitle(getServerLabel(server, labelService, workbenchEnvironmentService))));
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, modeService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService);
this.disposables.push(labelService.onDidChangeFormatters(() => this.updateTitle(getViewTitleForServer(viewTitle, server, labelService, workbenchEnvironmentService))));
}
async show(query: string): Promise<IPagedModel<IExtension>> {
query = query ? query : '@installed';
if (!ExtensionsListView.isInstalledExtensionsQuery(query) && !ExtensionsListView.isBuiltInExtensionsQuery(query)) {
if (!ExtensionsListView.isLocalExtensionsQuery(query) && !ExtensionsListView.isBuiltInExtensionsQuery(query)) {
query = query += ' @installed';
}
return super.show(query.trim());

View File

@@ -11,12 +11,13 @@ import * as platform from 'vs/base/common/platform';
import { localize } from 'vs/nls';
import { IExtensionManagementServerService, IExtensionTipsService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ILabelService } from 'vs/platform/label/common/label';
import { extensionButtonProminentBackground, extensionButtonProminentForeground } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { STATUS_BAR_HOST_NAME_BACKGROUND, STATUS_BAR_FOREGROUND, STATUS_BAR_NO_FOLDER_FOREGROUND } from 'vs/workbench/common/theme';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { Emitter, Event } from 'vs/base/common/event';
export abstract class ExtensionWidget extends Disposable implements IExtensionContainer {
private _extension: IExtension;
@@ -142,11 +143,53 @@ export class RatingsWidget extends ExtensionWidget {
}
}
export class TooltipWidget extends ExtensionWidget {
constructor(
private readonly parent: HTMLElement,
private readonly extensionLabelAction: DisabledLabelAction,
private readonly recommendationWidget: RecommendationWidget
) {
super();
this._register(this.extensionLabelAction.onDidChange(() => this.render()));
this._register(this.recommendationWidget.onDidChangeTooltip(() => this.render()));
}
render(): void {
this.parent.title = '';
this.parent.removeAttribute('aria-label');
if (this.extension) {
const title = this.getTitle();
this.parent.title = title;
this.parent.setAttribute('aria-label', localize('extension-arialabel', "{0}. {1} Press enter for extension details.", this.extension.displayName));
}
}
private getTitle(): string {
if (this.extensionLabelAction.enabled) {
return this.extensionLabelAction.label;
}
return this.recommendationWidget.tooltip;
}
}
export class RecommendationWidget extends ExtensionWidget {
private element?: HTMLElement;
private disposables: IDisposable[] = [];
private _tooltip: string;
get tooltip(): string { return this._tooltip; }
set tooltip(tooltip: string) {
if (this._tooltip !== tooltip) {
this._tooltip = tooltip;
this._onDidChangeTooltip.fire();
}
}
private _onDidChangeTooltip: Emitter<void> = this._register(new Emitter<void>());
readonly onDidChangeTooltip: Event<void> = this._onDidChangeTooltip.event;
constructor(
private parent: HTMLElement,
@IThemeService private readonly themeService: IThemeService,
@@ -159,7 +202,7 @@ export class RecommendationWidget extends ExtensionWidget {
}
private clear(): void {
this.parent.title = '';
this.tooltip = '';
this.parent.setAttribute('aria-label', this.extension ? localize('viewExtensionDetailsAria', "{0}. Press enter for extension details.", this.extension.displayName) : '');
if (this.element) {
this.parent.removeChild(this.element);
@@ -186,8 +229,7 @@ export class RecommendationWidget extends ExtensionWidget {
};
applyBookmarkStyle(this.themeService.getTheme());
this.themeService.onThemeChange(applyBookmarkStyle, this, this.disposables);
this.parent.title = extRecommendations[this.extension.identifier.id.toLowerCase()].reasonText;
this.parent.setAttribute('aria-label', localize('viewRecommendedExtensionDetailsAria', "{0}. {1} Press enter for extension details.", this.extension.displayName, extRecommendations[this.extension.identifier.id.toLowerCase()].reasonText));
this.tooltip = extRecommendations[this.extension.identifier.id.toLowerCase()].reasonText;
}
}
@@ -227,7 +269,7 @@ export class RemoteBadgeWidget extends ExtensionWidget {
}
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
this.element = append(this.parent, $('div.extension-remote-badge'));
append(this.element, $('span.octicon.octicon-file-symlink-directory'));
append(this.element, $('span.octicon.octicon-remote'));
const applyBadgeStyle = () => {
if (!this.element) {

View File

@@ -700,7 +700,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}
private fromGallery(gallery: IGalleryExtension, maliciousExtensionSet: Set<string>): IExtension {
Promise.all([this.localExtensions.syncLocalWithGalleryExtension(gallery, maliciousExtensionSet), this.remoteExtensions ? this.localExtensions.syncLocalWithGalleryExtension(gallery, maliciousExtensionSet) : Promise.resolve(false)])
Promise.all([this.localExtensions.syncLocalWithGalleryExtension(gallery, maliciousExtensionSet), this.remoteExtensions ? this.remoteExtensions.syncLocalWithGalleryExtension(gallery, maliciousExtensionSet) : Promise.resolve(false)])
.then(result => {
if (result[0] || result[1]) {
this.eventuallyAutoUpdateExtensions();

View File

@@ -12,7 +12,7 @@ import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/com
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/node/extensionsWorkbenchService';
import {
IExtensionManagementService, IExtensionGalleryService, IExtensionEnablementService, IExtensionTipsService, ILocalExtension, IGalleryExtension, IQueryOptions,
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, IExtensionManagementServerService, EnablementState, ExtensionRecommendationReason, SortBy
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, IExtensionManagementServerService, EnablementState, ExtensionRecommendationReason, SortBy, IExtensionManagementServer
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
@@ -39,6 +39,7 @@ import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteA
import { RemoteAgentService } from 'vs/workbench/services/remote/electron-browser/remoteAgentServiceImpl';
import { ExtensionIdentifier, ExtensionType, IExtensionDescription } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
suite('ExtensionsListView Tests', () => {
@@ -89,11 +90,14 @@ suite('ExtensionsListView Tests', () => {
instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event);
instantiationService.stub(IRemoteAgentService, RemoteAgentService);
instantiationService.stub(IExtensionManagementServerService, <IExtensionManagementServerService>{
localExtensionManagementServer: {
extensionManagementService: instantiationService.get(IExtensionManagementService)
instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService {
private _localExtensionManagementServer: IExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', authority: 'vscode-local' };
constructor() {
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService));
}
});
get localExtensionManagementServer(): IExtensionManagementServer { return this._localExtensionManagementServer; }
set localExtensionManagementServer(server: IExtensionManagementServer) { }
}());
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
@@ -151,14 +155,14 @@ suite('ExtensionsListView Tests', () => {
test('Test query types', () => {
assert.equal(ExtensionsListView.isBuiltInExtensionsQuery('@builtin'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@installed'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@enabled'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@disabled'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@outdated'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@installed searchText'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@enabled searchText'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@disabled searchText'), true);
assert.equal(ExtensionsListView.isInstalledExtensionsQuery('@outdated searchText'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@installed'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@enabled'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@disabled'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@outdated'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@installed searchText'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@enabled searchText'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@disabled searchText'), true);
assert.equal(ExtensionsListView.isLocalExtensionsQuery('@outdated searchText'), true);
});
test('Test empty query equates to sort by install count', () => {
@@ -200,8 +204,8 @@ suite('ExtensionsListView Tests', () => {
await testableView.show('@installed first').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with search text.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with search text.');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with search text.');
assert.equal(result.get(1).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with search text.');
});
await testableView.show('@disabled').then(result => {
@@ -242,27 +246,27 @@ suite('ExtensionsListView Tests', () => {
test('Test installed query with category', async () => {
await testableView.show('@installed category:themes').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query with category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with category.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with category.');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with category.');
assert.equal(result.get(1).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with category.');
});
await testableView.show('@installed category:"themes"').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query with quoted category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with quoted category.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with quoted category.');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with quoted category.');
assert.equal(result.get(1).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with quoted category.');
});
await testableView.show('@installed category:"programming languages"').then(result => {
assert.equal(result.length, 2, 'Unexpected number of results for @installed query with quoted category including space');
assert.equal(result.get(0).name, localDisabledLanguage.manifest.name, 'Unexpected extension for @installed query with quoted category inlcuding space.');
assert.equal(result.get(1).name, localEnabledLanguage.manifest.name, 'Unexpected extension for @installed query with quoted category including space.');
assert.equal(result.get(0).name, localEnabledLanguage.manifest.name, 'Unexpected extension for @installed query with quoted category including space.');
assert.equal(result.get(1).name, localDisabledLanguage.manifest.name, 'Unexpected extension for @installed query with quoted category inlcuding space.');
});
await testableView.show('@installed category:themes category:random').then(result => {
assert.equal(result.length, 3, 'Unexpected number of results for @installed query with multiple category');
assert.equal(result.get(0).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(1).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(2).name, localRandom.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(0).name, localEnabledTheme.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(1).name, localRandom.manifest.name, 'Unexpected extension for @installed query with multiple category.');
assert.equal(result.get(2).name, localDisabledTheme.manifest.name, 'Unexpected extension for @installed query with multiple category.');
});
await testableView.show('@enabled category:themes').then(result => {