Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973 (#6381)

* Merge from vscode 8e0f348413f4f616c23a88ae30030efa85811973

* disable strict null check
This commit is contained in:
Anthony Dresser
2019-07-15 22:35:46 -07:00
committed by GitHub
parent f720ec642f
commit 0b7e7ddbf9
2406 changed files with 59140 additions and 35464 deletions

View File

@@ -13,7 +13,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { Cache, CacheResult } from 'vs/base/common/cache';
import { Action } from 'vs/base/common/actions';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { domEvent } from 'vs/base/browser/event';
import { append, $, addClass, removeClass, finalHandler, join, toggleClass, hide, show } from 'vs/base/browser/dom';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
@@ -25,11 +25,10 @@ import { IExtensionManifest, IKeyBinding, IView, IViewContainer, ExtensionType }
import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, IExtension, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions';
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
import { RatingsWidget, InstallCountWidget, RemoteBadgeWidget } from 'vs/workbench/contrib/extensions/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, DisabledLabelAction, SystemDisabledWarningAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { WebviewElement } from 'vs/workbench/contrib/webview/electron-browser/webviewElement';
import { CombinedInstallAction, UpdateAction, ExtensionEditorDropDownAction, ReloadAction, MaliciousStatusLabelAction, IgnoreExtensionRecommendationAction, UndoIgnoreExtensionRecommendationAction, EnableDropDownAction, DisableDropDownAction, StatusLabelAction, SetFileIconThemeAction, SetColorThemeAction, RemoteInstallAction, DisabledLabelAction, SystemDisabledWarningAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { DomScrollableElement } from 'vs/base/browser/ui/scrollbar/scrollableElement';
import { IOpenerService } from 'vs/platform/opener/common/opener';
@@ -44,25 +43,27 @@ import { assign } from 'vs/base/common/objects';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionsTree, ExtensionData } from 'vs/workbench/contrib/extensions/browser/extensionsViewer';
import { ShowCurrentReleaseNotesAction } from 'vs/workbench/contrib/update/electron-browser/update';
import { ShowCurrentReleaseNotesActionId } from 'vs/workbench/contrib/update/common/update';
import { KeybindingParser } from 'vs/base/common/keybindingParser';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { getDefaultValue } from 'vs/platform/configuration/common/configurationRegistry';
import { isUndefined } from 'vs/base/common/types';
import { IWorkbenchThemeService } from 'vs/workbench/services/themes/common/workbenchThemeService';
import { URI } from 'vs/base/common/uri';
import { IWebviewService, Webview } from 'vs/workbench/contrib/webview/common/webview';
// {{SQL CARBON EDIT}}
import { renderDashboardContributions } from 'sql/workbench/parts/extensions/browser/contributionRenders';
// {{SQL CARBON EDIT}} - End
function renderBody(body: string): string {
const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-core-resource://');
const styleSheetPath = require.toUrl('./media/markdown.css').replace('file://', 'vscode-resource://');
return `<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src https: data:; media-src https:; script-src 'none'; style-src vscode-core-resource:; child-src 'none'; frame-src 'none';">
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src https: data:; media-src https:; script-src 'none'; style-src vscode-resource:; child-src 'none'; frame-src 'none';">
<link rel="stylesheet" type="text/css" href="${styleSheetPath}">
</head>
<body>
@@ -89,9 +90,9 @@ function removeEmbeddedSVGs(documentContent: string): string {
return newDocument.documentElement.outerHTML;
}
class NavBar {
class NavBar extends Disposable {
private _onChange = new Emitter<{ id: string | null, focus: boolean }>();
private _onChange = this._register(new Emitter<{ id: string | null, focus: boolean }>());
get onChange(): Event<{ id: string | null, focus: boolean }> { return this._onChange.event; }
private currentId: string | null = null;
@@ -99,9 +100,10 @@ class NavBar {
private actionbar: ActionBar;
constructor(container: HTMLElement) {
super();
const element = append(container, $('.navbar'));
this.actions = [];
this.actionbar = new ActionBar(element, { animated: false });
this.actionbar = this._register(new ActionBar(element, { animated: false }));
}
push(id: string, label: string, tooltip: string): void {
@@ -129,13 +131,9 @@ class NavBar {
_update(id: string | null = this.currentId, focus?: boolean): Promise<void> {
this.currentId = id;
this._onChange.fire({ id, focus: !!focus });
this.actions.forEach(a => a.enabled = a.id !== id);
this.actions.forEach(a => a.checked = a.id === id);
return Promise.resolve(undefined);
}
dispose(): void {
dispose(this.actionbar);
}
}
const NavbarSection = {
@@ -183,9 +181,8 @@ export class ExtensionEditor extends BaseEditor {
private extensionManifest: Cache<IExtensionManifest | null> | null;
private layoutParticipants: ILayoutParticipant[] = [];
private contentDisposables: IDisposable[] = [];
private transientDisposables: IDisposable[] = [];
private disposables: IDisposable[];
private readonly contentDisposables = this._register(new DisposableStore());
private readonly transientDisposables = this._register(new DisposableStore());
private activeElement: IActiveElement | null;
private editorLoadComplete: boolean = false;
@@ -201,11 +198,10 @@ export class ExtensionEditor extends BaseEditor {
@IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService,
@IStorageService storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IWebviewService private readonly webviewService: IWebviewService
) {
super(ExtensionEditor.ID, telemetryService, themeService, storageService);
this.disposables = [];
this.extensionReadme = null;
this.extensionChangelog = null;
this.extensionManifest = null;
@@ -232,19 +228,21 @@ export class ExtensionEditor extends BaseEditor {
this.builtin.textContent = localize('builtin', "Built-in");
const subtitle = append(details, $('.subtitle'));
this.publisher = append(subtitle, $('span.publisher.clickable', { title: localize('publisher', "Publisher name") }));
this.publisher = append(subtitle, $('span.publisher.clickable', { title: localize('publisher', "Publisher name"), tabIndex: 0 }));
this.installCount = append(subtitle, $('span.install', { title: localize('install count', "Install count") }));
this.installCount = append(subtitle, $('span.install', { title: localize('install count', "Install count"), tabIndex: 0 }));
this.rating = append(subtitle, $('span.rating.clickable', { title: localize('rating', "Rating") }));
this.rating = append(subtitle, $('span.rating.clickable', { title: localize('rating', "Rating"), tabIndex: 0 }));
this.repository = append(subtitle, $('span.repository.clickable'));
this.repository.textContent = localize('repository', 'Repository');
this.repository.style.display = 'none';
this.repository.tabIndex = 0;
this.license = append(subtitle, $('span.license.clickable'));
this.license.textContent = localize('license', 'License');
this.license.style.display = 'none';
this.license.tabIndex = 0;
this.description = append(details, $('.description'));
@@ -263,18 +261,18 @@ export class ExtensionEditor extends BaseEditor {
this.subtext = append(this.subtextContainer, $('.subtext'));
this.ignoreActionbar = new ActionBar(this.subtextContainer, { animated: false });
this.disposables.push(this.extensionActionBar);
this.disposables.push(this.ignoreActionbar);
this._register(this.extensionActionBar);
this._register(this.ignoreActionbar);
Event.chain(this.extensionActionBar.onDidRun)
this._register(Event.chain(this.extensionActionBar.onDidRun)
.map(({ error }) => error)
.filter(error => !!error)
.on(this.onError, this, this.disposables);
.on(this.onError, this));
Event.chain(this.ignoreActionbar.onDidRun)
this._register(Event.chain(this.ignoreActionbar.onDidRun)
.map(({ error }) => error)
.filter(error => !!error)
.on(this.onError, this, this.disposables);
.on(this.onError, this));
const body = append(root, $('.body'));
this.navbar = new NavBar(body);
@@ -291,7 +289,7 @@ export class ExtensionEditor extends BaseEditor {
this.editorLoadComplete = false;
const extension = input.extension;
this.transientDisposables = dispose(this.transientDisposables);
this.transientDisposables.clear();
this.extensionReadme = new Cache(() => createCancelablePromise(token => extension.getReadme(token)));
this.extensionChangelog = new Cache(() => createCancelablePromise(token => extension.getChangelog(token)));
@@ -401,7 +399,9 @@ export class ExtensionEditor extends BaseEditor {
this.extensionActionBar.clear();
this.extensionActionBar.push(actions, { icon: true, label: true });
this.transientDisposables.push(...[...actions, ...widgets, extensionContainers]);
for (const disposable of [...actions, ...widgets, extensionContainers]) {
this.transientDisposables.add(disposable);
}
this.setSubText(extension, reloadAction);
this.content.innerHTML = ''; // Clear content before setting navbar actions.
@@ -448,7 +448,8 @@ export class ExtensionEditor extends BaseEditor {
this.ignoreActionbar.clear();
this.ignoreActionbar.push([ignoreAction, undoIgnoreAction], { icon: true, label: true });
this.transientDisposables.push(ignoreAction, undoIgnoreAction);
this.transientDisposables.add(ignoreAction);
this.transientDisposables.add(undoIgnoreAction);
const extRecommendations = this.extensionTipsService.getAllRecommendationsWithReason();
if (extRecommendations[extension.identifier.id.toLowerCase()]) {
@@ -481,7 +482,7 @@ export class ExtensionEditor extends BaseEditor {
}
});
this.transientDisposables.push(reloadAction.onDidChange(e => {
this.transientDisposables.add(reloadAction.onDidChange(e => {
if (e.tooltip) {
this.subtext.textContent = reloadAction.tooltip;
show(this.subtextContainer);
@@ -504,8 +505,8 @@ export class ExtensionEditor extends BaseEditor {
}
showFind(): void {
if (this.activeElement instanceof WebviewElement) {
this.activeElement.showFind();
if (this.activeElement && (<Webview>this.activeElement).showFind) {
(<Webview>this.activeElement).showFind();
}
}
@@ -522,7 +523,7 @@ export class ExtensionEditor extends BaseEditor {
this.telemetryService.publicLog('extensionEditor:navbarChange', assign(extension.telemetryData, { navItem: id }));
}
this.contentDisposables = dispose(this.contentDisposables);
this.contentDisposables.clear();
this.content.innerHTML = '';
this.activeElement = null;
this.open(id, extension)
@@ -551,29 +552,32 @@ export class ExtensionEditor extends BaseEditor {
.then(renderBody)
.then(removeEmbeddedSVGs)
.then(body => {
const webviewElement = this.instantiationService.createInstance(WebviewElement,
const webviewElement = this.webviewService.createWebview('extensionEditor',
{
enableFindWidget: true,
},
{
svgWhiteList: this.extensionsWorkbenchService.allowedBadgeProviders
svgWhiteList: this.extensionsWorkbenchService.allowedBadgeProviders,
localResourceRoots: [
URI.parse(require.toUrl('./media'))
]
});
webviewElement.mountTo(this.content);
this.contentDisposables.push(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
this.contentDisposables.add(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, webviewElement);
this.contentDisposables.push(toDisposable(removeLayoutParticipant));
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
webviewElement.html = body;
this.contentDisposables.push(webviewElement.onDidClickLink(link => {
this.contentDisposables.add(webviewElement.onDidClickLink(link => {
if (!link) {
return;
}
// Whitelist supported schemes for links
if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesAction.ID)) {
if (['http', 'https', 'mailto'].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesActionId)) {
this.openerService.open(link);
}
}, null, this.contentDisposables));
this.contentDisposables.push(webviewElement);
this.contentDisposables.add(webviewElement);
return webviewElement;
})
.then(undefined, () => {
@@ -603,7 +607,7 @@ export class ExtensionEditor extends BaseEditor {
const layout = () => scrollableContent.scanDomNode();
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout });
this.contentDisposables.push(toDisposable(removeLayoutParticipant));
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
const renders = [
this.renderSettings(content, manifest, layout),
@@ -629,7 +633,7 @@ export class ExtensionEditor extends BaseEditor {
append(this.content, content);
} else {
append(this.content, scrollableContent.getDomNode());
this.contentDisposables.push(scrollableContent);
this.contentDisposables.add(scrollableContent);
}
return content;
}, () => {
@@ -648,7 +652,7 @@ export class ExtensionEditor extends BaseEditor {
const content = $('div', { class: 'subcontent' });
const scrollableContent = new DomScrollableElement(content, {});
append(this.content, scrollableContent.getDomNode());
this.contentDisposables.push(scrollableContent);
this.contentDisposables.add(scrollableContent);
const dependenciesTree = this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension, null, extension => extension.dependencies || [], this.extensionsWorkbenchService), content);
const layout = () => {
@@ -657,9 +661,9 @@ export class ExtensionEditor extends BaseEditor {
dependenciesTree.layout(scrollDimensions.height);
};
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout });
this.contentDisposables.push(toDisposable(removeLayoutParticipant));
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
this.contentDisposables.push(dependenciesTree);
this.contentDisposables.add(dependenciesTree);
scrollableContent.scanDomNode();
return Promise.resolve({ focus() { dependenciesTree.domFocus(); } });
}
@@ -668,7 +672,7 @@ export class ExtensionEditor extends BaseEditor {
const content = $('div', { class: 'subcontent' });
const scrollableContent = new DomScrollableElement(content, {});
append(this.content, scrollableContent.getDomNode());
this.contentDisposables.push(scrollableContent);
this.contentDisposables.add(scrollableContent);
const extensionsPackTree = this.instantiationService.createInstance(ExtensionsTree, new ExtensionData(extension, null, extension => extension.extensionPack || [], this.extensionsWorkbenchService), content);
const layout = () => {
@@ -677,9 +681,9 @@ export class ExtensionEditor extends BaseEditor {
extensionsPackTree.layout(scrollDimensions.height);
};
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, { layout });
this.contentDisposables.push(toDisposable(removeLayoutParticipant));
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
this.contentDisposables.push(extensionsPackTree);
this.contentDisposables.add(extensionsPackTree);
scrollableContent.scanDomNode();
return Promise.resolve({ focus() { extensionsPackTree.domFocus(); } });
}
@@ -687,7 +691,7 @@ export class ExtensionEditor extends BaseEditor {
private renderSettings(container: HTMLElement, manifest: IExtensionManifest, onDetailsToggle: Function): boolean {
const contributes = manifest.contributes;
const configuration = contributes && contributes.configuration;
let properties = {};
let properties: any = {};
if (Array.isArray(configuration)) {
configuration.forEach(config => {
properties = { ...properties, ...config.properties };
@@ -1094,7 +1098,7 @@ export class ExtensionEditor extends BaseEditor {
const onDone = () => removeClass(this.content, 'loading');
result.promise.then(onDone, onDone);
this.contentDisposables.push(toDisposable(() => result.dispose()));
this.contentDisposables.add(toDisposable(() => result.dispose()));
return result.promise;
}
@@ -1110,12 +1114,6 @@ export class ExtensionEditor extends BaseEditor {
this.notificationService.error(err);
}
dispose(): void {
this.transientDisposables = dispose(this.transientDisposables);
this.disposables = dispose(this.disposables);
super.dispose();
}
}
class ShowExtensionEditorFindCommand extends Command {
@@ -1136,7 +1134,7 @@ class ShowExtensionEditorFindCommand extends Command {
}
const showCommand = new ShowExtensionEditorFindCommand({
id: 'editor.action.extensioneditor.showfind',
precondition: ContextKeyExpr.equals('activeEditor', ExtensionEditor.ID),
precondition: ContextKeyExpr.and(ContextKeyExpr.equals('activeEditor', ExtensionEditor.ID), ContextKeyExpr.not('editorFocus')),
kbOpts: {
primary: KeyMod.CtrlCmd | KeyCode.KEY_F,
weight: KeybindingWeight.EditorContrib

View File

@@ -12,7 +12,7 @@ import { Event } from 'vs/base/common/event';
import * as json from 'vs/base/common/json';
import { ActionViewItem, Separator, IActionViewItemOptions } from 'vs/base/browser/ui/actionbar/actionbar';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { 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';
@@ -48,20 +48,20 @@ import { IEnvironmentService } from 'vs/platform/environment/common/environment'
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import product from 'vs/platform/product/node/product';
import { IQuickPickItem, IQuickInputService, IQuickPickSeparator } from 'vs/platform/quickinput/common/quickInput';
import { CancellationToken } from 'vs/base/common/cancellation';
import { clipboard } from 'electron';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { coalesce } from 'vs/base/common/arrays';
import { IWorkbenchThemeService, COLOR_THEME_SETTING, ICON_THEME_SETTING, IFileIconTheme, IColorTheme } from 'vs/workbench/services/themes/common/workbenchThemeService';
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 { isUIExtension } from 'vs/workbench/services/extensions/common/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';
import { IProductService } from 'vs/platform/product/common/product';
import { IClipboardService } from 'vs/platform/clipboard/common/clipboardService';
// {{SQL CARBON EDIT}}
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
@@ -72,15 +72,16 @@ function toExtensionDescription(local: ILocalExtension): IExtensionDescription {
isBuiltin: local.type === ExtensionType.System,
isUnderDevelopment: false,
extensionLocation: local.location,
...local.manifest
...local.manifest,
uuid: local.identifier.uuid
};
}
const promptDownloadManually = (extension: IGalleryExtension | undefined, message: string, error: Error, instantiationService: IInstantiationService, notificationService: INotificationService, openerService: IOpenerService) => {
if (!extension || error.name === INSTALL_ERROR_INCOMPATIBLE || error.name === INSTALL_ERROR_MALICIOUS) {
const promptDownloadManually = (extension: IGalleryExtension | undefined, message: string, error: Error, instantiationService: IInstantiationService, notificationService: INotificationService, openerService: IOpenerService, productService: IProductService) => {
if (!extension || error.name === INSTALL_ERROR_INCOMPATIBLE || error.name === INSTALL_ERROR_MALICIOUS || !productService.extensionsGallery) {
return Promise.reject(error);
} else {
const downloadUrl = `${product.extensionsGallery.serviceUrl}/publishers/${extension.publisher}/vsextensions/${extension.name}/${extension.version}/vspackage`;
const downloadUrl = `${productService.extensionsGallery.serviceUrl}/publishers/${extension.publisher}/vsextensions/${extension.name}/${extension.version}/vspackage`;
notificationService.prompt(Severity.Error, message, [{
label: localize('download', "Download Manually"),
run: () => openerService.open(URI.parse(downloadUrl)).then(() => {
@@ -151,7 +152,6 @@ export class InstallAction extends ExtensionAction {
private static readonly Class = 'extension-action prominent install';
private static readonly InstallingClass = 'extension-action install installing';
private disposables: IDisposable[] = [];
private _manifest: IExtensionManifest | null;
set manifest(manifest: IExtensionManifest) {
@@ -168,11 +168,12 @@ export class InstallAction extends ExtensionAction {
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
@ILabelService private readonly labelService: ILabelService
) {
super(`extensions.install`, InstallAction.INSTALL_LABEL, InstallAction.Class, false);
this.update();
this.labelService.onDidChangeFormatters(() => this.updateLabel(), this, this.disposables);
this._register(this.labelService.onDidChangeFormatters(() => this.updateLabel(), this));
}
update(): void {
@@ -197,7 +198,7 @@ export class InstallAction extends ExtensionAction {
this.tooltip = InstallAction.INSTALLING_LABEL;
} else {
if (this._manifest && this.workbenchEnvironmentService.configuration.remoteAuthority) {
if (isUIExtension(this._manifest, this.configurationService)) {
if (isUIExtension(this._manifest, this.productService, this.configurationService)) {
this.label = `${InstallAction.INSTALL_LABEL} ${localize('locally', "Locally")}`;
this.tooltip = `${InstallAction.INSTALL_LABEL} ${localize('locally', "Locally")}`;
} else {
@@ -221,7 +222,7 @@ export class InstallAction extends ExtensionAction {
alert(localize('installExtensionComplete', "Installing extension {0} is completed. Please reload Azure Data Studio to enable it.", this.extension.displayName));
// Add extension object check since ADS third party extensions will be directed to a download page
// {{SQL CARBON EDIT}} Add extension object check since ADS third party extensions will be directed to a download page
// and the extension object will be undefined.
if (extension && extension.local) {
const runningExtension = await this.getRunningExtension(extension.local);
@@ -243,7 +244,7 @@ export class InstallAction extends ExtensionAction {
}
private install(extension: IExtension): Promise<IExtension> {
private install(extension: IExtension): Promise<IExtension | void> {
return this.extensionsWorkbenchService.install(extension)
.then(null, err => {
// {{SQL CARBON EDIT}}
@@ -259,7 +260,7 @@ export class InstallAction extends ExtensionAction {
console.error(err);
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService, this.productService);
});
}
@@ -281,11 +282,6 @@ export class InstallAction extends ExtensionAction {
}
return null;
}
dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class RemoteInstallAction extends ExtensionAction {
@@ -297,7 +293,6 @@ export class RemoteInstallAction extends ExtensionAction {
private static readonly InstallingClass = 'extension-action install installing';
updateWhenCounterExtensionChanges: boolean = true;
private disposables: IDisposable[] = [];
private installing: boolean = false;
constructor(
@@ -306,9 +301,10 @@ export class RemoteInstallAction extends ExtensionAction {
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
) {
super(`extensions.remoteinstall`, RemoteInstallAction.INSTALL_LABEL, RemoteInstallAction.Class, false);
this.labelService.onDidChangeFormatters(() => this.updateLabel(), this, this.disposables);
this._register(this.labelService.onDidChangeFormatters(() => this.updateLabel(), this));
this.updateLabel();
this.update();
}
@@ -341,7 +337,7 @@ export class RemoteInstallAction extends ExtensionAction {
// Installed User Extension
&& this.extension && this.extension.local && this.extension.type === ExtensionType.User && this.extension.state === ExtensionState.Installed
// Local Workspace Extension
&& this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && (isLanguagePackExtension(this.extension.local.manifest) || !isUIExtension(this.extension.local.manifest, this.configurationService))
&& this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && (isLanguagePackExtension(this.extension.local.manifest) || !isUIExtension(this.extension.local.manifest, this.productService, this.configurationService))
// Extension does not exist in remote
&& !this.extensionsWorkbenchService.installed.some(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.extensionManagementServerService.remoteExtensionManagementServer)
&& this.extensionsWorkbenchService.canInstall(this.extension)
@@ -365,11 +361,6 @@ export class RemoteInstallAction extends ExtensionAction {
}
}
}
dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class LocalInstallAction extends ExtensionAction {
@@ -381,7 +372,6 @@ export class LocalInstallAction extends ExtensionAction {
private static readonly InstallingClass = 'extension-action install installing';
updateWhenCounterExtensionChanges: boolean = true;
private disposables: IDisposable[] = [];
private installing: boolean = false;
constructor(
@@ -390,9 +380,10 @@ export class LocalInstallAction extends ExtensionAction {
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
) {
super(`extensions.localinstall`, LocalInstallAction.INSTALL_LABEL, LocalInstallAction.Class, false);
this.labelService.onDidChangeFormatters(() => this.updateLabel(), this, this.disposables);
this._register(this.labelService.onDidChangeFormatters(() => this.updateLabel(), this));
this.updateLabel();
this.update();
}
@@ -420,7 +411,7 @@ export class LocalInstallAction extends ExtensionAction {
// Installed User Extension
&& this.extension && this.extension.local && this.extension.type === ExtensionType.User && this.extension.state === ExtensionState.Installed
// Remote UI or Language pack Extension
&& this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && (isLanguagePackExtension(this.extension.local.manifest) || isUIExtension(this.extension.local.manifest, this.configurationService))
&& this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && (isLanguagePackExtension(this.extension.local.manifest) || isUIExtension(this.extension.local.manifest, this.productService, this.configurationService))
// Extension does not exist in local
&& !this.extensionsWorkbenchService.installed.some(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.extensionManagementServerService.localExtensionManagementServer)
&& this.extensionsWorkbenchService.canInstall(this.extension)
@@ -444,11 +435,6 @@ export class LocalInstallAction extends ExtensionAction {
}
}
}
dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class UninstallAction extends ExtensionAction {
@@ -483,6 +469,7 @@ export class UninstallAction extends ExtensionAction {
this.label = UninstallAction.UninstallLabel;
this.class = UninstallAction.UninstallClass;
this.tooltip = UninstallAction.UninstallLabel;
if (state !== ExtensionState.Installed) {
this.enabled = false;
@@ -512,16 +499,14 @@ export class CombinedInstallAction extends ExtensionAction {
private static readonly NoExtensionClass = 'extension-action prominent install no-extension';
private installAction: InstallAction;
private uninstallAction: UninstallAction;
private disposables: IDisposable[] = [];
constructor(
@IInstantiationService instantiationService: IInstantiationService
) {
super('extensions.combinedInstall', '', '', false);
this.installAction = instantiationService.createInstance(InstallAction);
this.uninstallAction = instantiationService.createInstance(UninstallAction);
this.disposables.push(this.installAction, this.uninstallAction);
this.installAction = this._register(instantiationService.createInstance(InstallAction));
this.uninstallAction = this._register(instantiationService.createInstance(UninstallAction));
this.update();
}
@@ -574,11 +559,6 @@ export class CombinedInstallAction extends ExtensionAction {
return Promise.resolve();
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class UpdateAction extends ExtensionAction {
@@ -590,7 +570,8 @@ export class UpdateAction extends ExtensionAction {
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@INotificationService private readonly notificationService: INotificationService,
@IOpenerService private readonly openerService: IOpenerService
@IOpenerService private readonly openerService: IOpenerService,
@IProductService private readonly productService: IProductService
) {
super(`extensions.update`, '', UpdateAction.DisabledClass, false);
this.update();
@@ -641,7 +622,7 @@ export class UpdateAction extends ExtensionAction {
console.error(err);
return promptDownloadManually(extension.gallery, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
return promptDownloadManually(extension.gallery, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService, this.productService);
});
}
@@ -688,8 +669,6 @@ export class ExtensionActionViewItem extends ActionViewItem {
export abstract class ExtensionDropDownAction extends ExtensionAction {
protected disposables: IDisposable[] = [];
constructor(
id: string,
label: string,
@@ -713,17 +692,10 @@ export abstract class ExtensionDropDownAction extends ExtensionAction {
}
return Promise.resolve();
}
dispose(): void {
dispose(this.disposables);
super.dispose();
}
}
export class DropDownMenuActionViewItem extends ExtensionActionViewItem {
private disposables: IDisposable[] = [];
constructor(action: ExtensionDropDownAction,
tabOnlyOnFocus: boolean,
@IContextMenuService private readonly contextMenuService: IContextMenuService
@@ -752,11 +724,6 @@ export class DropDownMenuActionViewItem extends ExtensionActionViewItem {
}
return actions.length ? actions.slice(0, actions.length - 1) : actions;
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class ManageExtensionAction extends ExtensionDropDownAction {
@@ -841,7 +808,8 @@ export class InstallAnotherVersionAction extends ExtensionAction {
@IQuickInputService private readonly quickInputService: IQuickInputService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@INotificationService private readonly notificationService: INotificationService,
@IOpenerService private readonly openerService: IOpenerService
@IOpenerService private readonly openerService: IOpenerService,
@IProductService private readonly productService: IProductService
) {
super(InstallAnotherVersionAction.ID, InstallAnotherVersionAction.LABEL);
this.update();
@@ -870,7 +838,7 @@ export class InstallAnotherVersionAction extends ExtensionAction {
console.error(err);
return promptDownloadManually(this.extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", this.extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
return promptDownloadManually(this.extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", this.extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService, this.productService);
});
}
return null;
@@ -888,7 +856,9 @@ export class ExtensionInfoAction extends ExtensionAction {
static readonly ID = 'extensions.extensionInfo';
static readonly LABEL = localize('extensionInfoAction', "Copy Extension Information");
constructor() {
constructor(
@IClipboardService private readonly clipboardService: IClipboardService
) {
super(ExtensionInfoAction.ID, ExtensionInfoAction.LABEL);
this.update();
}
@@ -908,8 +878,7 @@ export class ExtensionInfoAction extends ExtensionAction {
const clipboardStr = `${name}\n${id}\n${description}\n${verision}\n${publisher}${link ? '\n' + link : ''}`;
clipboard.writeText(clipboardStr);
return Promise.resolve();
return this.clipboardService.writeText(clipboardStr);
}
}
@@ -1000,7 +969,7 @@ export class DisableForWorkspaceAction extends ExtensionAction {
update(): void {
this.enabled = false;
if (this.extension && this.runningExtensions.some(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier) && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY)) {
if (this.extension && this.runningExtensions.some(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier) && this.workspaceContextService.getWorkbenchState() !== WorkbenchState.EMPTY)) {
this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && !!this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local);
}
}
@@ -1025,7 +994,7 @@ export class DisableGloballyAction extends ExtensionAction {
update(): void {
this.enabled = false;
if (this.extension && this.runningExtensions.some(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier))) {
if (this.extension && this.runningExtensions.some(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier))) {
this.enabled = this.extension.state === ExtensionState.Installed && (this.extension.enablementState === EnablementState.Enabled || this.extension.enablementState === EnablementState.WorkspaceEnabled) && !!this.extension.local && this.extensionEnablementService.canChangeEnablement(this.extension.local);
}
}
@@ -1122,7 +1091,7 @@ export class CheckForUpdatesAction extends Action {
private checkUpdatesAndNotify(): void {
const outdated = this.extensionsWorkbenchService.outdated;
if (!outdated.length) {
this.notificationService.info(localize('noUpdatesAvailable', "All Extensions are up to date."));
this.notificationService.info(localize('noUpdatesAvailable', "All extensions are up to date."));
return;
}
@@ -1208,19 +1177,18 @@ export class UpdateAllAction extends Action {
static readonly ID = 'workbench.extensions.action.updateAllExtensions';
static LABEL = localize('updateAll', "Update All Extensions");
private disposables: IDisposable[] = [];
constructor(
id = UpdateAllAction.ID,
label = UpdateAllAction.LABEL,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@INotificationService private readonly notificationService: INotificationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IOpenerService private readonly openerService: IOpenerService
@IOpenerService private readonly openerService: IOpenerService,
@IProductService private readonly productService: IProductService
) {
super(id, label, '', false);
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
this._register(this.extensionsWorkbenchService.onChange(() => this.update()));
this.update();
}
@@ -1240,14 +1208,9 @@ export class UpdateAllAction extends Action {
console.error(err);
return promptDownloadManually(extension.gallery, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
return promptDownloadManually(extension.gallery, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService, this.productService);
});
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class ReloadAction extends ExtensionAction {
@@ -1256,7 +1219,6 @@ export class ReloadAction extends ExtensionAction {
private static readonly DisabledClass = `${ReloadAction.EnabledClass} disabled`;
updateWhenCounterExtensionChanges: boolean = true;
private disposables: IDisposable[] = [];
private _runningExtensions: IExtensionDescription[] | null = null;
constructor(
@@ -1266,10 +1228,11 @@ export class ReloadAction extends ExtensionAction {
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IConfigurationService private readonly configurationService: IConfigurationService
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
) {
super('extensions.reload', localize('reloadAction', "Reload"), ReloadAction.DisabledClass, false);
this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this, this.disposables);
this._register(this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this));
this.updateRunningExtensions();
}
@@ -1299,7 +1262,7 @@ export class ReloadAction extends ExtensionAction {
return;
}
const isUninstalled = this.extension.state === ExtensionState.Uninstalled;
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier))[0];
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier))[0];
const isSameExtensionRunning = runningExtension && this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation);
if (isUninstalled) {
@@ -1350,7 +1313,7 @@ export class ReloadAction extends ExtensionAction {
return;
}
if (this.workbenchEnvironmentService.configuration.remoteAuthority) {
const uiExtension = isUIExtension(this.extension.local.manifest, this.configurationService);
const uiExtension = isUIExtension(this.extension.local.manifest, this.productService, this.configurationService);
// Local Workspace Extension
if (!uiExtension && this.extension.server === this.extensionManagementServerService.localExtensionManagementServer) {
const remoteExtension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, this.extension.identifier) && e.server === this.extensionManagementServerService.remoteExtensionManagementServer)[0];
@@ -1383,11 +1346,6 @@ export class ReloadAction extends ExtensionAction {
run(): Promise<any> {
return Promise.resolve(this.windowService.reloadWindow());
}
dispose(): void {
dispose(this.disposables);
super.dispose();
}
}
export class SetColorThemeAction extends ExtensionAction {
@@ -1399,7 +1357,6 @@ export class SetColorThemeAction extends ExtensionAction {
private static readonly EnabledClass = 'extension-action theme';
private static readonly DisabledClass = `${SetColorThemeAction.EnabledClass} disabled`;
private disposables: IDisposable[] = [];
constructor(
private readonly colorThemes: IColorTheme[],
@@ -1409,7 +1366,7 @@ export class SetColorThemeAction extends ExtensionAction {
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super(`extensions.colorTheme`, localize('color theme', "Set Color Theme"), SetColorThemeAction.DisabledClass, false);
Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidColorThemeChange)(() => this.update(), this, this.disposables);
this._register(Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidColorThemeChange)(() => this.update(), this));
this.update();
}
@@ -1455,11 +1412,6 @@ export class SetColorThemeAction extends ExtensionAction {
const target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
return this.workbenchThemeService.setColorTheme(pickedTheme ? pickedTheme.id : currentTheme.id, target);
}
dispose() {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class SetFileIconThemeAction extends ExtensionAction {
@@ -1467,7 +1419,6 @@ export class SetFileIconThemeAction extends ExtensionAction {
private static readonly EnabledClass = 'extension-action theme';
private static readonly DisabledClass = `${SetFileIconThemeAction.EnabledClass} disabled`;
private disposables: IDisposable[] = [];
static getFileIconThemes(fileIconThemes: IFileIconTheme[], extension: IExtension): IFileIconTheme[] {
return fileIconThemes.filter(c => c.extensionData && ExtensionIdentifier.equals(c.extensionData.extensionId, extension.identifier.id));
@@ -1481,7 +1432,7 @@ export class SetFileIconThemeAction extends ExtensionAction {
@IConfigurationService private readonly configurationService: IConfigurationService
) {
super(`extensions.fileIconTheme`, localize('file icon theme', "Set File Icon Theme"), SetFileIconThemeAction.DisabledClass, false);
Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidFileIconThemeChange)(() => this.update(), this, this.disposables);
this._register(Event.any<any>(extensionService.onDidChangeExtensions, workbenchThemeService.onDidFileIconThemeChange)(() => this.update(), this));
this.update();
}
@@ -1527,11 +1478,6 @@ export class SetFileIconThemeAction extends ExtensionAction {
const target = typeof confValue.workspace !== 'undefined' ? ConfigurationTarget.WORKSPACE : ConfigurationTarget.USER;
return this.workbenchThemeService.setFileIconTheme(pickedTheme ? pickedTheme.id : currentTheme.id, target);
}
dispose() {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class OpenExtensionsViewletAction extends ShowViewletAction {
@@ -1629,8 +1575,6 @@ export class ClearExtensionsInputAction extends Action {
static readonly ID = 'workbench.extensions.action.clearExtensionsInput';
static LABEL = localize('clearExtensionsInput', "Clear Extensions Input");
private disposables: IDisposable[] = [];
constructor(
id: string,
label: string,
@@ -1640,7 +1584,7 @@ export class ClearExtensionsInputAction extends Action {
) {
super(id, label, 'clear-extensions', true);
this.onSearchChange(value);
onSearchChange(this.onSearchChange, this, this.disposables);
this._register(onSearchChange(this.onSearchChange, this));
}
private onSearchChange(value: string): void {
@@ -1655,10 +1599,6 @@ export class ClearExtensionsInputAction extends Action {
viewlet.focus();
});
}
dispose(): void {
this.disposables = dispose(this.disposables);
}
}
export class ShowBuiltInExtensionsAction extends Action {
@@ -1772,7 +1712,8 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action {
@IOpenerService private readonly openerService: IOpenerService,
@IExtensionsWorkbenchService private readonly extensionWorkbenchService: IExtensionsWorkbenchService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IProductService private readonly productService: IProductService,
) {
super(id, label, 'extension-action');
this.recommendations = recommendations;
@@ -1799,7 +1740,7 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action {
private async installExtension(extension: IExtension): Promise<void> {
try {
if (extension.local && extension.gallery) {
if (isUIExtension(extension.local.manifest, this.configurationService)) {
if (isUIExtension(extension.local.manifest, this.productService, this.configurationService)) {
await this.extensionManagementServerService.localExtensionManagementServer.extensionManagementService.installFromGallery(extension.gallery);
return;
} else if (this.extensionManagementServerService.remoteExtensionManagementServer) {
@@ -1810,7 +1751,7 @@ export class InstallWorkspaceRecommendedExtensionsAction extends Action {
await this.extensionWorkbenchService.install(extension);
} catch (err) {
console.error(err);
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService, this.productService);
}
}
}
@@ -1828,7 +1769,8 @@ export class InstallRecommendedExtensionAction extends Action {
@INotificationService private readonly notificationService: INotificationService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IOpenerService private readonly openerService: IOpenerService,
@IExtensionsWorkbenchService private readonly extensionWorkbenchService: IExtensionsWorkbenchService
@IExtensionsWorkbenchService private readonly extensionWorkbenchService: IExtensionsWorkbenchService,
@IProductService private readonly productService: IProductService
) {
super(InstallRecommendedExtensionAction.ID, InstallRecommendedExtensionAction.LABEL, undefined, false);
this.extensionId = extensionId;
@@ -1847,7 +1789,7 @@ export class InstallRecommendedExtensionAction extends Action {
return this.extensionWorkbenchService.install(extension)
.then(() => null, err => {
console.error(err);
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
return promptDownloadManually(extension.gallery, localize('failedToInstall', "Failed to install \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService, this.productService);
});
}
return null;
@@ -1862,7 +1804,6 @@ export class IgnoreExtensionRecommendationAction extends Action {
private static readonly Class = 'extension-action ignore';
private disposables: IDisposable[] = [];
extension: IExtension;
constructor(
@@ -1879,11 +1820,6 @@ export class IgnoreExtensionRecommendationAction extends Action {
this.extensionsTipsService.toggleIgnoredRecommendation(this.extension.identifier.id, true);
return Promise.resolve();
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class UndoIgnoreExtensionRecommendationAction extends Action {
@@ -1892,7 +1828,6 @@ export class UndoIgnoreExtensionRecommendationAction extends Action {
private static readonly Class = 'extension-action undo-ignore';
private disposables: IDisposable[] = [];
extension: IExtension;
constructor(
@@ -1909,11 +1844,6 @@ export class UndoIgnoreExtensionRecommendationAction extends Action {
this.extensionsTipsService.toggleIgnoredRecommendation(this.extension.identifier.id, false);
return Promise.resolve();
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
@@ -1989,7 +1919,6 @@ export class ShowAzureExtensionsAction extends Action {
export class ChangeSortAction extends Action {
private query: Query;
private disposables: IDisposable[] = [];
constructor(
id: string,
@@ -2006,7 +1935,7 @@ export class ChangeSortAction extends Action {
this.query = Query.parse('');
this.enabled = false;
onSearchChange(this.onSearchChange, this, this.disposables);
this._register(onSearchChange(this.onSearchChange, this));
}
private onSearchChange(value: string): void {
@@ -2311,7 +2240,6 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends AbstractConfi
static readonly ID = 'workbench.extensions.action.configureWorkspaceRecommendedExtensions';
static LABEL = localize('configureWorkspaceRecommendedExtensions', "Configure Recommended Extensions (Workspace)");
private disposables: IDisposable[] = [];
constructor(
id: string,
@@ -2324,7 +2252,7 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends AbstractConfi
@ITextModelService textModelResolverService: ITextModelService
) {
super(id, label, contextService, fileService, textFileService, editorService, jsonEditingService, textModelResolverService);
this.contextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables);
this._register(this.contextService.onDidChangeWorkbenchState(() => this.update(), this));
this.update();
}
@@ -2341,11 +2269,6 @@ export class ConfigureWorkspaceRecommendedExtensionsAction extends AbstractConfi
}
return Promise.resolve();
}
dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class ConfigureWorkspaceFolderRecommendedExtensionsAction extends AbstractConfigureRecommendedExtensionsAction {
@@ -2353,7 +2276,6 @@ export class ConfigureWorkspaceFolderRecommendedExtensionsAction extends Abstrac
static readonly ID = 'workbench.extensions.action.configureWorkspaceFolderRecommendedExtensions';
static LABEL = localize('configureWorkspaceFolderRecommendedExtensions', "Configure Recommended Extensions (Workspace Folder)");
private disposables: IDisposable[] = [];
constructor(
id: string,
@@ -2367,7 +2289,7 @@ export class ConfigureWorkspaceFolderRecommendedExtensionsAction extends Abstrac
@ICommandService private readonly commandService: ICommandService
) {
super(id, label, contextService, fileService, textFileService, editorService, jsonEditingService, textModelResolverService);
this.contextService.onDidChangeWorkspaceFolders(() => this.update(), this, this.disposables);
this._register(this.contextService.onDidChangeWorkspaceFolders(() => this.update(), this));
this.update();
}
@@ -2386,11 +2308,6 @@ export class ConfigureWorkspaceFolderRecommendedExtensionsAction extends Abstrac
return null;
});
}
dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class AddToWorkspaceFolderRecommendationsAction extends AbstractConfigureRecommendedExtensionsAction {
@@ -2600,7 +2517,7 @@ export class StatusLabelAction extends Action implements IExtensionContainer {
const runningExtensions = await this.extensionService.getExtensions();
const canAddExtension = () => {
const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier))[0];
const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier))[0];
if (this.extension.local) {
if (runningExtension && this.extension.version === runningExtension.version) {
return true;
@@ -2611,7 +2528,7 @@ export class StatusLabelAction extends Action implements IExtensionContainer {
};
const canRemoveExtension = () => {
if (this.extension.local) {
if (runningExtensions.every(e => !(areSameExtensions({ id: e.identifier.value }, this.extension.identifier) && this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(e.extensionLocation)))) {
if (runningExtensions.every(e => !(areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier) && this.extension.server === this.extensionManagementServerService.getExtensionManagementServer(e.extensionLocation)))) {
return true;
}
return this.extensionService.canRemoveExtension(toExtensionDescription(this.extension.local));
@@ -2679,7 +2596,6 @@ export class DisabledLabelAction extends ExtensionAction {
private static readonly Class = 'disable-status';
updateWhenCounterExtensionChanges: boolean = true;
private disposables: IDisposable[] = [];
private _runningExtensions: IExtensionDescription[] | null = null;
constructor(
@@ -2688,8 +2604,8 @@ export class DisabledLabelAction extends ExtensionAction {
@IExtensionService private readonly extensionService: IExtensionService,
) {
super('extensions.disabledLabel', warningAction.tooltip, `${DisabledLabelAction.Class} hide`, false);
warningAction.onDidChange(() => this.update(), this, this.disposables);
this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this, this.disposables);
this._register(warningAction.onDidChange(() => this.update(), this));
this._register(this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this));
this.updateRunningExtensions();
}
@@ -2710,7 +2626,7 @@ export class DisabledLabelAction extends ExtensionAction {
}
if (this.extension && this.extension.local && this._runningExtensions) {
const isEnabled = this.extensionEnablementService.isEnabled(this.extension.local);
const isExtensionRunning = this._runningExtensions.some(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier));
const isExtensionRunning = this._runningExtensions.some(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier));
if (!isExtensionRunning && !isEnabled && this.extensionEnablementService.canChangeEnablement(this.extension.local)) {
this.class = DisabledLabelAction.Class;
this.label = localize('disabled by user', "This extension is disabled by the user.");
@@ -2722,11 +2638,6 @@ export class DisabledLabelAction extends ExtensionAction {
run(): Promise<any> {
return Promise.resolve(null);
}
dispose(): void {
dispose(this.disposables);
super.dispose();
}
}
export class SystemDisabledWarningAction extends ExtensionAction {
@@ -2736,20 +2647,20 @@ export class SystemDisabledWarningAction extends ExtensionAction {
private static readonly INFO_CLASS = `${SystemDisabledWarningAction.CLASS} info`;
updateWhenCounterExtensionChanges: boolean = true;
private disposables: IDisposable[] = [];
private _runningExtensions: IExtensionDescription[] | null = null;
constructor(
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
@ILabelService private readonly labelService: ILabelService,
@IWorkbenchEnvironmentService private readonly workbenchEnvironmentService: IWorkbenchEnvironmentService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionService private readonly extensionService: IExtensionService,
) {
super('extensions.install', '', `${SystemDisabledWarningAction.CLASS} hide`, false);
this.labelService.onDidChangeFormatters(() => this.update(), this, this.disposables);
this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this, this.disposables);
this._register(this.labelService.onDidChangeFormatters(() => this.update(), this));
this._register(this.extensionService.onDidChangeExtensions(this.updateRunningExtensions, this));
this.updateRunningExtensions();
this.update();
}
@@ -2781,11 +2692,11 @@ export class SystemDisabledWarningAction extends ExtensionAction {
}
return;
}
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value }, this.extension.identifier))[0];
const runningExtension = this._runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, this.extension.identifier))[0];
const runningExtensionServer = runningExtension ? this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation) : null;
const localExtension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, this.extension.identifier))[0];
const localExtensionServer = localExtension ? localExtension.server : null;
if (this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.configurationService)) {
if (this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && !isUIExtension(this.extension.local.manifest, this.productService, this.configurationService)) {
if (runningExtensionServer === this.extensionManagementServerService.remoteExtensionManagementServer) {
this.class = `${SystemDisabledWarningAction.INFO_CLASS}`;
this.tooltip = localize('disabled locally', "Extension is enabled on '{0}' and disabled locally.", this.getServerLabel(this.extensionManagementServerService.remoteExtensionManagementServer));
@@ -2797,7 +2708,7 @@ export class SystemDisabledWarningAction extends ExtensionAction {
return;
}
}
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && isUIExtension(this.extension.local.manifest, this.configurationService)) {
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && isUIExtension(this.extension.local.manifest, this.productService, this.configurationService)) {
if (runningExtensionServer === this.extensionManagementServerService.localExtensionManagementServer) {
this.class = `${SystemDisabledWarningAction.INFO_CLASS}`;
this.tooltip = localize('disabled remotely', "Extension is enabled locally and disabled on '{0}'.", this.getServerLabel(this.extensionManagementServerService.remoteExtensionManagementServer));
@@ -2820,11 +2731,6 @@ export class SystemDisabledWarningAction extends ExtensionAction {
run(): Promise<any> {
return Promise.resolve(null);
}
dispose(): void {
dispose(this.disposables);
super.dispose();
}
}
export class DisableAllAction extends Action {
@@ -2832,7 +2738,6 @@ export class DisableAllAction extends Action {
static readonly ID = 'workbench.extensions.action.disableAll';
static LABEL = localize('disableAll', "Disable All Installed Extensions");
private disposables: IDisposable[] = [];
constructor(
id: string = DisableAllAction.ID, label: string = DisableAllAction.LABEL,
@@ -2841,7 +2746,7 @@ export class DisableAllAction extends Action {
) {
super(id, label);
this.update();
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
this._register(this.extensionsWorkbenchService.onChange(() => this.update()));
}
private update(): void {
@@ -2851,11 +2756,6 @@ export class DisableAllAction extends Action {
run(): Promise<any> {
return this.extensionsWorkbenchService.setEnablement(this.extensionsWorkbenchService.local.filter(e => e.type === ExtensionType.User), EnablementState.Disabled);
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class DisableAllWorkpsaceAction extends Action {
@@ -2863,7 +2763,6 @@ export class DisableAllWorkpsaceAction extends Action {
static readonly ID = 'workbench.extensions.action.disableAllWorkspace';
static LABEL = localize('disableAllWorkspace', "Disable All Installed Extensions for this Workspace");
private disposables: IDisposable[] = [];
constructor(
id: string = DisableAllWorkpsaceAction.ID, label: string = DisableAllWorkpsaceAction.LABEL,
@@ -2872,8 +2771,8 @@ export class DisableAllWorkpsaceAction extends Action {
) {
super(id, label);
this.update();
this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables);
this.extensionsWorkbenchService.onChange(() => this.update(), this, this.disposables);
this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this));
this._register(this.extensionsWorkbenchService.onChange(() => this.update(), this));
}
private update(): void {
@@ -2883,11 +2782,6 @@ export class DisableAllWorkpsaceAction extends Action {
run(): Promise<any> {
return this.extensionsWorkbenchService.setEnablement(this.extensionsWorkbenchService.local.filter(e => e.type === ExtensionType.User), EnablementState.WorkspaceDisabled);
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class EnableAllAction extends Action {
@@ -2895,7 +2789,6 @@ export class EnableAllAction extends Action {
static readonly ID = 'workbench.extensions.action.enableAll';
static LABEL = localize('enableAll', "Enable All Extensions");
private disposables: IDisposable[] = [];
constructor(
id: string = EnableAllAction.ID, label: string = EnableAllAction.LABEL,
@@ -2904,7 +2797,7 @@ export class EnableAllAction extends Action {
) {
super(id, label);
this.update();
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
this._register(this.extensionsWorkbenchService.onChange(() => this.update()));
}
private update(): void {
@@ -2914,11 +2807,6 @@ export class EnableAllAction extends Action {
run(): Promise<any> {
return this.extensionsWorkbenchService.setEnablement(this.extensionsWorkbenchService.local, EnablementState.Enabled);
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class EnableAllWorkpsaceAction extends Action {
@@ -2926,7 +2814,6 @@ export class EnableAllWorkpsaceAction extends Action {
static readonly ID = 'workbench.extensions.action.enableAllWorkspace';
static LABEL = localize('enableAllWorkspace', "Enable All Extensions for this Workspace");
private disposables: IDisposable[] = [];
constructor(
id: string = EnableAllWorkpsaceAction.ID, label: string = EnableAllWorkpsaceAction.LABEL,
@@ -2936,8 +2823,8 @@ export class EnableAllWorkpsaceAction extends Action {
) {
super(id, label);
this.update();
this.extensionsWorkbenchService.onChange(() => this.update(), this, this.disposables);
this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this, this.disposables);
this._register(this.extensionsWorkbenchService.onChange(() => this.update(), this));
this._register(this.workspaceContextService.onDidChangeWorkbenchState(() => this.update(), this));
}
private update(): void {
@@ -2947,11 +2834,6 @@ export class EnableAllWorkpsaceAction extends Action {
run(): Promise<any> {
return this.extensionsWorkbenchService.setEnablement(this.extensionsWorkbenchService.local, EnablementState.WorkspaceEnabled);
}
dispose(): void {
super.dispose();
this.disposables = dispose(this.disposables);
}
}
export class OpenExtensionsFolderAction extends Action {

View File

@@ -5,7 +5,7 @@
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { localize } from 'vs/nls';
import { IDisposable } from 'vs/base/common/lifecycle';
import { timeout } from 'vs/base/common/async';
@@ -17,7 +17,7 @@ export class ExtensionActivationProgress implements IWorkbenchContribution {
constructor(
@IExtensionService extensionService: IExtensionService,
@IProgressService2 progressService: IProgressService2,
@IProgressService progressService: IProgressService,
@ILogService logService: ILogService,
) {

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import { append, $, addClass, removeClass, toggleClass } from 'vs/base/browser/dom';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IDisposable, dispose, combinedDisposable } from 'vs/base/common/lifecycle';
import { Action } from 'vs/base/common/actions';
import { ActionBar } from 'vs/base/browser/ui/actionbar/actionbar';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
@@ -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, ExtensionActionViewItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { InstallAction, UpdateAction, ManageExtensionAction, ReloadAction, MaliciousStatusLabelAction, ExtensionActionViewItem, StatusLabelAction, RemoteInstallAction, SystemDisabledWarningAction, DisabledLabelAction, LocalInstallAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/electron-browser/extensionsWidgets';
import { Label, RatingsWidget, InstallCountWidget, RecommendationWidget, RemoteBadgeWidget, TooltipWidget } from 'vs/workbench/contrib/extensions/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';
@@ -118,11 +118,11 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
const extensionContainers: ExtensionContainers = this.instantiationService.createInstance(ExtensionContainers, [...actions, ...widgets, disabledLabelAction]);
actionbar.push(actions, actionOptions);
const disposables = [...actions, ...widgets, actionbar, extensionContainers];
const disposables = combinedDisposable(...actions, ...widgets, actionbar, extensionContainers, disabledLabelAction);
return {
// {{SQL CARBON EDIT}}
root, element, icon, name, /*installCount, ratings,*/ author, description, disposables, actionbar,
root, element, icon, name, /*installCount, ratings,*/ author, description, disposables: [disposables], actionbar,
extensionDisposables: [],
set extension(extension: IExtension) {
extensionContainers.extension = extension;
@@ -158,7 +158,7 @@ export class Renderer implements IPagedRenderer<IExtension, ITemplateData> {
const updateEnablement = async () => {
const runningExtensions = await this.extensionService.getExtensions();
if (extension.local && !isLanguagePackExtension(extension.local.manifest)) {
const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value }, extension.identifier))[0];
const runningExtension = runningExtensions.filter(e => areSameExtensions({ id: e.identifier.value, uuid: e.uuid }, extension.identifier))[0];
const isSameExtensionRunning = runningExtension && extension.server === this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation);
toggleClass(data.root, 'disabled', !isSameExtensionRunning);
} else {

View File

@@ -255,8 +255,10 @@ export class ExtensionData implements IExtensionData {
toQuery.push(id);
}
}
const galleryResult = await this.extensionsWorkbenchService.queryGallery({ names: this.childrenExtensionIds, pageSize: this.childrenExtensionIds.length }, CancellationToken.None);
result.push(...galleryResult.firstPage);
if (toQuery.length) {
const galleryResult = await this.extensionsWorkbenchService.queryGallery({ names: toQuery, pageSize: toQuery.length }, CancellationToken.None);
result.push(...galleryResult.firstPage);
}
return result.map(extension => new ExtensionData(extension, this, this.getChildrenExtensionIds, this.extensionsWorkbenchService));
}
return null;

View File

@@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
import { timeout, Delayer } from 'vs/base/common/async';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { Event as EventOf, Emitter } from 'vs/base/common/event';
import { IAction } from 'vs/base/common/actions';
import { Separator } from 'vs/base/browser/ui/actionbar/actionbar';
@@ -23,12 +23,12 @@ import {
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
} from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IExtensionManagementService, IExtensionManagementServerService, IExtensionManagementServer, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from './extensionsViews';
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
import Severity from 'vs/base/common/severity';
import { IActivityService, ProgressBadge, NumberBadge } from 'vs/workbench/services/activity/common/activity';
@@ -58,6 +58,7 @@ import { RemoteAuthorityContext } from 'vs/workbench/browser/contextkeys';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
import { ILabelService } from 'vs/platform/label/common/label';
import { MementoObject } from 'vs/workbench/common/memento';
interface SearchInputEvent extends Event {
target: HTMLInputElement;
@@ -342,13 +343,12 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private extensionsBox: HTMLElement;
private primaryActions: IAction[];
private secondaryActions: IAction[] | null;
private disposables: IDisposable[] = [];
private searchViewletState: object;
private readonly searchViewletState: MementoObject;
constructor(
@IWorkbenchLayoutService layoutService: IWorkbenchLayoutService,
@ITelemetryService telemetryService: ITelemetryService,
@IProgressService2 private readonly progressService: IProgressService2,
@IProgressService private readonly progressService: IProgressService,
@IInstantiationService instantiationService: IInstantiationService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService,
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
@@ -377,14 +377,14 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.recommendedExtensionsContextKey = RecommendedExtensionsContext.bindTo(contextKeyService);
this.defaultRecommendedExtensionsContextKey = DefaultRecommendedExtensionsContext.bindTo(contextKeyService);
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
this.disposables.push(this.viewletService.onDidViewletOpen(this.onViewletOpen, this, this.disposables));
this._register(this.viewletService.onDidViewletOpen(this.onViewletOpen, this));
this.searchViewletState = this.getMemento(StorageScope.WORKSPACE);
this.extensionManagementService.getInstalled(ExtensionType.User).then(result => {
this.hasInstalledExtensionsContextKey.set(result.length > 0);
});
this.configurationService.onDidChangeConfiguration(e => {
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(AutoUpdateConfigurationKey)) {
this.secondaryActions = null;
this.updateTitleArea();
@@ -392,7 +392,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
if (e.affectedKeys.indexOf(ShowRecommendationsOnlyOnDemandKey) > -1) {
this.defaultRecommendedExtensionsContextKey.set(!this.configurationService.getValue<boolean>(ShowRecommendationsOnlyOnDemandKey));
}
}, this, this.disposables);
}, this));
}
create(parent: HTMLElement): void {
@@ -404,7 +404,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
const placeholder = localize('searchExtensions', "Search Extensions in Marketplace");
const searchValue = this.searchViewletState['query.value'] ? this.searchViewletState['query.value'] : '';
this.searchBox = this.instantiationService.createInstance(SuggestEnabledInput, `${VIEWLET_ID}.searchbox`, header, {
this.searchBox = this._register(this.instantiationService.createInstance(SuggestEnabledInput, `${VIEWLET_ID}.searchbox`, header, {
triggerCharacters: ['@'],
sortKey: (item: string) => {
if (item.indexOf(':') === -1) { return 'a'; }
@@ -413,24 +413,22 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
else { return 'd'; }
},
provideResults: (query: string) => Query.suggestions(query)
}, placeholder, 'extensions:searchinput', { placeholderText: placeholder, value: searchValue });
}, placeholder, 'extensions:searchinput', { placeholderText: placeholder, value: searchValue }));
if (this.searchBox.getValue()) {
this.triggerSearch();
}
this.disposables.push(attachSuggestEnabledInputBoxStyler(this.searchBox, this.themeService));
this.disposables.push(this.searchBox);
this._register(attachSuggestEnabledInputBoxStyler(this.searchBox, this.themeService));
const _searchChange = new Emitter<string>();
this.onSearchChange = _searchChange.event;
this.searchBox.onInputDidChange(() => {
this._register(this.searchBox.onInputDidChange(() => {
this.triggerSearch();
_searchChange.fire(this.searchBox.getValue());
}, this, this.disposables);
}, this));
this.searchBox.onShouldFocusResults(() => this.focusListView(), this, this.disposables);
this._register(this.searchBox.onShouldFocusResults(() => this.focusListView(), this));
this._register(this.onDidChangeVisibility(visible => {
if (visible) {
@@ -619,52 +617,39 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.notificationService.error(err);
}
dispose(): void {
this.disposables = dispose(this.disposables);
super.dispose();
}
}
export class StatusUpdater implements IWorkbenchContribution {
export class StatusUpdater extends Disposable implements IWorkbenchContribution {
private disposables: IDisposable[];
private badgeHandle: IDisposable;
private readonly badgeHandle = this._register(new MutableDisposable());
constructor(
@IActivityService private readonly activityService: IActivityService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
) {
extensionsWorkbenchService.onChange(this.onServiceChange, this, this.disposables);
super();
this._register(extensionsWorkbenchService.onChange(this.onServiceChange, this));
}
private onServiceChange(): void {
dispose(this.badgeHandle);
this.badgeHandle.clear();
if (this.extensionsWorkbenchService.local.some(e => e.state === ExtensionState.Installing)) {
this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge');
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, new ProgressBadge(() => localize('extensions', "Extensions")), 'extensions-badge progress-badge');
return;
}
const outdated = this.extensionsWorkbenchService.outdated.reduce((r, e) => r + (this.extensionEnablementService.isEnabled(e.local!) ? 1 : 0), 0);
if (outdated > 0) {
const badge = new NumberBadge(outdated, n => localize('outdatedExtensions', '{0} Outdated Extensions', n));
this.badgeHandle = this.activityService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge');
this.badgeHandle.value = this.activityService.showActivity(VIEWLET_ID, badge, 'extensions-badge count-badge');
}
}
dispose(): void {
this.disposables = dispose(this.disposables);
dispose(this.badgeHandle);
}
}
export class MaliciousExtensionChecker implements IWorkbenchContribution {
private disposables: IDisposable[];
constructor(
@IExtensionManagementService private readonly extensionsManagementService: IExtensionManagementService,
@IWindowService private readonly windowService: IWindowService,
@@ -709,8 +694,4 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
}).then(() => undefined);
}, err => this.logService.error(err));
}
dispose(): void {
this.disposables = dispose(this.disposables);
}
}

View File

@@ -4,10 +4,10 @@
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { dispose, Disposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { assign } from 'vs/base/common/objects';
import { Event, Emitter } from 'vs/base/common/event';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { isPromiseCanceledError, getErrorMessage } from 'vs/base/common/errors';
import { PagedModel, IPagedModel, IPager, DelayedPagedModel } from 'vs/base/common/paging';
import { SortBy, SortOrder, IQueryOptions, IExtensionTipsService, IExtensionRecommendation, IExtensionManagementServer, IExtensionManagementServerService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
@@ -15,7 +15,7 @@ import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { append, $, toggleClass } from 'vs/base/browser/dom';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/contrib/extensions/electron-browser/extensionsList';
import { Delegate, Renderer, IExtensionsViewState } from 'vs/workbench/contrib/extensions/browser/extensionsList';
import { IExtension, IExtensionsWorkbenchService, ExtensionState } from '../common/extensions';
import { Query } from '../common/extensionQuery';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
@@ -24,18 +24,17 @@ import { attachBadgeStyler } from 'vs/platform/theme/common/styler';
import { IViewletViewOptions } from 'vs/workbench/browser/parts/views/viewsViewlet';
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IModeService } from 'vs/editor/common/services/modeService';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
import { ActionBar, Separator } from 'vs/base/browser/ui/actionbar/actionbar';
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { InstallWorkspaceRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction, ManageExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { WorkbenchPagedList } from 'vs/platform/list/browser/listService';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ViewletPanel, IViewletPanelOptions } from 'vs/workbench/browser/parts/views/panelViewlet';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { distinct, coalesce } from 'vs/base/common/arrays';
import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/contrib/experiments/node/experimentService';
import { IExperimentService, IExperiment, ExperimentActionType } from 'vs/workbench/contrib/experiments/common/experimentService';
import { alert } from 'vs/base/browser/ui/aria/aria';
import { IListContextMenuEvent } from 'vs/base/browser/ui/list/list';
import { createErrorWithActions } from 'vs/base/common/errorsWithActions';
@@ -43,9 +42,10 @@ import { CancellationToken } from 'vs/base/common/cancellation';
import { IAction } from 'vs/base/common/actions';
import { ExtensionType, ExtensionIdentifier, IExtensionDescription, isLanguagePackExtension } 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';
import { isUIExtension } from 'vs/workbench/services/extensions/node/extensionsUtil';
import { isUIExtension } from 'vs/workbench/services/extensions/common/extensionsUtil';
import { IProductService } from 'vs/platform/product/common/product';
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
class ExtensionsViewState extends Disposable implements IExtensionsViewState {
@@ -68,9 +68,13 @@ export interface ExtensionsListViewOptions extends IViewletViewOptions {
server?: IExtensionManagementServer;
}
class ExtensionListViewWarning extends Error { }
export class ExtensionsListView extends ViewletPanel {
private readonly server: IExtensionManagementServer | undefined;
private messageContainer: HTMLElement;
private messageSeverityIcon: HTMLElement;
private messageBox: HTMLElement;
private extensionsList: HTMLElement;
private badge: CountBadge;
@@ -89,13 +93,13 @@ export class ExtensionsListView extends ViewletPanel {
@IExtensionsWorkbenchService protected extensionsWorkbenchService: IExtensionsWorkbenchService,
@IEditorService private readonly editorService: IEditorService,
@IExtensionTipsService protected tipsService: IExtensionTipsService,
@IModeService private readonly modeService: IModeService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@IConfigurationService configurationService: IConfigurationService,
@IWorkspaceContextService protected contextService: IWorkspaceContextService,
@IExperimentService private readonly experimentService: IExperimentService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
@IProductService protected readonly productService: IProductService,
) {
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService);
this.server = options.server;
@@ -110,12 +114,14 @@ export class ExtensionsListView extends ViewletPanel {
this.badgeContainer = append(container, $('.count-badge-wrapper'));
this.badge = new CountBadge(this.badgeContainer);
this.disposables.push(attachBadgeStyler(this.badge, this.themeService));
this._register(attachBadgeStyler(this.badge, this.themeService));
}
renderBody(container: HTMLElement): void {
this.extensionsList = append(container, $('.extensions-list'));
this.messageBox = append(container, $('.message'));
this.messageContainer = append(container, $('.message-container'));
this.messageSeverityIcon = append(this.messageContainer, $(''));
this.messageBox = append(this.messageContainer, $('.message'));
const delegate = new Delegate();
const extensionsViewState = new ExtensionsViewState();
const renderer = this.instantiationService.createInstance(Renderer, extensionsViewState);
@@ -125,20 +131,20 @@ export class ExtensionsListView extends ViewletPanel {
setRowLineHeight: false,
horizontalScrolling: false
}) as WorkbenchPagedList<IExtension>;
this.list.onContextMenu(e => this.onContextMenu(e), this, this.disposables);
this.list.onFocusChange(e => extensionsViewState.onFocusChange(coalesce(e.elements)), this, this.disposables);
this.disposables.push(this.list);
this.disposables.push(extensionsViewState);
this._register(this.list.onContextMenu(e => this.onContextMenu(e), this));
this._register(this.list.onFocusChange(e => extensionsViewState.onFocusChange(coalesce(e.elements)), this));
this._register(this.list);
this._register(extensionsViewState);
Event.chain(this.list.onOpen)
this._register(Event.chain(this.list.onOpen)
.map(e => e.elements[0])
.filter(e => !!e)
.on(this.openExtension, this, this.disposables);
.on(this.openExtension, this));
Event.chain(this.list.onPin)
this._register(Event.chain(this.list.onPin)
.map(e => e.elements[0])
.filter(e => !!e)
.on(this.pin, this, this.disposables);
.on(this.pin, this));
}
protected layoutBody(height: number, width: number): void {
@@ -176,12 +182,11 @@ export class ExtensionsListView extends ViewletPanel {
};
const errorCallback = (e: Error) => {
const errorCallback = (e: any) => {
const model = new PagedModel([]);
if (!isPromiseCanceledError(e)) {
this.queryRequest = null;
console.warn('Error querying extensions gallery', e);
this.setModel(model, true);
this.setModel(model, e);
}
return this.list ? this.list.model : model;
};
@@ -236,7 +241,11 @@ export class ExtensionsListView extends ViewletPanel {
if (ExtensionsListView.isLocalExtensionsQuery(query.value) || /@builtin/.test(query.value)) {
return this.queryLocal(query, options);
}
return this.queryGallery(query, options, token);
return this.queryGallery(query, options, token)
.then(null, e => {
console.warn('Error querying extensions gallery', getErrorMessage(e));
return Promise.reject(new ExtensionListViewWarning(localize('galleryError', "We cannot connect to the Extensions Marketplace at this time, please try again later.")));
});
}
private async queryByIds(ids: string[], options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
@@ -383,7 +392,7 @@ export class ExtensionsListView extends ViewletPanel {
const result = local
.sort((e1, e2) => e1.displayName.localeCompare(e2.displayName))
.filter(e => runningExtensions.every(r => !areSameExtensions({ id: r.identifier.value }, e.identifier))
.filter(e => runningExtensions.every(r => !areSameExtensions({ id: r.identifier.value, uuid: r.uuid }, e.identifier))
&& (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))));
@@ -398,7 +407,7 @@ export class ExtensionsListView extends ViewletPanel {
const result = local
.sort((e1, e2) => e1.displayName.localeCompare(e2.displayName))
.filter(e => runningExtensions.some(r => areSameExtensions({ id: r.identifier.value }, e.identifier))
.filter(e => runningExtensions.some(r => areSameExtensions({ id: r.identifier.value, uuid: r.uuid }, e.identifier))
&& (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))));
@@ -431,29 +440,11 @@ export class ExtensionsListView extends ViewletPanel {
return this.getCuratedModel(query, options, token);
}
let text = query.value;
const extensionRegex = /\bext:([^\s]+)\b/g;
const text = query.value;
if (extensionRegex.test(query.value)) {
text = query.value.replace(extensionRegex, (m, ext) => {
// Get curated keywords
const lookup = product.extensionKeywords || {};
const keywords = lookup[ext] || [];
// Get mode name
const modeId = this.modeService.getModeIdByFilepathOrFirstLine(`.${ext}`);
const languageName = modeId && this.modeService.getLanguageName(modeId);
const languageTag = languageName ? ` tag:"${languageName}"` : '';
// Construct a rich query
return `tag:"__ext_${ext}" tag:"__ext_.${ext}" ${keywords.map(tag => `tag:"${tag}"`).join(' ')}${languageTag} tag:"${ext}"`;
});
if (text !== query.value) {
options = assign(options, { text: text.substr(0, 350), source: 'file-extension-tags' });
return this.extensionsWorkbenchService.queryGallery(options, token).then(pager => this.getPagedModel(pager));
}
if (/\bext:([^\s]+)\b/g.test(text)) {
options = assign(options, { text, source: 'file-extension-tags' });
return this.extensionsWorkbenchService.queryGallery(options, token).then(pager => this.getPagedModel(pager));
}
let preferredResults: string[] = [];
@@ -733,28 +724,36 @@ export class ExtensionsListView extends ViewletPanel {
});
}
private setModel(model: IPagedModel<IExtension>, isGalleryError?: boolean) {
private setModel(model: IPagedModel<IExtension>, error?: any) {
if (this.list) {
this.list.model = new DelayedPagedModel(model);
this.list.scrollTop = 0;
const count = this.count();
toggleClass(this.extensionsList, 'hidden', count === 0);
toggleClass(this.messageBox, 'hidden', count > 0);
toggleClass(this.messageContainer, 'hidden', count > 0);
this.badge.setCount(count);
if (count === 0 && this.isBodyVisible()) {
this.messageBox.textContent = isGalleryError ? localize('galleryError', "We cannot connect to the Extensions Marketplace at this time, please try again later.") : localize('no extensions found', "No extensions found.");
if (isGalleryError) {
alert(this.messageBox.textContent);
if (error) {
if (error instanceof ExtensionListViewWarning) {
this.messageSeverityIcon.className = SeverityIcon.className(Severity.Warning);
this.messageBox.textContent = getErrorMessage(error);
} else {
this.messageSeverityIcon.className = SeverityIcon.className(Severity.Error);
this.messageBox.textContent = localize('error', "Error while loading extensions. {0}", getErrorMessage(error));
}
} else {
this.messageSeverityIcon.className = '';
this.messageBox.textContent = localize('no extensions found', "No extensions found.");
}
} else {
this.messageBox.textContent = '';
alert(this.messageBox.textContent);
}
}
}
private openExtension(extension: IExtension): void {
extension = this.extensionsWorkbenchService.local.filter(e => areSameExtensions(e.identifier, extension.identifier))[0] || extension;
this.extensionsWorkbenchService.open(extension).then(undefined, err => this.onError(err));
}
@@ -806,7 +805,6 @@ export class ExtensionsListView extends ViewletPanel {
this.queryRequest.request.cancel();
this.queryRequest = null;
}
this.disposables = dispose(this.disposables);
this.list = null;
}
@@ -886,18 +884,18 @@ export class ServerExtensionsView extends ExtensionsListView {
@IExtensionService extensionService: IExtensionService,
@IEditorService editorService: IEditorService,
@IExtensionTipsService tipsService: IExtensionTipsService,
@IModeService modeService: IModeService,
@ITelemetryService telemetryService: ITelemetryService,
@IConfigurationService configurationService: IConfigurationService,
@IWorkspaceContextService contextService: IWorkspaceContextService,
@IExperimentService experimentService: IExperimentService,
@IWorkbenchThemeService workbenchThemeService: IWorkbenchThemeService,
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService,
@IProductService productService: IProductService,
) {
options.server = server;
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, modeService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService);
this.disposables.push(onDidChangeTitle(title => this.updateTitle(title)));
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService);
this._register(onDidChangeTitle(title => this.updateTitle(title)));
}
async show(query: string): Promise<IPagedModel<IExtension>> {
@@ -910,18 +908,18 @@ export class ServerExtensionsView extends ExtensionsListView {
}
export class EnabledExtensionsView extends ExtensionsListView {
private readonly enabledExtensionsQuery = '@enabled';
async show(query: string): Promise<IPagedModel<IExtension>> {
return (query && query.trim() !== this.enabledExtensionsQuery) ? this.showEmptyModel() : super.show(this.enabledExtensionsQuery);
query = query || '@enabled';
return ExtensionsListView.isEnabledExtensionsQuery(query) ? super.show(query) : this.showEmptyModel();
}
}
export class DisabledExtensionsView extends ExtensionsListView {
private readonly disabledExtensionsQuery = '@disabled';
async show(query: string): Promise<IPagedModel<IExtension>> {
return (query && query.trim() !== this.disabledExtensionsQuery) ? this.showEmptyModel() : super.show(this.disabledExtensionsQuery);
query = query || '@disabled';
return ExtensionsListView.isDisabledExtensionsQuery(query) ? super.show(query) : this.showEmptyModel();
}
}
@@ -950,7 +948,7 @@ export class DefaultRecommendedExtensionsView extends ExtensionsListView {
renderBody(container: HTMLElement): void {
super.renderBody(container);
this.disposables.push(this.tipsService.onRecommendationChange(() => {
this._register(this.tipsService.onRecommendationChange(() => {
this.show('');
}));
}
@@ -975,7 +973,7 @@ export class RecommendedExtensionsView extends ExtensionsListView {
renderBody(container: HTMLElement): void {
super.renderBody(container);
this.disposables.push(this.tipsService.onRecommendationChange(() => {
this._register(this.tipsService.onRecommendationChange(() => {
this.show('');
}));
}
@@ -993,9 +991,9 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
renderBody(container: HTMLElement): void {
super.renderBody(container);
this.disposables.push(this.tipsService.onRecommendationChange(() => this.update()));
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.setRecommendationsToInstall()));
this.disposables.push(this.contextService.onDidChangeWorkbenchState(() => this.update()));
this._register(this.tipsService.onRecommendationChange(() => this.update()));
this._register(this.extensionsWorkbenchService.onChange(() => this.setRecommendationsToInstall()));
this._register(this.contextService.onDidChangeWorkbenchState(() => this.update()));
}
renderHeader(container: HTMLElement): void {
@@ -1004,21 +1002,19 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
const listActionBar = $('.list-actionbar-container');
container.insertBefore(listActionBar, this.badgeContainer);
const actionbar = new ActionBar(listActionBar, {
const actionbar = this._register(new ActionBar(listActionBar, {
animated: false
});
}));
actionbar.onDidRun(({ error }) => error && this.notificationService.error(error));
this.installAllAction = this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, InstallWorkspaceRecommendedExtensionsAction.LABEL, []);
const configureWorkspaceFolderAction = this.instantiationService.createInstance(ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction.ID, ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL);
this.installAllAction = this._register(this.instantiationService.createInstance(InstallWorkspaceRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction.ID, InstallWorkspaceRecommendedExtensionsAction.LABEL, []));
const configureWorkspaceFolderAction = this._register(this.instantiationService.createInstance(ConfigureWorkspaceFolderRecommendedExtensionsAction, ConfigureWorkspaceFolderRecommendedExtensionsAction.ID, ConfigureWorkspaceFolderRecommendedExtensionsAction.LABEL));
this.installAllAction.class = 'octicon octicon-cloud-download';
configureWorkspaceFolderAction.class = 'octicon octicon-pencil';
actionbar.push([this.installAllAction], { icon: true, label: false });
actionbar.push([configureWorkspaceFolderAction], { icon: true, label: false });
this.disposables.push(...[this.installAllAction, configureWorkspaceFolderAction, actionbar]);
}
async show(query: string): Promise<IPagedModel<IExtension>> {
@@ -1045,7 +1041,7 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
if (!extension || !extension.local || extension.state !== ExtensionState.Installed) {
return true;
}
return isUIExtension(extension.local.manifest, this.configurationService) ? extension.server !== this.extensionManagementServerService.localExtensionManagementServer : extension.server !== this.extensionManagementServerService.remoteExtensionManagementServer;
return isUIExtension(extension.local.manifest, this.productService, this.configurationService) ? extension.server !== this.extensionManagementServerService.localExtensionManagementServer : extension.server !== this.extensionManagementServerService.remoteExtensionManagementServer;
}));
}
}

View File

@@ -4,14 +4,14 @@
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/extensionsWidgets';
import { Disposable, IDisposable, dispose, toDisposable } from 'vs/base/common/lifecycle';
import { Disposable, toDisposable, DisposableStore, MutableDisposable } from 'vs/base/common/lifecycle';
import { IExtension, IExtensionsWorkbenchService, IExtensionContainer, ExtensionState } from '../common/extensions';
import { append, $, addClass } from 'vs/base/browser/dom';
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, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { extensionButtonProminentBackground, extensionButtonProminentForeground, DisabledLabelAction, ReloadAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IThemeService, ITheme } from 'vs/platform/theme/common/themeService';
import { EXTENSION_BADGE_REMOTE_BACKGROUND, EXTENSION_BADGE_REMOTE_FOREGROUND } from 'vs/workbench/common/theme';
import { REMOTE_HOST_SCHEME } from 'vs/platform/remote/common/remoteHosts';
@@ -196,7 +196,7 @@ export class TooltipWidget extends ExtensionWidget {
export class RecommendationWidget extends ExtensionWidget {
private element?: HTMLElement;
private disposables: IDisposable[] = [];
private readonly disposables = this._register(new DisposableStore());
private _tooltip: string;
get tooltip(): string { return this._tooltip; }
@@ -227,7 +227,7 @@ export class RecommendationWidget extends ExtensionWidget {
this.parent.removeChild(this.element);
}
this.element = undefined;
this.disposables = dispose(this.disposables);
this.disposables.clear();
}
render(): void {
@@ -256,8 +256,7 @@ export class RecommendationWidget extends ExtensionWidget {
export class RemoteBadgeWidget extends ExtensionWidget {
private remoteBadge: RemoteBadge | null;
private disposables: IDisposable[] = [];
private readonly remoteBadge = this._register(new MutableDisposable<RemoteBadge>());
private element: HTMLElement;
@@ -274,12 +273,10 @@ export class RemoteBadgeWidget extends ExtensionWidget {
}
private clear(): void {
if (this.remoteBadge) {
this.element.removeChild(this.remoteBadge.element);
this.remoteBadge.dispose();
if (this.remoteBadge.value) {
this.element.removeChild(this.remoteBadge.value.element);
}
this.remoteBadge = null;
this.disposables = dispose(this.disposables);
this.remoteBadge.clear();
}
render(): void {
@@ -288,17 +285,10 @@ export class RemoteBadgeWidget extends ExtensionWidget {
return;
}
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer) {
this.remoteBadge = this.instantiationService.createInstance(RemoteBadge, this.tooltip);
append(this.element, this.remoteBadge.element);
this.remoteBadge.value = this.instantiationService.createInstance(RemoteBadge, this.tooltip);
append(this.element, this.remoteBadge.value.element);
}
}
dispose(): void {
if (this.remoteBadge) {
this.remoteBadge.dispose();
}
super.dispose();
}
}
class RemoteBadge extends Disposable {

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#C5C5C5"/>
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#C5C5C5"/>
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#C5C5C5"/>
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#C5C5C5"/>
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#C5C5C5"/>
</svg>

After

Width:  |  Height:  |  Size: 484 B

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="white"/>
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="white"/>
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="white"/>
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="white"/>
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 474 B

View File

@@ -0,0 +1,7 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10 12.6L10.7 13.3L12.3 11.7L13.9 13.3L14.7 12.6L13 11L14.7 9.40005L13.9 8.60005L12.3 10.3L10.7 8.60005L10 9.40005L11.6 11L10 12.6Z" fill="#424242"/>
<path d="M1 4L15 4L15 3L1 3L1 4Z" fill="#424242"/>
<path d="M1 7L15 7L15 6L1 6L1 7Z" fill="#424242"/>
<path d="M9 9.5L9 9L1 9L1 10L9 10L9 9.5Z" fill="#424242"/>
<path d="M9 13L9 12.5L9 12L1 12L1 13L9 13Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 484 B

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -13,12 +13,15 @@
}
.monaco-action-bar .action-item .action-label.clear-extensions {
background: url('clear.svg') center center no-repeat;
background: url('clear-light.svg') center center no-repeat;
}
.vs-dark .monaco-action-bar .action-item .action-label.clear-extensions {
background: url('clear-dark.svg') center center no-repeat;
}
.vs-dark .monaco-action-bar .action-item .action-label.clear-extensions,
.hc-black .monaco-action-bar .action-item .action-label.clear-extensions {
background: url('clear-inverse.svg') center center no-repeat;
background: url('clear-hc.svg') center center no-repeat;
}
.monaco-action-bar .action-item .action-label.extension-action.multiserver.install:after,
@@ -81,22 +84,6 @@
width: 10px;
}
.monaco-action-bar .action-item .action-label.system-disable.warning.icon {
background: url('status-warning.svg') center center no-repeat;
}
.vs-dark .monaco-action-bar .action-item .action-label.system-disable.warning.icon {
background: url('status-warning-inverse.svg') center center no-repeat;
}
.monaco-action-bar .action-item .action-label.system-disable.info.icon {
background: url('status-info.svg') center center no-repeat;
}
.vs-dark .monaco-action-bar .action-item .action-label.system-disable.info.icon {
background: url('status-info-inverse.svg') center center no-repeat;
}
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.extension-status-label,
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.disable-status,
.extension-editor>.header>.details>.actions>.monaco-action-bar .action-item .action-label.malicious-status {
@@ -117,14 +104,17 @@
height: 18px;
width: 10px;
border: none;
background: url('manage.svg') center center no-repeat;
background: url('configure-light.svg') center center no-repeat;
outline-offset: 0px;
margin-top: 0.15em
}
.hc-black .extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage,
.vs-dark .extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage {
background: url('manage-inverse.svg') center center no-repeat;
background: url('configure-dark.svg') center center no-repeat;
}
.hc-black .extensions-viewlet>.extensions .extension>.details>.footer>.monaco-action-bar .action-item .action-label.extension-action.manage {
background: url('configure-hc.svg') center center no-repeat;
}
.extension-editor > .header.recommended > .details > .recommendation > .monaco-action-bar .actions-container {

View File

@@ -205,7 +205,7 @@
opacity: 0.7;
}
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item.disabled > .action-label {
.extension-editor > .body > .navbar > .monaco-action-bar > .actions-container > .action-item > .action-label.checked {
opacity: 1;
text-decoration: underline;
}

View File

@@ -0,0 +1,3 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.5 1.5L15 0H22.5L24 1.5V9L22.5 10.5H15L13.5 9V1.5ZM15 1.5V9H22.5V1.5H15ZM0 15V6L1.5 4.5H9L10.5 6V13.5H18L19.5 15V22.5L18 24H10.5H9H1.5L0 22.5V15ZM9 13.5V6H1.5V13.5H9ZM9 15H1.5V22.5H9V15ZM10.5 22.5H18V15H10.5V22.5Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
.monaco-workbench .activitybar > .content .monaco-action-bar .action-label.extensions {
-webkit-mask: url('extensions-dark.svg') no-repeat 50% 50%;
-webkit-mask: url('extensions-activity-bar.svg') no-repeat 50% 50%;
}
.extensions .split-view-view .panel-header .count-badge-wrapper {

View File

@@ -38,7 +38,7 @@
}
.extensions-viewlet > .extensions .extensions-list.hidden,
.extensions-viewlet > .extensions .message.hidden {
.extensions-viewlet > .extensions .message-container.hidden {
display: none;
visibility: hidden;
}
@@ -51,9 +51,14 @@
flex: 1;
}
.extensions-viewlet > .extensions .message {
.extensions-viewlet > .extensions .message-container {
padding: 5px 9px 5px 16px;
cursor: default;
display: flex;
}
.extensions-viewlet > .extensions .message-container .message {
padding-left: 5px;
}
.extensions-viewlet > .extensions .monaco-list-row > .bookmark {
@@ -214,7 +219,6 @@
.extensions-viewlet > .extensions .extension > .details > .footer > .author {
flex: 1;
font-size: 90%;
padding-right: 6px;
opacity: 0.9;
font-weight: 600;
}

View File

@@ -26,18 +26,19 @@
.extension-ratings.small > .star {
width: 10px;
height: 10px;
background-image: url('star-small.svg');
}
.extension-ratings > .full {
background-image: url('FullStarLight.svg');
background-image: url('star-full.svg');
}
.extension-ratings > .half {
background-image: url('HalfStarLight.svg');
background-image: url('star-half.svg');
}
.extension-ratings > .empty {
background-image: url('EmptyStar.svg');
background-image: url('star-empty.svg');
}
.extension-ratings > .count {

View File

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM11.9139 8C11.9139 10.1616 10.1616 11.9139 8 11.9139C5.83839 11.9139 4.08606 10.1616 4.08606 8C4.08606 5.83839 5.83839 4.08606 8 4.08606C10.1616 4.08606 11.9139 5.83839 11.9139 8ZM8 3.86919C10.2814 3.86919 12.1308 5.71862 12.1308 8C12.1308 8.00001 12.1308 8 12.1308 8C12.1308 5.71862 10.2814 3.86919 8 3.86919Z" fill="#848484"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 715 B

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM11.9139 8C11.9139 10.1616 10.1616 11.9139 8 11.9139C5.83839 11.9139 4.08606 10.1616 4.08606 8C4.08606 5.83839 5.83839 4.08606 8 4.08606C10.1616 4.08606 11.9139 5.83839 11.9139 8ZM8 3.86919C10.2814 3.86919 12.1308 5.71862 12.1308 8C12.1308 8.00001 12.1308 8 12.1308 8C12.1308 5.71862 10.2814 3.86919 8 3.86919Z" fill="#848484"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 715 B

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M8 2C8.55078 2 9.08203 2.07227 9.59375 2.2168C10.1055 2.35742 10.582 2.55859 11.0234 2.82031C11.4688 3.08203 11.873 3.39648 12.2363 3.76367C12.6035 4.12695 12.918 4.53125 13.1797 4.97656C13.4414 5.41797 13.6426 5.89453 13.7832 6.40625C13.9277 6.91797 14 7.44922 14 8C14 8.55078 13.9277 9.08203 13.7832 9.59375C13.6426 10.1055 13.4414 10.584 13.1797 11.0293C12.918 11.4707 12.6035 11.875 12.2363 12.2422C11.873 12.6055 11.4688 12.918 11.0234 13.1797C10.582 13.4414 10.1055 13.6445 9.59375 13.7891C9.08203 13.9297 8.55078 14 8 14C7.44922 14 6.91797 13.9297 6.40625 13.7891C5.89453 13.6445 5.41602 13.4414 4.9707 13.1797C4.5293 12.918 4.125 12.6055 3.75781 12.2422C3.39453 11.875 3.08203 11.4707 2.82031 11.0293C2.55859 10.584 2.35547 10.1055 2.21094 9.59375C2.07031 9.08203 2 8.55078 2 8C2 7.44922 2.07031 6.91797 2.21094 6.40625C2.35547 5.89453 2.55859 5.41797 2.82031 4.97656C3.08203 4.53125 3.39453 4.12695 3.75781 3.76367C4.125 3.39648 4.5293 3.08203 4.9707 2.82031C5.41602 2.55859 5.89453 2.35742 6.40625 2.2168C6.91797 2.07227 7.44922 2 8 2Z" fill="#F48771"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,10 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path d="M8 2C8.55078 2 9.08203 2.07227 9.59375 2.2168C10.1055 2.35742 10.582 2.55859 11.0234 2.82031C11.4688 3.08203 11.873 3.39648 12.2363 3.76367C12.6035 4.12695 12.918 4.53125 13.1797 4.97656C13.4414 5.41797 13.6426 5.89453 13.7832 6.40625C13.9277 6.91797 14 7.44922 14 8C14 8.55078 13.9277 9.08203 13.7832 9.59375C13.6426 10.1055 13.4414 10.584 13.1797 11.0293C12.918 11.4707 12.6035 11.875 12.2363 12.2422C11.873 12.6055 11.4688 12.918 11.0234 13.1797C10.582 13.4414 10.1055 13.6445 9.59375 13.7891C9.08203 13.9297 8.55078 14 8 14C7.44922 14 6.91797 13.9297 6.40625 13.7891C5.89453 13.6445 5.41602 13.4414 4.9707 13.1797C4.5293 12.918 4.125 12.6055 3.75781 12.2422C3.39453 11.875 3.08203 11.4707 2.82031 11.0293C2.55859 10.584 2.35547 10.1055 2.21094 9.59375C2.07031 9.08203 2 8.55078 2 8C2 7.44922 2.07031 6.91797 2.21094 6.40625C2.35547 5.89453 2.55859 5.41797 2.82031 4.97656C3.08203 4.53125 3.39453 4.12695 3.75781 3.76367C4.125 3.39648 4.5293 3.08203 4.9707 2.82031C5.41602 2.55859 5.89453 2.35742 6.40625 2.2168C6.91797 2.07227 7.44922 2 8 2Z" fill="#A1260D"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="16" height="16" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="#C5C5C5"/>
</svg>

After

Width:  |  Height:  |  Size: 406 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M15 3V11.5L14.5 12H12V14.5L11.5 15H1.5L1 14.5V4.5L1.5 4H3.985V1.5L4.485 1H13L13.353 1.147L14.853 2.647L15 3ZM12 6V11H14V3.206L12.793 2H4.985V4H10L10.353 4.146L11.853 5.646L12 6ZM11 14H2V5H3V8.07143H9V5H9.793L11 6.208V14ZM8 5H6V7.5H8V5Z" fill="#424242"/>
</svg>

After

Width:  |  Height:  |  Size: 406 B

View File

@@ -0,0 +1,5 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<g opacity="0.5">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.59454 6.25211L8 1L6.40546 6.25211H1L5.37311 9.65247L3.7496 15L8 11.695L12.2504 15L10.6269 9.65247L15 6.25211H9.59454ZM2.34804 6.72168H6.72044L8 2.50706L8.00002 2.50708L6.72046 6.7217H2.34805L2.34804 6.72168ZM5.88539 9.4722L4.57848 13.7769L4.57851 13.7769L5.8854 9.47221L5.88539 9.4722ZM13.6519 6.7217L13.652 6.72168H9.27956L9.27958 6.7217H13.6519ZM4.90113 7.6229H7.26847L8.00002 5.21332L8.73156 7.6229H11.0989L9.18369 9.1121L9.91523 11.5217L8.00002 10.0325L6.0848 11.5217L6.81635 9.1121L4.90113 7.6229Z" fill="#C5C5C5"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 699 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.59454 6.25211L8 1L6.40546 6.25211H1L5.37311 9.65247L3.7496 15L8 11.695L12.2504 15L10.6269 9.65247L15 6.25211H9.59454Z" fill="#FF8E00"/>
</svg>

After

Width:  |  Height:  |  Size: 291 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.40546 6.25211L8 1L9.59454 6.25211H15L10.6269 9.65247L12.2504 15L8 11.695L3.7496 15L5.37311 9.65247L1 6.25211H6.40546ZM8 10.0325L8.00002 10.0325L9.91523 11.5217L9.18369 9.1121L11.0989 7.6229H8.73156L8.00002 5.21332L8 5.21338V10.0325V10.0325ZM8 2.50714L8.00002 2.50708L8 2.50706V2.50714ZM13.6519 6.7217L13.652 6.72168H9.27956L9.27958 6.7217H13.6519Z" fill="#FF8E00"/>
</svg>

After

Width:  |  Height:  |  Size: 521 B

View File

@@ -0,0 +1,10 @@
<svg width="10" height="10" viewBox="0 0 10 10" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.99659 3.90757L5 0.625L4.00341 3.90757H0.625L3.35819 6.0328L2.3435 9.375L5 7.3094L7.6565 9.375L6.64181 6.0328L9.375 3.90757H5.99659Z" fill="#FF8E00"/>
</g>
<defs>
<clipPath id="clip0">
<rect width="10" height="10" fill="white"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 431 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.99977 14V2.18091L12.9998 8.06215L3.99977 14ZM5.5 4.99997L10.3145 8.06215L5.5 11.1809L5.5 4.99997Z" fill="#89D185"/>
</svg>

After

Width:  |  Height:  |  Size: 271 B

View File

@@ -0,0 +1,3 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3.99977 14V2.18091L12.9998 8.06215L3.99977 14ZM5.5 4.99997L10.3145 8.06215L5.5 11.1809L5.5 4.99997Z" fill="#388A34"/>
</svg>

After

Width:  |  Height:  |  Size: 271 B

View File

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -29,8 +29,8 @@ export class Query {
if (hasSort && command === 'sort' || hasCategory && command === 'category') {
return [];
}
if (subcommands[command]) {
return subcommands[command].map((subcommand: string) => `@${command}:${subcommand}${subcommand === '' ? '' : ' '}`);
if ((subcommands as any)[command]) {
return (subcommands as any)[command].map((subcommand: string) => `@${command}:${subcommand}${subcommand === '' ? '' : ' '}`);
}
else {
return [`@${command} `];

View File

@@ -144,7 +144,7 @@ export class ExtensionContainers extends Disposable {
for (const container of this.containers) {
if (extension && container.extension) {
if (areSameExtensions(container.extension.identifier, extension.identifier)) {
if (!container.extension.server || container.extension.server === extension.server) {
if (!container.extension.server || !extension.server || container.extension.server === extension.server) {
container.extension = extension;
} else if (container.updateWhenCounterExtensionChanges) {
container.update();

View File

@@ -7,7 +7,7 @@ import * as arrays from 'vs/base/common/arrays';
import { localize } from 'vs/nls';
import { Event } from 'vs/base/common/event';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IExtensionManagementService, ILocalExtension, IExtensionEnablementService, IExtensionTipsService, IExtensionIdentifier, EnablementState, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
@@ -22,9 +22,7 @@ export interface IExtensionStatus {
globallyEnabled: boolean;
}
export class KeymapExtensions implements IWorkbenchContribution {
private disposables: IDisposable[] = [];
export class KeymapExtensions extends Disposable implements IWorkbenchContribution {
constructor(
@IInstantiationService private readonly instantiationService: IInstantiationService,
@@ -34,13 +32,12 @@ export class KeymapExtensions implements IWorkbenchContribution {
@INotificationService private readonly notificationService: INotificationService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
) {
this.disposables.push(
lifecycleService.onShutdown(() => this.dispose()),
instantiationService.invokeFunction(onExtensionChanged)((identifiers => {
Promise.all(identifiers.map(identifier => this.checkForOtherKeymaps(identifier)))
.then(undefined, onUnexpectedError);
}))
);
super();
this._register(lifecycleService.onShutdown(() => this.dispose()));
this._register(instantiationService.invokeFunction(onExtensionChanged)((identifiers => {
Promise.all(identifiers.map(identifier => this.checkForOtherKeymaps(identifier)))
.then(undefined, onUnexpectedError);
})));
}
private checkForOtherKeymaps(extensionIdentifier: IExtensionIdentifier): Promise<void> {
@@ -87,10 +84,6 @@ export class KeymapExtensions implements IWorkbenchContribution {
}]
);
}
dispose(): void {
this.disposables = dispose(this.disposables);
}
}
export function onExtensionChanged(accessor: ServicesAccessor): Event<IExtensionIdentifier[]> {

View File

@@ -5,14 +5,11 @@
import * as nls from 'vs/nls';
import { Event, Emitter } from 'vs/base/common/event';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IInstantiationService, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { IExtensionHostProfile, ProfileSession, IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { Disposable, IDisposable, dispose } from 'vs/base/common/lifecycle';
import { Disposable, toDisposable, MutableDisposable } from 'vs/base/common/lifecycle';
import { onUnexpectedError } from 'vs/base/common/errors';
import { append, $, addDisposableListener } from 'vs/base/browser/dom';
import { IStatusbarRegistry, StatusbarItemDescriptor, Extensions, IStatusbarItem } from 'vs/workbench/browser/parts/statusbar/statusbar';
import { StatusbarAlignment } from 'vs/platform/statusbar/common/statusbar';
import { Registry } from 'vs/platform/registry/common/platform';
import { StatusbarAlignment, IStatusbarService, IStatusbarEntryAccessor, IStatusbarEntry } from 'vs/platform/statusbar/common/statusbar';
import { IExtensionHostProfileService, ProfileSessionState } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsEditor';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IWindowsService } from 'vs/platform/windows/common/windows';
@@ -22,10 +19,11 @@ 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';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
export class ExtensionHostProfileService extends Disposable implements IExtensionHostProfileService {
_serviceBrand: any;
_serviceBrand: ServiceIdentifier<IExtensionHostProfileService>;
private readonly _onDidChangeState: Emitter<void> = this._register(new Emitter<void>());
public readonly onDidChangeState: Event<void> = this._onDidChangeState.event;
@@ -38,6 +36,9 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
private _profileSession: ProfileSession | null;
private _state: ProfileSessionState;
private profilingStatusBarIndicator: IStatusbarEntryAccessor | undefined;
private readonly profilingStatusBarIndicatorLabelUpdater = this._register(new MutableDisposable());
public get state() { return this._state; }
public get lastProfile() { return this._profile; }
@@ -46,12 +47,18 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
@IEditorService private readonly _editorService: IEditorService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IWindowsService private readonly _windowsService: IWindowsService,
@IDialogService private readonly _dialogService: IDialogService
@IDialogService private readonly _dialogService: IDialogService,
@IStatusbarService private readonly _statusbarService: IStatusbarService,
) {
super();
this._profile = null;
this._profileSession = null;
this._setState(ProfileSessionState.None);
CommandsRegistry.registerCommand('workbench.action.extensionHostProfilder.stop', () => {
this.stopProfiling();
this._editorService.openEditor(this._instantiationService.createInstance(RuntimeExtensionsInput), { revealIfOpened: true });
});
}
private _setState(state: ProfileSessionState): void {
@@ -61,17 +68,45 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
this._state = state;
if (this._state === ProfileSessionState.Running) {
ProfileExtHostStatusbarItem.instance.show(() => {
this.stopProfiling();
this._editorService.openEditor(this._instantiationService.createInstance(RuntimeExtensionsInput), { revealIfOpened: true });
});
this.updateProfilingStatusBarIndicator(true);
} else if (this._state === ProfileSessionState.Stopping) {
ProfileExtHostStatusbarItem.instance.hide();
this.updateProfilingStatusBarIndicator(false);
}
this._onDidChangeState.fire(undefined);
}
private updateProfilingStatusBarIndicator(visible: boolean): void {
this.profilingStatusBarIndicatorLabelUpdater.clear();
if (visible) {
const indicator: IStatusbarEntry = {
text: nls.localize('profilingExtensionHost', "$(sync~spin) Profiling Extension Host"),
tooltip: nls.localize('selectAndStartDebug', "Click to stop profiling."),
command: 'workbench.action.extensionHostProfilder.stop'
};
const timeStarted = Date.now();
const handle = setInterval(() => {
if (this.profilingStatusBarIndicator) {
this.profilingStatusBarIndicator.update({ ...indicator, text: nls.localize('profilingExtensionHostTime', "$(sync~spin) Profiling Extension Host ({0} sec)", Math.round((new Date().getTime() - timeStarted) / 1000)), });
}
}, 1000);
this.profilingStatusBarIndicatorLabelUpdater.value = toDisposable(() => clearInterval(handle));
if (!this.profilingStatusBarIndicator) {
this.profilingStatusBarIndicator = this._statusbarService.addEntry(indicator, 'status.profiler', nls.localize('status.profiler', "Extension Profiler"), StatusbarAlignment.RIGHT);
} else {
this.profilingStatusBarIndicator.update(indicator);
}
} else {
if (this.profilingStatusBarIndicator) {
this.profilingStatusBarIndicator.dispose();
this.profilingStatusBarIndicator = undefined;
}
}
}
public startProfiling(): Promise<any> | null {
if (this._state !== ProfileSessionState.None) {
return null;
@@ -134,76 +169,3 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
}
}
export class ProfileExtHostStatusbarItem implements IStatusbarItem {
public static instance: ProfileExtHostStatusbarItem;
private toDispose: IDisposable[];
private statusBarItem: HTMLElement;
private label: HTMLElement;
private timeStarted: number;
private labelUpdater: any;
private clickHandler: (() => void) | null;
constructor() {
ProfileExtHostStatusbarItem.instance = this;
this.toDispose = [];
this.timeStarted = 0;
}
public show(clickHandler: () => void) {
this.clickHandler = clickHandler;
if (this.timeStarted === 0) {
this.timeStarted = new Date().getTime();
this.statusBarItem.hidden = false;
this.labelUpdater = setInterval(() => {
this.updateLabel();
}, 1000);
this.updateLabel();
}
}
public hide() {
this.clickHandler = null;
this.statusBarItem.hidden = true;
this.timeStarted = 0;
clearInterval(this.labelUpdater);
this.labelUpdater = null;
}
public render(container: HTMLElement): IDisposable {
if (!this.statusBarItem && container) {
this.statusBarItem = append(container, $('.profileExtHost-statusbar-item'));
this.toDispose.push(addDisposableListener(this.statusBarItem, 'click', () => {
if (this.clickHandler) {
this.clickHandler();
}
}));
this.statusBarItem.title = nls.localize('selectAndStartDebug', "Click to stop profiling.");
const a = append(this.statusBarItem, $('a'));
append(a, $('.icon'));
this.label = append(a, $('span.label'));
this.updateLabel();
this.statusBarItem.hidden = true;
}
return this;
}
private updateLabel() {
let label = 'Profiling Extension Host';
if (this.timeStarted > 0) {
let secondsRecoreded = (new Date().getTime() - this.timeStarted) / 1000;
label = `Profiling Extension Host (${Math.round(secondsRecoreded)} sec)`;
}
this.label.textContent = label;
}
public dispose(): void {
this.toDispose = dispose(this.toDispose);
}
}
Registry.as<IStatusbarRegistry>(Extensions.Statusbar).registerStatusbarItem(
new StatusbarItemDescriptor(ProfileExtHostStatusbarItem, StatusbarAlignment.RIGHT)
);

View File

@@ -6,19 +6,19 @@
import { localize } from 'vs/nls';
import { join } from 'vs/base/common/path';
import { forEach } from 'vs/base/common/collections';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { match } from 'vs/base/common/glob';
import * as json from 'vs/base/common/json';
import {
IExtensionManagementService, IExtensionGalleryService, IExtensionTipsService, ExtensionRecommendationReason, EXTENSION_IDENTIFIER_PATTERN,
IExtensionsConfigContent, RecommendationChangeNotification, IExtensionRecommendation, ExtensionRecommendationSource, InstallOperation
IExtensionsConfigContent, RecommendationChangeNotification, IExtensionRecommendation, ExtensionRecommendationSource, InstallOperation, ILocalExtension
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { IModelService } from 'vs/editor/common/services/modelService';
import { ITextModel } from 'vs/editor/common/model';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import product from 'vs/platform/product/node/product';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { ShowRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction, InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import { ShowRecommendedExtensionsAction, InstallWorkspaceRecommendedExtensionsAction, InstallRecommendedExtensionAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import Severity from 'vs/base/common/severity';
import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace, IWorkspaceFoldersChangeEvent, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IFileService } from 'vs/platform/files/common/files';
@@ -32,9 +32,8 @@ import { flatten, distinct, shuffle, coalesce } from 'vs/base/common/arrays';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { guessMimeTypes, MIME_UNKNOWN } from 'vs/base/common/mime';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { getHashedRemotesFromUri } from 'vs/workbench/contrib/stats/node/workspaceStats';
import { IRequestService } from 'vs/platform/request/node/request';
import { asJson } from 'vs/base/node/request';
import { getHashedRemotesFromUri } from 'vs/workbench/contrib/stats/electron-browser/workspaceStats';
import { IRequestService, asJson } from 'vs/platform/request/common/request';
import { isNumber } from 'vs/base/common/types';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { INotificationService } from 'vs/platform/notification/common/notification';
@@ -42,7 +41,7 @@ import { Emitter, Event } from 'vs/base/common/event';
import { assign } from 'vs/base/common/objects';
import { URI } from 'vs/base/common/uri';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IExperimentService, ExperimentActionType, ExperimentState } from 'vs/workbench/contrib/experiments/node/experimentService';
import { IExperimentService, ExperimentActionType, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { extname } from 'vs/base/common/resources';
@@ -86,11 +85,10 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
private _globallyIgnoredRecommendations: string[] = [];
private _workspaceIgnoredRecommendations: string[] = [];
private _extensionsRecommendationsUrl: string;
private _disposables: IDisposable[] = [];
public loadWorkspaceConfigPromise: Promise<void>;
private proactiveRecommendationsFetched: boolean = false;
private readonly _onRecommendationChange = new Emitter<RecommendationChangeNotification>();
private readonly _onRecommendationChange = this._register(new Emitter<RecommendationChangeNotification>());
onRecommendationChange: Event<RecommendationChangeNotification> = this._onRecommendationChange.event;
private sessionSeed: number;
@@ -138,13 +136,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
this.fetchProactiveRecommendations(true);
}
// {{SQL CARBON EDIT}} disable extension recommendation prompt
this.loadWorkspaceConfigPromise = this.getWorkspaceRecommendations().then();
// .then(() => {
// this.promptWorkspaceRecommendations();
// this._modelService.onModelAdded(this.promptFiletypeBasedRecommendations, this, this._disposables);
// this._modelService.getModels().forEach(model => this.promptFiletypeBasedRecommendations(model));
// });
this.loadWorkspaceConfigPromise = this.getWorkspaceRecommendations().then(); // {{SQL CARBON EDIT}} disable workspace recommandations
this._register(this.contextService.onDidChangeWorkspaceFolders(e => this.onWorkspaceFoldersChanged(e)));
this._register(this.configurationService.onDidChangeConfiguration(e => {
@@ -597,8 +589,6 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
* or prompt to search the marketplace if it has extensions that can support the file type
*/
private promptFiletypeBasedRecommendations(model: ITextModel): void {
let hasSuggestion = false;
const uri = model.uri;
if (!uri || !this.fileService.canHandleResource(uri)) {
return;
@@ -612,23 +602,22 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
processedFileExtensions.push(fileExtension);
}
// re-schedule this bit of the operation to be off
// the critical path - in case glob-match is slow
setImmediate(() => {
// re-schedule this bit of the operation to be off the critical path - in case glob-match is slow
setImmediate(async () => {
let recommendationsToSuggest: string[] = [];
const now = Date.now();
forEach(this._availableRecommendations, entry => {
let { key: pattern, value: ids } = entry;
if (match(pattern, uri.path)) {
if (match(pattern, model.uri.path)) {
for (let id of ids) {
if (caseInsensitiveGet(product.extensionImportantTips, id)) {
recommendationsToSuggest.push(id);
}
const filedBasedRecommendation = this._fileBasedRecommendations[id.toLowerCase()] || { recommendedTime: now, sources: [] };
filedBasedRecommendation.recommendedTime = now;
if (!filedBasedRecommendation.sources.some(s => s instanceof URI && s.toString() === uri.toString())) {
filedBasedRecommendation.sources.push(uri);
if (!filedBasedRecommendation.sources.some(s => s instanceof URI && s.toString() === model.uri.toString())) {
filedBasedRecommendation.sources.push(model.uri);
}
this._fileBasedRecommendations[id.toLowerCase()] = filedBasedRecommendation;
}
@@ -637,7 +626,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
this.storageService.store(
'extensionsAssistant/recommendations',
JSON.stringify(Object.keys(this._fileBasedRecommendations).reduce((result, key) => { result[key] = this._fileBasedRecommendations[key].recommendedTime; return result; }, {})),
JSON.stringify(Object.keys(this._fileBasedRecommendations).reduce((result, key) => { result[key] = this._fileBasedRecommendations[key].recommendedTime; return result; }, {} as { [key: string]: any })),
StorageScope.GLOBAL
);
@@ -646,197 +635,212 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
return;
}
const importantRecommendationsIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]'));
recommendationsToSuggest = recommendationsToSuggest.filter(id => importantRecommendationsIgnoreList.indexOf(id) === -1 && this.isExtensionAllowedToBeRecommended(id));
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
if (await this.promptRecommendedExtensionForFileType(recommendationsToSuggest, installed)) {
return;
}
const importantTipsPromise = recommendationsToSuggest.length === 0 ? Promise.resolve(null) : this.extensionWorkbenchService.queryLocal().then(local => {
const localExtensions = local.map(e => e.identifier);
recommendationsToSuggest = recommendationsToSuggest.filter(id => localExtensions.every(local => !areSameExtensions(local, { id })));
if (!recommendationsToSuggest.length) {
return;
}
const id = recommendationsToSuggest[0];
const entry = caseInsensitiveGet(product.extensionImportantTips, id);
if (!entry) {
return;
}
const name = entry['name'];
if (fileExtension) {
fileExtension = fileExtension.substr(1); // Strip the dot
}
if (!fileExtension) {
return;
}
// Indicates we have a suggested extension via the whitelist
hasSuggestion = true;
await this.extensionService.whenInstalledExtensionsRegistered();
const mimeTypes = guessMimeTypes(uri);
if (mimeTypes.length !== 1 || mimeTypes[0] !== MIME_UNKNOWN) {
return;
}
let message = localize('reallyRecommended2', "The '{0}' extension is recommended for this file type.", name);
// Temporary fix for the only extension pack we recommend. See https://github.com/Microsoft/vscode/issues/35364
if (id === 'vscjava.vscode-java-pack') {
message = localize('reallyRecommendedExtensionPack', "The '{0}' extension pack is recommended for this file type.", name);
}
this.promptRecommendedExtensionForFileExtension(fileExtension, installed);
});
}
const setIgnoreRecommendationsConfig = (configVal: boolean) => {
this.configurationService.updateValue('extensions.ignoreRecommendations', configVal, ConfigurationTarget.USER);
if (configVal) {
const ignoreWorkspaceRecommendationsStorageKey = 'extensionsAssistant/workspaceRecommendationsIgnore';
this.storageService.store(ignoreWorkspaceRecommendationsStorageKey, true, StorageScope.WORKSPACE);
private async promptRecommendedExtensionForFileType(recommendationsToSuggest: string[], installed: ILocalExtension[]): Promise<boolean> {
const importantRecommendationsIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]'));
const installedExtensionsIds = installed.reduce((result, i) => { result.add(i.identifier.id.toLowerCase()); return result; }, new Set<string>());
recommendationsToSuggest = recommendationsToSuggest.filter(id => {
if (importantRecommendationsIgnoreList.indexOf(id) !== -1) {
return false;
}
if (!this.isExtensionAllowedToBeRecommended(id)) {
return false;
}
if (installedExtensionsIds.has(id.toLowerCase())) {
return false;
}
return true;
});
if (recommendationsToSuggest.length === 0) {
return false;
}
const id = recommendationsToSuggest[0];
const entry = caseInsensitiveGet(product.extensionImportantTips, id);
if (!entry) {
return false;
}
const name = entry['name'];
let message = localize('reallyRecommended2', "The '{0}' extension is recommended for this file type.", name);
// Temporary fix for the only extension pack we recommend. See https://github.com/Microsoft/vscode/issues/35364
if (id === 'vscjava.vscode-java-pack') {
message = localize('reallyRecommendedExtensionPack', "The '{0}' extension pack is recommended for this file type.", name);
}
const setIgnoreRecommendationsConfig = (configVal: boolean) => {
this.configurationService.updateValue('extensions.ignoreRecommendations', configVal, ConfigurationTarget.USER);
if (configVal) {
const ignoreWorkspaceRecommendationsStorageKey = 'extensionsAssistant/workspaceRecommendationsIgnore';
this.storageService.store(ignoreWorkspaceRecommendationsStorageKey, true, StorageScope.WORKSPACE);
}
};
this.notificationService.prompt(Severity.Info, message,
[{
label: localize('install', 'Install'),
run: () => {
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
};
this.notificationService.prompt(Severity.Info, message,
[{
label: localize('install', 'Install'),
run: () => {
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'install', extensionId: name });
this.instantiationService.createInstance(InstallRecommendedExtensionAction, id).run();
}
}, {
label: localize('showRecommendations', "Show Recommendations"),
run: () => {
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'show', extensionId: name });
const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations"));
recommendationsAction.run();
recommendationsAction.dispose();
}
}, {
label: choiceNever,
isSecondary: true,
run: () => {
importantRecommendationsIgnoreList.push(id);
this.storageService.store(
'extensionsAssistant/importantRecommendationsIgnore',
JSON.stringify(importantRecommendationsIgnoreList),
StorageScope.GLOBAL
);
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'neverShowAgain', extensionId: name });
this.notificationService.prompt(
Severity.Info,
localize('ignoreExtensionRecommendations', "Do you want to ignore all extension recommendations?"),
[{
label: localize('ignoreAll', "Yes, Ignore All"),
run: () => setIgnoreRecommendationsConfig(true)
}, {
label: localize('no', "No"),
run: () => setIgnoreRecommendationsConfig(false)
}]
);
}
}],
{
sticky: true,
onCancel: () => {
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name });
}
}
);
});
const mimeTypesPromise = this.extensionService.whenInstalledExtensionsRegistered()
.then(() => {
return guessMimeTypes(uri.fsPath);
});
Promise.all([importantTipsPromise, mimeTypesPromise]).then(result => {
const fileExtensionSuggestionIgnoreList = <string[]>JSON.parse(this.storageService.get
('extensionsAssistant/fileExtensionsSuggestionIgnore', StorageScope.GLOBAL, '[]'));
const mimeTypes = result[1];
if (fileExtension) {
fileExtension = fileExtension.substr(1); // Strip the dot
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'install', extensionId: name });
this.instantiationService.createInstance(InstallRecommendedExtensionAction, id).run();
}
}, {
label: localize('showRecommendations', "Show Recommendations"),
run: () => {
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'show', extensionId: name });
if (hasSuggestion ||
!fileExtension ||
mimeTypes.length !== 1 ||
mimeTypes[0] !== MIME_UNKNOWN ||
fileExtensionSuggestionIgnoreList.indexOf(fileExtension) > -1
) {
return;
const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations"));
recommendationsAction.run();
recommendationsAction.dispose();
}
const lookup = product.extensionKeywords || {};
const keywords = lookup[fileExtension] || [];
this._galleryService.query({ text: `tag:"__ext_${fileExtension}" ${keywords.map(tag => `tag:"${tag}"`)}` }, CancellationToken.None).then(pager => {
if (!pager || !pager.firstPage || !pager.firstPage.length) {
return;
}
}, {
label: choiceNever,
isSecondary: true,
run: () => {
importantRecommendationsIgnoreList.push(id);
this.storageService.store(
'extensionsAssistant/importantRecommendationsIgnore',
JSON.stringify(importantRecommendationsIgnoreList),
StorageScope.GLOBAL
);
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'neverShowAgain', extensionId: name });
this.notificationService.prompt(
Severity.Info,
localize('showLanguageExtensions', "The Marketplace has extensions that can help with '.{0}' files", fileExtension),
localize('ignoreExtensionRecommendations', "Do you want to ignore all extension recommendations?"),
[{
label: searchMarketplace,
run: () => {
/* __GDPR__
"fileExtensionSuggestion:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'ok', fileExtension: fileExtension });
this.viewletService.openViewlet('workbench.view.extensions', true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
viewlet.search(`ext:${fileExtension}`);
viewlet.focus();
});
}
label: localize('ignoreAll', "Yes, Ignore All"),
run: () => setIgnoreRecommendationsConfig(true)
}, {
label: localize('dontShowAgainExtension', "Don't Show Again for '.{0}' files", fileExtension),
run: () => {
fileExtensionSuggestionIgnoreList.push(fileExtension);
this.storageService.store(
'extensionsAssistant/fileExtensionsSuggestionIgnore',
JSON.stringify(fileExtensionSuggestionIgnoreList),
StorageScope.GLOBAL
);
/* __GDPR__
"fileExtensionSuggestion:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'neverShowAgain', fileExtension: fileExtension });
}
}],
{
sticky: true,
onCancel: () => {
/* __GDPR__
"fileExtensionSuggestion:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension });
}
}
label: localize('no', "No"),
run: () => setIgnoreRecommendationsConfig(false)
}]
);
});
});
});
}
}],
{
sticky: true,
onCancel: () => {
/* __GDPR__
"extensionRecommendations:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"extensionId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId: name });
}
}
);
return true;
}
private async promptRecommendedExtensionForFileExtension(fileExtension: string, installed: ILocalExtension[]): Promise<void> {
const fileExtensionSuggestionIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/fileExtensionsSuggestionIgnore', StorageScope.GLOBAL, '[]'));
if (fileExtensionSuggestionIgnoreList.indexOf(fileExtension) > -1) {
return;
}
const text = `ext:${fileExtension}`;
const pager = await this.extensionWorkbenchService.queryGallery({ text, pageSize: 100 }, CancellationToken.None);
if (pager.firstPage.length === 0) {
return;
}
const installedExtensionsIds = installed.reduce((result, i) => { result.add(i.identifier.id.toLowerCase()); return result; }, new Set<string>());
if (pager.firstPage.some(e => installedExtensionsIds.has(e.identifier.id.toLowerCase()))) {
return;
}
this.notificationService.prompt(
Severity.Info,
localize('showLanguageExtensions', "The Marketplace has extensions that can help with '.{0}' files", fileExtension),
[{
label: searchMarketplace,
run: () => {
/* __GDPR__
"fileExtensionSuggestion:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'ok', fileExtension: fileExtension });
this.viewletService.openViewlet('workbench.view.extensions', true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
viewlet.search(`ext:${fileExtension}`);
viewlet.focus();
});
}
}, {
label: localize('dontShowAgainExtension', "Don't Show Again for '.{0}' files", fileExtension),
run: () => {
fileExtensionSuggestionIgnoreList.push(fileExtension);
this.storageService.store(
'extensionsAssistant/fileExtensionsSuggestionIgnore',
JSON.stringify(fileExtensionSuggestionIgnoreList),
StorageScope.GLOBAL
);
/* __GDPR__
"fileExtensionSuggestion:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'neverShowAgain', fileExtension: fileExtension });
}
}],
{
sticky: true,
onCancel: () => {
/* __GDPR__
"fileExtensionSuggestion:popup" : {
"userReaction" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"fileExtension": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" }
}
*/
this.telemetryService.publicLog('fileExtensionSuggestion:popup', { userReaction: 'cancelled', fileExtension: fileExtension });
}
}
);
}
//#endregion
@@ -935,7 +939,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
const storageKey = 'extensionsAssistant/dynamicWorkspaceRecommendations';
let storedRecommendationsJson = {};
let storedRecommendationsJson: { [key: string]: any } = {};
try {
storedRecommendationsJson = JSON.parse(this.storageService.get(storageKey, StorageScope.WORKSPACE, '{}'));
} catch (e) {
@@ -980,7 +984,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
if (context.res.statusCode !== 200) {
return Promise.resolve(undefined);
}
return asJson(context).then((result) => {
return asJson(context).then((result: { [key: string]: any }) => {
if (!result) {
return;
}
@@ -1001,8 +1005,8 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}), StorageScope.WORKSPACE);
/* __GDPR__
"dynamicWorkspaceRecommendations" : {
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"cache" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" }
"count" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true },
"cache" : { "classification": "SystemMetaData", "purpose": "FeatureInsight", "isMeasurement": true }
}
*/
this.telemetryService.publicLog('dynamicWorkspaceRecommendations', { count: this._dynamicWorkspaceRecommendations.length, cache: 0 });
@@ -1037,8 +1041,4 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
private isExtensionAllowedToBeRecommended(id: string): boolean {
return this._allIgnoredRecommendations.indexOf(id.toLowerCase()) === -1;
}
dispose() {
this._disposables = dispose(this._disposables);
}
}

View File

@@ -3,7 +3,7 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./media/extensions';
import 'vs/css!../browser/media/extensions';
import { localize } from 'vs/nls';
import { KeyMod, KeyChord, KeyCode } from 'vs/base/common/keyCodes';
import { Registry } from 'vs/platform/registry/common/platform';
@@ -23,11 +23,11 @@ import {
OpenExtensionsViewletAction, InstallExtensionsAction, ShowOutdatedExtensionsAction, ShowRecommendedExtensionsAction, ShowRecommendedKeymapExtensionsAction, ShowPopularExtensionsAction,
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowDisabledExtensionsAction, ShowBuiltInExtensionsAction, UpdateAllAction,
EnableAllAction, EnableAllWorkpsaceAction, DisableAllAction, DisableAllWorkpsaceAction, CheckForUpdatesAction, ShowLanguageExtensionsAction, ShowAzureExtensionsAction, EnableAutoUpdateAction, DisableAutoUpdateAction, ConfigureRecommendedExtensionsCommandsContributor, OpenExtensionsFolderAction, InstallVSIXAction, ReinstallAction, InstallSpecificVersionOfExtensionAction
} from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ViewletRegistry, Extensions as ViewletExtensions, ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { ExtensionEditor } from 'vs/workbench/contrib/extensions/electron-browser/extensionEditor';
import { StatusUpdater, ExtensionsViewlet, MaliciousExtensionChecker, ExtensionsViewletViewsContribution } from 'vs/workbench/contrib/extensions/electron-browser/extensionsViewlet';
import { ExtensionEditor } from 'vs/workbench/contrib/extensions/browser/extensionEditor';
import { StatusUpdater, ExtensionsViewlet, MaliciousExtensionChecker, ExtensionsViewletViewsContribution } from 'vs/workbench/contrib/extensions/browser/extensionsViewlet';
import { IQuickOpenRegistry, Extensions, QuickOpenHandlerDescriptor } from 'vs/workbench/browser/quickopen';
import { IConfigurationRegistry, Extensions as ConfigurationExtensions, ConfigurationScope } from 'vs/platform/configuration/common/configurationRegistry';
import * as jsonContributionRegistry from 'vs/platform/jsonschemas/common/jsonContributionRegistry';
@@ -45,11 +45,12 @@ import { ExtensionHostProfileService } from 'vs/workbench/contrib/extensions/ele
import { RuntimeExtensionsInput } from 'vs/workbench/contrib/extensions/electron-browser/runtimeExtensionsInput';
import { URI, UriComponents } from 'vs/base/common/uri';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { ExtensionActivationProgress } from 'vs/workbench/contrib/extensions/electron-browser/extensionsActivationProgress';
import { ExtensionActivationProgress } from 'vs/workbench/contrib/extensions/browser/extensionsActivationProgress';
import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron-browser/extensionsAutoProfiler';
import { onUnexpectedError } from 'vs/base/common/errors';
import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/electron-browser/extensionsDependencyChecker';
import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/browser/extensionsDependencyChecker';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
// Singletons
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
@@ -194,13 +195,13 @@ const disableAllWorkspaceAction = new SyncActionDescriptor(DisableAllWorkpsaceAc
actionRegistry.registerWorkbenchAction(disableAllWorkspaceAction, 'Extensions: Disable All Installed Extensions for this Workspace', ExtensionsLabel);
const enableAllAction = new SyncActionDescriptor(EnableAllAction, EnableAllAction.ID, EnableAllAction.LABEL);
actionRegistry.registerWorkbenchAction(enableAllAction, 'Extensions: Enable All Installed Extensions', ExtensionsLabel);
actionRegistry.registerWorkbenchAction(enableAllAction, 'Extensions: Enable All Extensions', ExtensionsLabel);
const enableAllWorkspaceAction = new SyncActionDescriptor(EnableAllWorkpsaceAction, EnableAllWorkpsaceAction.ID, EnableAllWorkpsaceAction.LABEL);
actionRegistry.registerWorkbenchAction(enableAllWorkspaceAction, 'Extensions: Enable All Installed Extensions for this Workspace', ExtensionsLabel);
actionRegistry.registerWorkbenchAction(enableAllWorkspaceAction, 'Extensions: Enable All Extensions for this Workspace', ExtensionsLabel);
const checkForUpdatesAction = new SyncActionDescriptor(CheckForUpdatesAction, CheckForUpdatesAction.ID, CheckForUpdatesAction.LABEL);
actionRegistry.registerWorkbenchAction(checkForUpdatesAction, `Extensions: Check for Updates`, ExtensionsLabel);
actionRegistry.registerWorkbenchAction(checkForUpdatesAction, `Extensions: Check for Extension Updates`, ExtensionsLabel);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(EnableAutoUpdateAction, EnableAutoUpdateAction.ID, EnableAutoUpdateAction.LABEL), `Extensions: Enable Auto Updating Extensions`, ExtensionsLabel);
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(DisableAutoUpdateAction, DisableAutoUpdateAction.ID, DisableAutoUpdateAction.LABEL), `Extensions: Disable Auto Updating Extensions`, ExtensionsLabel);
@@ -312,13 +313,22 @@ CommandsRegistry.registerCommand(SaveExtensionHostProfileAction.ID, (accessor: S
// });
// {{SQL CARBON EDIT}} - End
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '2_keybindings',
command: {
id: ShowRecommendedKeymapExtensionsAction.ID,
title: localize('miOpenKeymapExtensions2', "Keymaps")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarPreferencesMenu, {
group: '1_settings',
command: {
id: VIEWLET_ID,
title: localize({ key: 'miPreferencesExtensions', comment: ['&& denotes a mnemonic'] }, "&&Extensions")
},
order: 2
order: 3
});
// View menu
@@ -340,8 +350,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
id: DebugExtensionHostAction.ID,
title: DebugExtensionHostAction.LABEL,
iconLocation: {
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/start-inverse.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/start.svg`)),
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/start-dark.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/start-light.svg`)),
}
},
group: 'navigation',
@@ -353,8 +363,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
id: StartExtensionHostProfileAction.ID,
title: StartExtensionHostProfileAction.LABEL,
iconLocation: {
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/profile-start-inverse.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/profile-start.svg`)),
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/profile-start-dark.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/profile-start-light.svg`)),
}
},
group: 'navigation',
@@ -366,8 +376,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
id: StopExtensionHostProfileAction.ID,
title: StopExtensionHostProfileAction.LABEL,
iconLocation: {
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/profile-stop-inverse.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/profile-stop.svg`)),
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/profile-stop-dark.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/profile-stop-light.svg`)),
}
},
group: 'navigation',
@@ -379,8 +389,8 @@ MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
id: SaveExtensionHostProfileAction.ID,
title: SaveExtensionHostProfileAction.LABEL,
iconLocation: {
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/save-inverse.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/electron-browser/media/save.svg`)),
dark: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/save-dark.svg`)),
light: URI.parse(require.toUrl(`vs/workbench/contrib/extensions/browser/media/save-light.svg`)),
},
precondition: CONTEXT_EXTENSION_HOST_PROFILE_RECORDED
},
@@ -421,3 +431,43 @@ CommandsRegistry.registerCommand({
}
}
});
CommandsRegistry.registerCommand({
id: 'workbench.extensions.uninstallExtension',
description: {
description: localize('workbench.extensions.uninstallExtension.description', "Uninstall the given extension"),
args: [
{
name: localize('workbench.extensions.uninstallExtension.arg.name', "Id of the extension to uninstall"),
schema: {
'type': 'string'
}
}
]
},
handler: async (accessor, id: string) => {
if (!id) {
throw new Error(localize('id required', "Extension id required."));
}
const extensionManagementService = accessor.get(IExtensionManagementService);
try {
const installed = await extensionManagementService.getInstalled(ExtensionType.User);
const [extensionToUninstall] = installed.filter(e => areSameExtensions(e.identifier, { id }));
if (!extensionToUninstall) {
return Promise.reject(new Error(localize('notInstalled', "Extension '{0}' is not installed. Make sure you use the full extension ID, including the publisher, e.g.: ms-vscode.csharp.", id)));
}
await extensionManagementService.uninstall(extensionToUninstall, true);
} catch (e) {
onUnexpectedError(e);
}
}
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '2_configuration',
command: {
id: VIEWLET_ID,
title: localize('showExtensions', "Extensions")
},
order: 3
});

View File

@@ -11,9 +11,8 @@ import { URI } from 'vs/base/common/uri';
import { IExtensionHostProfile } from 'vs/workbench/services/extensions/common/extensions';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { localize } from 'vs/nls';
import { IRequestService } from 'vs/platform/request/node/request';
import { CancellationToken } from 'vs/base/common/cancellation';
import { asText } from 'vs/base/node/request';
import { IRequestService, asText } from 'vs/platform/request/common/request';
import { join } from 'vs/base/common/path';
import { onUnexpectedError } from 'vs/base/common/errors';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 10.3 10" style="enable-background:new 0 0 10.3 10;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;opacity:0.2;fill:#ED1C24;}
.st2{display:inline;opacity:0.43;fill:#39B54A;}
.st3{fill:#353535;}
.st4{fill:#FFFFFF;}
.st5{display:inline;opacity:0.8;fill:#353535;}
.st6{display:inline;}
.st7{display:inline;opacity:0.8;fill:#321F5A;}
.st8{opacity:0.15;fill:#353535;}
.st9{display:inline;opacity:0.34;}
.st10{fill:#070909;}
.st11{fill:#333333;}
.st12{fill:#7551A0;}
.st13{fill:#D2D2D2;}
.st14{fill:#E6E7E8;}
.st15{fill:#3076BC;}
.st16{display:none;fill:#3076BC;}
.st17{display:inline;fill:#321F5A;}
.st18{fill:#D63F26;}
.st19{display:none;fill:none;stroke:#BCBEC0;stroke-miterlimit:10;}
.st20{opacity:0.52;}
.st21{fill:none;stroke:#BE1E2D;stroke-miterlimit:10;}
.st22{fill:#BE1E2D;}
.st23{display:none;opacity:0.2;}
.st24{display:inline;opacity:0.2;}
.st25{fill:#656565;}
.st26{fill:#D1D3D4;}
.st27{fill:#EEEEEE;}
.st28{display:none;fill-rule:evenodd;clip-rule:evenodd;fill:#F4F4F4;}
.st29{fill:#505150;}
.st30{display:none;fill:#BFD8E8;}
.st31{fill:#224096;}
.st32{fill:#17244E;}
.st33{display:inline;fill:#353535;}
.st34{display:none;fill:#F1F2F2;}
.st35{fill:#009444;}
.st36{fill:none;stroke:#505150;stroke-miterlimit:10;}
.st37{fill:#B9D532;}
.st38{fill:none;stroke:#D9D9D8;stroke-width:0.72;stroke-linejoin:round;stroke-miterlimit:10;}
.st39{fill:none;stroke:#D2D2D2;stroke-miterlimit:10;}
.st40{display:inline;fill:#333333;}
.st41{display:inline;fill:#7551A0;}
.st42{display:inline;fill:#D2D2D2;}
.st43{fill-rule:evenodd;clip-rule:evenodd;fill:#EEEEEE;}
.st44{fill:#321F5A;}
.st45{fill:none;stroke:#BCBEC0;stroke-miterlimit:10;}
.st46{opacity:0.53;fill:#FFFFFF;}
.st47{fill:none;stroke:#ED1C24;stroke-miterlimit:10;}
.st48{fill:#ED1C24;}
.st49{display:inline;opacity:0.1;fill:#E71E27;}
.st50{display:inline;opacity:0.3;}
.st51{fill:#E71E27;}
.st52{display:inline;opacity:0.2;fill:#E71E27;}
.st53{display:inline;fill:none;stroke:#ED1C24;stroke-miterlimit:10;}
.st54{fill:none;stroke:#2E3192;stroke-miterlimit:10;}
.st55{fill:#2E3192;}
.st56{fill:none;stroke:#FFF200;stroke-miterlimit:10;}
.st57{fill:#FFF200;}
</style>
<g id="grids">
</g>
<g id="Layer_2" class="st0">
</g>
<g id="home">
</g>
<g id="VSOdetails">
<g id="overview2">
</g>
</g>
<g id="reviews">
</g>
<g id="QA_2">
</g>
<g id="CARDS-RL">
<g>
<g>
<path class="st13" d="M8,9.7c-0.1,0-0.2,0-0.2-0.1L5.1,7.8L2.5,9.6c-0.1,0.1-0.3,0.1-0.5,0C1.9,9.5,1.9,9.4,1.9,9.2l1-3.1
L0.3,4.2C0.2,4.1,0.1,4,0.2,3.8c0.1-0.2,0.2-0.3,0.4-0.3h3.2l1-3.1C4.8,0.3,5,0.2,5.1,0.2c0.2,0,0.3,0.1,0.4,0.3l1,3.1h3.2
c0.2,0,0.3,0.1,0.4,0.3c0.1,0.2,0,0.3-0.1,0.5L7.4,6.1l1,3.1c0.1,0.2,0,0.3-0.1,0.5C8.2,9.7,8.1,9.7,8,9.7z"/>
</g>
</g>
</g>
<g id="sticky">
</g>
<g id="REDLINES" class="st0">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,92 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 10.3 10" style="enable-background:new 0 0 10.3 10;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;opacity:0.2;fill:#ED1C24;}
.st2{display:inline;opacity:0.43;fill:#39B54A;}
.st3{fill:#353535;}
.st4{fill:#FFFFFF;}
.st5{display:inline;opacity:0.8;fill:#353535;}
.st6{display:inline;}
.st7{display:inline;opacity:0.8;fill:#321F5A;}
.st8{opacity:0.15;fill:#353535;}
.st9{display:inline;opacity:0.34;}
.st10{fill:#070909;}
.st11{fill:#333333;}
.st12{fill:#7551A0;}
.st13{fill:#D2D2D2;}
.st14{fill:#E6E7E8;}
.st15{fill:#3076BC;}
.st16{display:none;fill:#3076BC;}
.st17{display:inline;fill:#321F5A;}
.st18{fill:#FF8E00;}
.st19{display:none;fill:none;stroke:#BCBEC0;stroke-miterlimit:10;}
.st20{opacity:0.52;}
.st21{fill:none;stroke:#BE1E2D;stroke-miterlimit:10;}
.st22{fill:#BE1E2D;}
.st23{display:none;opacity:0.2;}
.st24{display:inline;opacity:0.2;}
.st25{fill:#656565;}
.st26{fill:#D1D3D4;}
.st27{fill:#EEEEEE;}
.st28{display:none;fill-rule:evenodd;clip-rule:evenodd;fill:#F4F4F4;}
.st29{fill:#505150;}
.st30{display:none;fill:#BFD8E8;}
.st31{fill:#224096;}
.st32{fill:#17244E;}
.st33{display:inline;fill:#353535;}
.st34{display:none;fill:#F1F2F2;}
.st35{fill:#009444;}
.st36{fill:none;stroke:#505150;stroke-miterlimit:10;}
.st37{fill:#B9D532;}
.st38{fill:none;stroke:#D9D9D8;stroke-width:0.72;stroke-linejoin:round;stroke-miterlimit:10;}
.st39{fill:none;stroke:#D2D2D2;stroke-miterlimit:10;}
.st40{display:inline;fill:#333333;}
.st41{display:inline;fill:#7551A0;}
.st42{display:inline;fill:#D2D2D2;}
.st43{fill-rule:evenodd;clip-rule:evenodd;fill:#EEEEEE;}
.st44{fill:#321F5A;}
.st45{fill:none;stroke:#BCBEC0;stroke-miterlimit:10;}
.st46{opacity:0.53;fill:#FFFFFF;}
.st47{fill:none;stroke:#ED1C24;stroke-miterlimit:10;}
.st48{fill:#ED1C24;}
.st49{display:inline;opacity:0.1;fill:#E71E27;}
.st50{display:inline;opacity:0.3;}
.st51{fill:#E71E27;}
.st52{display:inline;opacity:0.2;fill:#E71E27;}
.st53{display:inline;fill:none;stroke:#ED1C24;stroke-miterlimit:10;}
.st54{fill:none;stroke:#2E3192;stroke-miterlimit:10;}
.st55{fill:#2E3192;}
.st56{fill:none;stroke:#FFF200;stroke-miterlimit:10;}
.st57{fill:#FFF200;}
</style>
<g id="grids">
</g>
<g id="Layer_2" class="st0">
</g>
<g id="home">
</g>
<g id="VSOdetails">
<g id="overview2">
</g>
</g>
<g id="reviews">
</g>
<g id="QA_2">
</g>
<g id="CARDS-RL">
<g>
<g>
<path class="st18" d="M8,9.8c-0.1,0-0.2,0-0.2-0.1L5.2,7.8L2.6,9.7c-0.1,0.1-0.3,0.1-0.5,0C1.9,9.6,1.9,9.4,1.9,9.2l1-3.1
L0.3,4.3C0.2,4.2,0.1,4,0.2,3.8c0.1-0.2,0.2-0.3,0.4-0.3h3.2l1-3.1C4.8,0.3,5,0.2,5.2,0.2c0.2,0,0.3,0.1,0.4,0.3l1,3.1h3.2
c0.2,0,0.3,0.1,0.4,0.3c0.1,0.2,0,0.3-0.1,0.5L7.4,6.2l1,3.1c0.1,0.2,0,0.3-0.1,0.5C8.2,9.7,8.1,9.8,8,9.8z"/>
</g>
</g>
</g>
<g id="sticky">
</g>
<g id="REDLINES" class="st0">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@@ -1,91 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 10.3 10" style="enable-background:new 0 0 10.3 10;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;opacity:0.2;fill:#ED1C24;}
.st2{display:inline;opacity:0.43;fill:#39B54A;}
.st3{fill:#353535;}
.st4{fill:#FFFFFF;}
.st5{display:inline;opacity:0.8;fill:#353535;}
.st6{display:inline;}
.st7{display:inline;opacity:0.8;fill:#321F5A;}
.st8{opacity:0.15;fill:#353535;}
.st9{display:inline;opacity:0.34;}
.st10{fill:#070909;}
.st11{fill:#333333;}
.st12{fill:#7551A0;}
.st13{fill:#D2D2D2;}
.st14{fill:#E6E7E8;}
.st15{fill:#3076BC;}
.st16{display:none;fill:#3076BC;}
.st17{display:inline;fill:#321F5A;}
.st18{fill:#FF8E00;}
.st19{display:none;fill:none;stroke:#BCBEC0;stroke-miterlimit:10;}
.st20{opacity:0.52;}
.st21{fill:none;stroke:#BE1E2D;stroke-miterlimit:10;}
.st22{fill:#BE1E2D;}
.st23{display:none;opacity:0.2;}
.st24{display:inline;opacity:0.2;}
.st25{fill:#656565;}
.st26{fill:#D1D3D4;}
.st27{fill:#EEEEEE;}
.st28{display:none;fill-rule:evenodd;clip-rule:evenodd;fill:#F4F4F4;}
.st29{fill:#505150;}
.st30{display:none;fill:#BFD8E8;}
.st31{fill:#224096;}
.st32{fill:#17244E;}
.st33{display:inline;fill:#353535;}
.st34{display:none;fill:#F1F2F2;}
.st35{fill:#009444;}
.st36{fill:none;stroke:#505150;stroke-miterlimit:10;}
.st37{fill:#B9D532;}
.st38{fill:none;stroke:#D9D9D8;stroke-width:0.72;stroke-linejoin:round;stroke-miterlimit:10;}
.st39{fill:none;stroke:#D2D2D2;stroke-miterlimit:10;}
.st40{display:inline;fill:#333333;}
.st41{display:inline;fill:#7551A0;}
.st42{display:inline;fill:#D2D2D2;}
.st43{fill-rule:evenodd;clip-rule:evenodd;fill:#EEEEEE;}
.st44{fill:#321F5A;}
.st45{fill:none;stroke:#BCBEC0;stroke-miterlimit:10;}
.st46{opacity:0.53;fill:#FFFFFF;}
.st47{fill:none;stroke:#ED1C24;stroke-miterlimit:10;}
.st48{fill:#ED1C24;}
.st49{display:inline;opacity:0.1;fill:#E71E27;}
.st50{display:inline;opacity:0.3;}
.st51{fill:#E71E27;}
.st52{display:inline;opacity:0.2;fill:#E71E27;}
.st53{display:inline;fill:none;stroke:#ED1C24;stroke-miterlimit:10;}
.st54{fill:none;stroke:#2E3192;stroke-miterlimit:10;}
.st55{fill:#2E3192;}
.st56{fill:none;stroke:#FFF200;stroke-miterlimit:10;}
.st57{fill:#FFF200;}
</style>
<g id="grids">
</g>
<g id="Layer_2" class="st0">
</g>
<g id="home">
</g>
<g id="VSOdetails">
<g id="overview2">
</g>
</g>
<g id="reviews">
</g>
<g id="QA_2">
</g>
<g id="CARDS-RL">
<g>
<path class="st13" d="M10.1,3.8c-0.1-0.2-0.2-0.3-0.4-0.3H6.5l-1-3.1C5.5,0.3,5.3,0.2,5.2,0.2v7.6l2.6,1.9C7.8,9.7,7.9,9.7,8,9.7
s0.2,0,0.2-0.1c0.1-0.1,0.2-0.3,0.1-0.5l-1-3.1L10,4.2C10.1,4.1,10.2,4,10.1,3.8z"/>
<path class="st18" d="M5.2,0.2L5.2,0.2C5,0.2,4.8,0.3,4.8,0.5l-1,3.1H0.6c-0.2,0-0.3,0.1-0.4,0.3C0.1,4,0.2,4.1,0.3,4.2l2.6,1.9
l-1,3.1c-0.1,0.2,0,0.3,0.1,0.5c0.1,0.1,0.3,0.1,0.5,0l2.6-1.9l0,0V0.2z"/>
</g>
</g>
<g id="sticky">
</g>
<g id="REDLINES" class="st0">
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.1 KiB

View File

@@ -1 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.065 13H15v2H2.056v-2h5.009zm3.661-12H7.385L8.44 2.061 7.505 3H15V1h-4.274zM3.237 9H2.056v2H15V9H3.237zm4.208-4l.995 1-.995 1H15V5H7.445z" fill="#424242"/><path d="M5.072 4.03L7.032 6 5.978 7.061l-1.96-1.97-1.961 1.97L1 6l1.96-1.97L1 2.061 2.056 1l1.96 1.97L5.977 1l1.057 1.061L5.072 4.03z" fill="#A1260D"/></svg>

Before

Width:  |  Height:  |  Size: 419 B

View File

@@ -1 +0,0 @@
<svg fill="none" height="28" viewBox="0 0 28 28" width="28" xmlns="http://www.w3.org/2000/svg"><g fill="#fff"><path clip-rule="evenodd" d="m3 3h10v4h-6v6 2 6h6v4h-10zm18 12v6h-6v4h10v-10zm4-2v-10h-10v4h3v-1h4v4h-1v3z" fill-rule="evenodd"/><path d="m9 9h10v10h-10z"/></g></svg>

Before

Width:  |  Height:  |  Size: 276 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#C5C5C5"><path d="M12.714 9.603c-.07.207-.15.407-.246.601l1.017 2.139c-.335.424-.718.807-1.142 1.143l-2.14-1.018c-.193.097-.394.176-.601.247l-.795 2.235c-.265.03-.534.05-.807.05-.272 0-.541-.02-.806-.05l-.795-2.235c-.207-.071-.408-.15-.602-.247l-2.14 1.017c-.424-.336-.807-.719-1.143-1.143l1.017-2.139c-.094-.193-.175-.393-.245-.6l-2.236-.796c-.03-.265-.05-.534-.05-.807s.02-.542.05-.807l2.236-.795c.07-.207.15-.407.246-.601l-1.016-2.139c.336-.423.719-.807 1.143-1.142l2.14 1.017c.193-.096.394-.176.602-.247l.793-2.236c.265-.03.534-.05.806-.05.273 0 .542.02.808.05l.795 2.236c.207.07.407.15.601.246l2.14-1.017c.424.335.807.719 1.142 1.142l-1.017 2.139c.096.194.176.394.246.601l2.236.795c.029.266.049.535.049.808s-.02.542-.05.807l-2.236.796zm-4.714-4.603c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><circle cx="8" cy="8" r="1.5"/></g></svg>

Before

Width:  |  Height:  |  Size: 927 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g fill="#424242"><path d="M12.714 9.603c-.07.207-.15.407-.246.601l1.017 2.139c-.335.424-.718.807-1.142 1.143l-2.14-1.018c-.193.097-.394.176-.601.247l-.795 2.235c-.265.03-.534.05-.807.05-.272 0-.541-.02-.806-.05l-.795-2.235c-.207-.071-.408-.15-.602-.247l-2.14 1.017c-.424-.336-.807-.719-1.143-1.143l1.017-2.139c-.094-.193-.175-.393-.245-.6l-2.236-.796c-.03-.265-.05-.534-.05-.807s.02-.542.05-.807l2.236-.795c.07-.207.15-.407.246-.601l-1.016-2.139c.336-.423.719-.807 1.143-1.142l2.14 1.017c.193-.096.394-.176.602-.247l.793-2.236c.265-.03.534-.05.806-.05.273 0 .542.02.808.05l.795 2.236c.207.07.407.15.601.246l2.14-1.017c.424.335.807.719 1.142 1.142l-1.017 2.139c.096.194.176.394.246.601l2.236.795c.029.266.049.535.049.808s-.02.542-.05.807l-2.236.796zm-4.714-4.603c-1.657 0-3 1.343-3 3s1.343 3 3 3 3-1.343 3-3-1.343-3-3-3z"/><circle cx="8" cy="8" r="1.5"/></g></svg>

Before

Width:  |  Height:  |  Size: 927 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#C5C5C5" cx="8" cy="8" r="6"/></svg>

Before

Width:  |  Height:  |  Size: 167 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#424242" cx="8" cy="8" r="6"/></svg>

Before

Width:  |  Height:  |  Size: 167 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#c10" cx="8" cy="8" r="6"/></svg>

Before

Width:  |  Height:  |  Size: 164 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle fill="#E51400" cx="8" cy="8" r="6"/></svg>

Before

Width:  |  Height:  |  Size: 167 B

View File

@@ -36,20 +36,3 @@
.runtime-extensions-editor .monaco-action-bar .actions-container {
justify-content: left;
}
.monaco-workbench .part.statusbar .profileExtHost-statusbar-item .icon {
background: url('profile-stop.svg') no-repeat;
display: inline-block;
padding-right: 2px;
padding-bottom: 2px;
width: 16px;
height: 16px;
vertical-align: middle;
animation:fade 1000ms infinite;
}
@keyframes fade {
from { opacity: 1.0; }
50% { opacity: 0.5; }
to { opacity: 1.0; }
}

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M16 2.6L13.4 0H6v6H0v10h10v-6h6z"/><g fill="#C5C5C5"><path d="M5 7h1v2H5zM11 1h1v2h-1zM13 1v3H9V1H7v5h.4L10 8.6V9h5V3zM7 10H3V7H1v8h8V9L7 7z"/></g></svg>

Before

Width:  |  Height:  |  Size: 294 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M16 2.6L13.4 0H6v6H0v10h10v-6h6z"/><g fill="#424242"><path d="M5 7h1v2H5zM11 1h1v2h-1zM13 1v3H9V1H7v5h.4L10 8.6V9h5V3zM7 10H3V7H1v8h8V9L7 7z"/></g></svg>

Before

Width:  |  Height:  |  Size: 294 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#252526;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-green{fill:#89d185;}</style></defs><title>continue</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.334,8,3.667,16H3V0h.667Z"/></g><g id="iconBg"><path class="icon-vs-action-green" d="M4,1.5v13L12.667,8,4,1.5Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 505 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><defs><style>.icon-canvas-transparent,.icon-vs-out{fill:#f6f6f6;}.icon-canvas-transparent{opacity:0;}.icon-vs-action-green{fill:#388a34;}</style></defs><title>continue</title><g id="canvas"><path class="icon-canvas-transparent" d="M16,0V16H0V0Z"/></g><g id="outline" style="display: none;"><path class="icon-vs-out" d="M14.334,8,3.667,16H3V0h.667Z"/></g><g id="iconBg"><path class="icon-vs-action-green" d="M4,1.5v13L12.667,8,4,1.5Z"/></g></svg>

Before

Width:  |  Height:  |  Size: 505 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8.5" cy="7.5" r="5.5" fill="#1E1E1E"/><path d="M8.5 3C6.015 3 4 5.015 4 7.5S6.015 12 8.5 12 13 9.985 13 7.5 10.985 3 8.5 3zm.5 8H8V6h1v5zm0-6H8V4h1v1z" fill="#1BA1E2"/><path d="M8 6h1v5H8V6zm0-2v1h1V4H8z" fill="#252526"/></svg>

Before

Width:  |  Height:  |  Size: 356 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><circle cx="8.5" cy="7.5" r="5.5" fill="#F6F6F6"/><path d="M8.5 3C6.015 3 4 5.015 4 7.5S6.015 12 8.5 12 13 9.985 13 7.5 10.985 3 8.5 3zm.5 8H8V6h1v5zm0-6H8V4h1v1z" fill="#1BA1E2"/><path d="M8 6h1v5H8V6zm0-2v1h1V4H8z" fill="#fff"/></svg>

Before

Width:  |  Height:  |  Size: 353 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" height="16" width="16"><path fill="#1E1E1E" d="M7.5 2L2 12l2 2h9l2-2L9.5 2z"/><path d="M9 3H8l-4.5 9 1 1h8l1-1L9 3zm0 9H8v-1h1v1zm0-2H8V6h1v4z" fill="#fc0"/><path d="M9 10H8V6h1v4zm0 1H8v1h1v-1z"/></svg>

Before

Width:  |  Height:  |  Size: 263 B

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16" enable-background="new 0 0 16 16" height="16" width="16"><path fill="#F6F6F6" d="M7.5 2L2 12l2 2h9l2-2L9.5 2z"/><path d="M9 3H8l-4.5 9 1 1h8l1-1L9 3zm0 9H8v-1h1v1zm0-2H8V6h1v4z" fill="#fc0"/><path d="M9 10H8V6h1v4zm0 1H8v1h1v-1z"/></svg>

Before

Width:  |  Height:  |  Size: 297 B

View File

@@ -9,7 +9,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { index, distinct } from 'vs/base/common/arrays';
import { ThrottledDelayer } from 'vs/base/common/async';
import { isPromiseCanceledError } from 'vs/base/common/errors';
import { IDisposable, dispose, Disposable } from 'vs/base/common/lifecycle';
import { Disposable } from 'vs/base/common/lifecycle';
import { IPager, mapPager, singlePagePager } from 'vs/base/common/paging';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
// {{SQL CARBON EDIT}}
@@ -17,30 +17,30 @@ import {
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions,
InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, INSTALL_ERROR_INCOMPATIBLE
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, getMaliciousExtensionsSet, groupByExtension } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { getGalleryExtensionTelemetryData, getLocalExtensionTelemetryData, areSameExtensions, getMaliciousExtensionsSet, groupByExtension, ExtensionIdentifierWithVersion } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWindowService } from 'vs/platform/windows/common/windows';
import Severity from 'vs/base/common/severity';
import { URI } from 'vs/base/common/uri';
import { IExtension, ExtensionState, IExtensionsWorkbenchService, AutoUpdateConfigurationKey, AutoCheckUpdatesConfigurationKey, ExtensionsPolicyKey, ExtensionsPolicy } from 'vs/workbench/contrib/extensions/common/extensions';
import { IEditorService, SIDE_GROUP, ACTIVE_GROUP } from 'vs/workbench/services/editor/common/editorService';
import { IURLService, IURLHandler } from 'vs/platform/url/common/url';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import product from 'vs/platform/product/node/product';
import { ILogService } from 'vs/platform/log/common/log';
import { IProgressService2, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { INotificationService } from 'vs/platform/notification/common/notification';
import * as resources from 'vs/base/common/resources';
import { CancellationToken } from 'vs/base/common/cancellation';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IFileService } from 'vs/platform/files/common/files';
import { IExtensionManifest, ExtensionType, ExtensionIdentifierWithVersion, IExtension as IPlatformExtension, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
import { IExtensionManifest, ExtensionType, IExtension as IPlatformExtension, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
import { IModeService } from 'vs/editor/common/services/modeService';
import { IProductService } from 'vs/platform/product/common/product';
// {{SQL CARBON EDIT}}
import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator';
import { ExtensionManagementError } from 'vs/platform/extensionManagement/node/extensionManagementService';
import pkg from 'vs/platform/product/node/package';
import { isEngineValid } from 'vs/platform/extensions/common/extensionValidator';
interface IExtensionStateProvider<T> {
(extension: Extension): T;
@@ -51,14 +51,15 @@ class Extension implements IExtension {
public enablementState: EnablementState = EnablementState.Enabled;
constructor(
private galleryService: IExtensionGalleryService,
private stateProvider: IExtensionStateProvider<ExtensionState>,
public readonly server: IExtensionManagementServer | undefined,
public local: ILocalExtension | undefined,
public gallery: IGalleryExtension | undefined,
private telemetryService: ITelemetryService,
private logService: ILogService,
private fileService: IFileService
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@ILogService private readonly logService: ILogService,
@IFileService private readonly fileService: IFileService,
@IProductService private readonly productService: IProductService
) { }
get type(): ExtensionType | undefined {
@@ -117,17 +118,16 @@ class Extension implements IExtension {
}
get url(): string | undefined {
if (!product.extensionsGallery || !this.gallery) {
if (!this.productService.extensionsGallery || !this.gallery) {
return undefined;
}
// {{SQL CARBON EDIT}}
return product.extensionsGallery.itemUrl && `${product.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`;
return this.productService.extensionsGallery.itemUrl && `${this.productService.extensionsGallery.itemUrl}?itemName=${this.publisher}.${this.name}`; // {{SQL CARBON EDIT}} add check for itemurl
}
// {{SQL CARBON EDIT}}
get downloadPage(): string {
if (!product.extensionsGallery) {
if (!this.productService.extensionsGallery) {
return null;
}
@@ -162,14 +162,14 @@ class Extension implements IExtension {
if (this.type === ExtensionType.System && this.local) {
if (this.local.manifest && this.local.manifest.contributes) {
if (Array.isArray(this.local.manifest.contributes.themes) && this.local.manifest.contributes.themes.length) {
return require.toUrl('../electron-browser/media/theme-icon.png');
return require.toUrl('../browser/media/theme-icon.png');
}
if (Array.isArray(this.local.manifest.contributes.grammars) && this.local.manifest.contributes.grammars.length) {
return require.toUrl('../electron-browser/media/language-icon.svg');
return require.toUrl('../browser/media/language-icon.svg');
}
}
}
return require.toUrl('../electron-browser/media/defaultIcon.png');
return require.toUrl('../browser/media/defaultIcon.png');
}
get repository(): string | undefined {
@@ -327,21 +327,18 @@ class Extensions extends Disposable {
private readonly _onChange: Emitter<Extension | undefined> = new Emitter<Extension | undefined>();
get onChange(): Event<Extension | undefined> { return this._onChange.event; }
private readonly stateProvider: IExtensionStateProvider<ExtensionState>;
private installing: Extension[] = [];
private uninstalling: Extension[] = [];
private installed: Extension[] = [];
constructor(
private readonly server: IExtensionManagementServer,
private readonly stateProvider: IExtensionStateProvider<ExtensionState>,
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
@ITelemetryService private readonly telemetryService: ITelemetryService,
@ILogService private readonly logService: ILogService,
@IFileService private readonly fileService: IFileService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
super();
this.stateProvider = ext => this.getExtensionState(ext);
this._register(server.extensionManagementService.onInstallExtension(e => this.onInstallExtension(e)));
this._register(server.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e)));
this._register(server.extensionManagementService.onUninstallExtension(e => this.onUninstallExtension(e)));
@@ -359,9 +356,9 @@ class Extensions extends Disposable {
async queryInstalled(): Promise<IExtension[]> {
const installed = await this.server.extensionManagementService.getInstalled();
const byId = index(this.installed, e => e.identifier.id);
const byId = index(this.installed, e => e.local ? e.local.identifier.id : e.identifier.id);
this.installed = installed.map(local => {
const extension = byId[local.identifier.id] || new Extension(this.galleryService, this.stateProvider, this.server, local, undefined, this.telemetryService, this.logService, this.fileService);
const extension = byId[local.identifier.id] || this.instantiationService.createInstance(Extension, this.stateProvider, this.server, local, undefined);
extension.local = local;
extension.enablementState = this.extensionEnablementService.getEnablementState(local);
return extension;
@@ -414,7 +411,7 @@ class Extensions extends Disposable {
const { gallery } = event;
if (gallery) {
const extension = this.installed.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0]
|| new Extension(this.galleryService, this.stateProvider, this.server, undefined, gallery, this.telemetryService, this.logService, this.fileService);
|| this.instantiationService.createInstance(Extension, this.stateProvider, this.server, undefined, gallery);
this.installing.push(extension);
this._onChange.fire(extension);
}
@@ -425,7 +422,7 @@ class Extensions extends Disposable {
const installingExtension = gallery ? this.installing.filter(e => areSameExtensions(e.identifier, gallery.identifier))[0] : null;
this.installing = installingExtension ? this.installing.filter(e => e !== installingExtension) : this.installing;
let extension: Extension | undefined = installingExtension ? installingExtension : zipPath ? new Extension(this.galleryService, this.stateProvider, this.server, local, undefined, this.telemetryService, this.logService, this.fileService) : undefined;
let extension: Extension | undefined = installingExtension ? installingExtension : zipPath ? this.instantiationService.createInstance(Extension, this.stateProvider, this.server, local, undefined) : undefined;
if (extension) {
if (local) {
const installed = this.installed.filter(e => areSameExtensions(e.identifier, extension!.identifier))[0];
@@ -497,12 +494,12 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
private readonly remoteExtensions: Extensions | null;
private syncDelayer: ThrottledDelayer<void>;
private autoUpdateDelayer: ThrottledDelayer<void>;
private disposables: IDisposable[] = [];
private readonly _onChange: Emitter<IExtension | undefined> = new Emitter<IExtension | undefined>();
get onChange(): Event<IExtension | undefined> { return this._onChange.event; }
private _extensionAllowedBadgeProviders: string[];
private installing: IExtension[] = [];
constructor(
@IInstantiationService private readonly instantiationService: IInstantiationService,
@@ -515,17 +512,17 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
@IURLService urlService: IURLService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@IWindowService private readonly windowService: IWindowService,
@ILogService private readonly logService: ILogService,
@IProgressService2 private readonly progressService: IProgressService2,
@IProgressService private readonly progressService: IProgressService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IStorageService private readonly storageService: IStorageService,
@IFileService private readonly fileService: IFileService
@IModeService private readonly modeService: IModeService,
@IProductService private readonly productService: IProductService
) {
super();
this.localExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.localExtensionManagementServer));
this.localExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.localExtensionManagementServer, ext => this.getExtensionState(ext)));
this._register(this.localExtensions.onChange(e => this._onChange.fire(e)));
if (this.extensionManagementServerService.remoteExtensionManagementServer) {
this.remoteExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.remoteExtensionManagementServer));
this.remoteExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.remoteExtensionManagementServer, ext => this.getExtensionState(ext)));
this._register(this.remoteExtensions.onChange(e => this._onChange.fire(e)));
} else {
this.remoteExtensions = null;
@@ -536,7 +533,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
urlService.registerHandler(this);
this.configurationService.onDidChangeConfiguration(e => {
this._register(this.configurationService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration(AutoUpdateConfigurationKey)) {
// {{SQL CARBON EDIT}}
// if (this.isAutoUpdateEnabled()) {
@@ -548,7 +545,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
this.checkForUpdates();
}
}
}, this, this.disposables);
}, this));
this.queryLocal().then(() => {
this.resetIgnoreAutoUpdateExtensions();
@@ -602,6 +599,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
queryGallery(arg1: any, arg2?: any): Promise<IPager<IExtension>> {
const options: IQueryOptions = CancellationToken.isCancellationToken(arg1) ? {} : arg1;
const token: CancellationToken = CancellationToken.isCancellationToken(arg1) ? arg1 : arg2;
options.text = options.text ? this.resolveQueryText(options.text) : options.text;
return this.extensionService.getExtensionsReport()
.then(report => {
const maliciousSet = getMaliciousExtensionsSet(report);
@@ -618,6 +616,27 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
});
}
private resolveQueryText(text: string): string {
const extensionRegex = /\bext:([^\s]+)\b/g;
if (extensionRegex.test(text)) {
text = text.replace(extensionRegex, (m, ext) => {
// Get curated keywords
const lookup = this.productService.extensionKeywords || {};
const keywords = lookup[ext] || [];
// Get mode name
const modeId = this.modeService.getModeIdByFilepathOrFirstLine(URI.file(`.${ext}`));
const languageName = modeId && this.modeService.getLanguageName(modeId);
const languageTag = languageName ? ` tag:"${languageName}"` : '';
// Construct a rich query
return `tag:"__ext_${ext}" tag:"__ext_.${ext}" ${keywords.map(tag => `tag:"${tag}"`).join(' ')}${languageTag} tag:"${ext}"`;
});
}
return text.substr(0, 350);
}
open(extension: IExtension, sideByside: boolean = false): Promise<any> {
return Promise.resolve(this.editorService.openEditor(this.instantiationService.createInstance(ExtensionsInput, extension), undefined, sideByside ? SIDE_GROUP : ACTIVE_GROUP));
}
@@ -646,7 +665,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
if (installed) {
return installed;
}
const extension = new Extension(this.galleryService, ext => this.getExtensionState(ext), undefined, undefined, gallery, this.telemetryService, this.logService, this.fileService);
const extension = this.instantiationService.createInstance(Extension, ext => this.getExtensionState(ext), undefined, undefined, gallery);
if (maliciousExtensionSet.has(extension.identifier.id)) {
extension.isMalicious = true;
}
@@ -669,6 +688,13 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}
private getExtensionState(extension: Extension): ExtensionState {
const isInstalling = this.installing.some(i => areSameExtensions(i.identifier, extension.identifier));
if (extension.server) {
const state = (extension.server === this.extensionManagementServerService.localExtensionManagementServer ? this.localExtensions : this.remoteExtensions!).getExtensionState(extension);
return state === ExtensionState.Uninstalled && isInstalling ? ExtensionState.Installing : state;
} else if (isInstalling) {
return ExtensionState.Installing;
}
if (this.remoteExtensions) {
const state = this.remoteExtensions.getExtensionState(extension);
if (state !== ExtensionState.Uninstalled) {
@@ -759,9 +785,9 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
// This is the error handler when installing local VSIX file.
// Prompt the user about the error detail.
try {
const extensionIdentifier = await this.extensionService.install(URI.file(extension));
this.checkAndEnableDisabledDependencies(extensionIdentifier);
return this.local.filter(local => areSameExtensions(local.identifier, extensionIdentifier))[0];
const { identifier } = await this.extensionService.install(URI.file(extension));
this.checkAndEnableDisabledDependencies(identifier);
return this.local.filter(local => areSameExtensions(local.identifier, identifier))[0];
} catch (error) {
this.notificationService.error(error);
return Promise.reject(error);
@@ -784,7 +810,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
// This is the execution path for install/update extension from marketplace.
// Check both the vscode version and azure data studio version
// The check is added here because we want to fail fast instead of downloading the VSIX and then fail.
if (gallery.properties.engine && (!isEngineValid(gallery.properties.engine, product.vscodeVersion)
if (gallery.properties.engine && (!isEngineValid(gallery.properties.engine, this.productService.vscodeVersion)
|| (gallery.properties.azDataEngine && !isEngineValid(gallery.properties.azDataEngine, pkg.version)))) {
return Promise.reject(new ExtensionManagementError(nls.localize('incompatible2', "Unable to install version '{2}' of extension '{0}' as it is not compatible with Azure Data Studio '{1}'.", extension.gallery!.identifier.id, pkg.version, gallery.version), INSTALL_ERROR_INCOMPATIBLE));
}
@@ -826,8 +852,6 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
if (!toUninstall) {
return Promise.reject(new Error('Missing local'));
}
this.logService.info(`Requested uninstalling the extension ${extension.identifier.id} from window ${this.windowService.windowId}`);
return this.progressService.withProgress({
location: ProgressLocation.Extensions,
title: nls.localize('uninstallingExtension', 'Uninstalling extension....'),
@@ -847,12 +871,10 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
return this.galleryService.getCompatibleExtension(extension.gallery.identifier, version)
.then(gallery => {
if (!gallery) {
// {{SQL CARBON EDIT}} - use Azure Data Studio in the text instead of VS Code
return Promise.reject(new Error(nls.localize('incompatible', "Unable to install extension '{0}' with version '{1}' as it is not compatible with Azure Data Studio.", extension.gallery!.identifier.id, version)));
return Promise.reject(new Error(nls.localize('incompatible', "Unable to install extension '{0}' as it is not compatible with Azure Data Studio '{1}'.", extension.gallery!.identifier.id, version))); // {{SQL CARBON EDIT}} Change vscode to ads
}
return this.installWithProgress(async () => {
const extensionService = extension.server && extension.local && !isLanguagePackExtension(extension.local.manifest) ? extension.server.extensionManagementService : this.extensionService;
await extensionService.installFromGallery(gallery);
await this.installFromGallery(extension, gallery);
if (extension.latestVersion !== version) {
this.ignoreAutoUpdate(new ExtensionIdentifierWithVersion(gallery.identifier, version));
}
@@ -884,6 +906,21 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}, () => installTask());
}
private async installFromGallery(extension: IExtension, gallery: IGalleryExtension): Promise<void> {
this.installing.push(extension);
this._onChange.fire(extension);
try {
const extensionService = extension.server && extension.local && !isLanguagePackExtension(extension.local.manifest) ? extension.server.extensionManagementService : this.extensionService;
await extensionService.installFromGallery(gallery);
const ids: string[] | undefined = extension.identifier.uuid ? [extension.identifier.uuid] : undefined;
const names: string[] | undefined = extension.identifier.uuid ? undefined : [extension.identifier.id];
this.queryGallery({ names, ids, pageSize: 1 }, CancellationToken.None);
} finally {
this.installing = this.installing.filter(e => e !== extension);
this._onChange.fire(this.local.filter(e => areSameExtensions(e.identifier, extension.identifier))[0]);
}
}
private checkAndEnableDisabledDependencies(extensionIdentifier: IExtensionIdentifier): Promise<void> {
const extension = this.local.filter(e => (e.local || e.gallery) && areSameExtensions(extensionIdentifier, e.identifier))[0];
if (extension) {
@@ -1018,7 +1055,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
get allowedBadgeProviders(): string[] {
if (!this._extensionAllowedBadgeProviders) {
this._extensionAllowedBadgeProviders = (product.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase());
this._extensionAllowedBadgeProviders = (this.productService.extensionAllowedBadgeProviders || []).map(s => s.toLowerCase());
}
return this._extensionAllowedBadgeProviders;
}
@@ -1062,7 +1099,6 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
return this.windowService.focusWindow()
.then(() => this.open(extension));
}
return this.queryGallery({ names: [extensionId], source: 'uri' }, CancellationToken.None).then(result => {
if (result.total < 1) {
return Promise.resolve(null);
@@ -1071,17 +1107,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
const extension = result.firstPage[0];
return this.windowService.focusWindow().then(() => {
return this.open(extension).then(() => {
this.notificationService.prompt(
Severity.Info,
nls.localize('installConfirmation', "Would you like to install the '{0}' extension?", extension.displayName, extension.publisher),
[{
label: nls.localize('install', "Install"),
run: () => this.install(extension).then(undefined, error => this.onError(error))
}],
{ sticky: true }
);
});
return this.open(extension);
});
});
}).then(undefined, error => this.onError(error));
@@ -1116,7 +1142,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
}
dispose(): void {
super.dispose();
this.syncDelayer.cancel();
this.disposables = dispose(this.disposables);
}
}

View File

@@ -7,7 +7,7 @@ import * as assert from 'assert';
import { assign } from 'vs/base/common/objects';
import { generateUuid } from 'vs/base/common/uuid';
import { IExtensionsWorkbenchService, ExtensionContainers } from 'vs/workbench/contrib/extensions/common/extensions';
import * as ExtensionsActions from 'vs/workbench/contrib/extensions/electron-browser/extensionsActions';
import * as ExtensionsActions from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/node/extensionsWorkbenchService';
import {
IExtensionManagementService, IExtensionGalleryService, IExtensionEnablementService, IExtensionTipsService, ILocalExtension, IGalleryExtension,
@@ -17,7 +17,7 @@ import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/ex
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/electron-browser/extensionTipsService';
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IURLService } from 'vs/platform/url/common/url';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { Emitter } from 'vs/base/common/event';
@@ -40,6 +40,7 @@ import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedPr
import { CancellationToken } from 'vs/base/common/cancellation';
import { ILabelService } from 'vs/platform/label/common/label';
import { ExtensionManagementServerService } from 'vs/workbench/services/extensions/electron-browser/extensionManagementServerService';
import { IProductService } from 'vs/platform/product/common/product';
suite('ExtensionsActions Test', () => {
@@ -78,7 +79,7 @@ suite('ExtensionsActions Test', () => {
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));
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(IExtensionGalleryService), instantiationService.get(IConfigurationService), instantiationService.get(IProductService), instantiationService.get(ILogService));
}
get localExtensionManagementServer(): IExtensionManagementServer { return this._localExtensionManagementServer; }
set localExtensionManagementServer(server: IExtensionManagementServer) { }

View File

@@ -15,7 +15,7 @@ import {
IExtensionEnablementService, DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier
} from 'vs/platform/extensionManagement/common/extensionManagement';
import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/electron-browser/extensionTipsService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { Emitter } from 'vs/base/common/event';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -41,15 +41,15 @@ import { IModelService } from 'vs/editor/common/services/modelService';
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { INotificationService, Severity, IPromptChoice, IPromptOptions } from 'vs/platform/notification/common/notification';
import { URLService } from 'vs/platform/url/common/urlService';
import { IExperimentService } from 'vs/workbench/contrib/experiments/node/experimentService';
import { IExperimentService } from 'vs/workbench/contrib/experiments/common/experimentService';
import { TestExperimentService } from 'vs/workbench/contrib/experiments/test/electron-browser/experimentService.test';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedProcessService';
import { FileService } from 'vs/workbench/services/files/common/fileService';
import { FileService } from 'vs/platform/files/common/fileService';
import { NullLogService } from 'vs/platform/log/common/log';
import { Schemas } from 'vs/base/common/network';
import { DiskFileSystemProvider } from 'vs/workbench/services/files/node/diskFileSystemProvider';
import { DiskFileSystemProvider } from 'vs/platform/files/node/diskFileSystemProvider';
import { IFileService } from 'vs/platform/files/common/files';
const mockExtensionGallery: IGalleryExtension[] = [
@@ -73,7 +73,7 @@ const mockExtensionGallery: IGalleryExtension[] = [
icon: { uri: 'uri:icon', fallbackUri: 'fallback:icon' },
license: { uri: 'uri:license', fallbackUri: 'fallback:license' },
repository: { uri: 'uri:repository', fallbackUri: 'fallback:repository' },
coreTranslations: {}
coreTranslations: []
}),
aGalleryExtension('MockExtension2', {
displayName: 'Mock Extension 2',
@@ -95,7 +95,7 @@ const mockExtensionGallery: IGalleryExtension[] = [
icon: { uri: 'uri:icon', fallbackUri: 'fallback:icon' },
license: { uri: 'uri:license', fallbackUri: 'fallback:license' },
repository: { uri: 'uri:repository', fallbackUri: 'fallback:repository' },
coreTranslations: {}
coreTranslations: []
})
];
@@ -154,7 +154,7 @@ const noAssets: IGalleryExtensionAssets = {
manifest: null,
readme: null,
repository: null,
coreTranslations: null!
coreTranslations: []
};
function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: IGalleryExtensionAssets = noAssets): IGalleryExtension {

View File

@@ -6,7 +6,7 @@
import * as assert from 'assert';
import { assign } from 'vs/base/common/objects';
import { generateUuid } from 'vs/base/common/uuid';
import { ExtensionsListView } from 'vs/workbench/contrib/extensions/electron-browser/extensionsViews';
import { ExtensionsListView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/node/extensionsWorkbenchService';
@@ -18,7 +18,7 @@ import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/ex
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/electron-browser/extensionTipsService';
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IURLService } from 'vs/platform/url/common/url';
import { Emitter } from 'vs/base/common/event';
import { IPager } from 'vs/base/common/paging';
@@ -34,12 +34,14 @@ import { URLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
import { TestConfigurationService } from 'vs/platform/configuration/test/common/testConfigurationService';
import { SinonStub } from 'sinon';
import { IExperimentService, ExperimentService, ExperimentState, ExperimentActionType } from 'vs/workbench/contrib/experiments/node/experimentService';
import { IExperimentService, ExperimentState, ExperimentActionType } from 'vs/workbench/contrib/experiments/common/experimentService';
import { ExperimentService } from 'vs/workbench/contrib/experiments/electron-browser/experimentService';
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService';
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';
import { IProductService } from 'vs/platform/product/common/product';
suite('ExtensionsListView Tests', () => {
@@ -93,7 +95,7 @@ suite('ExtensionsListView Tests', () => {
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));
super(instantiationService.get(ISharedProcessService), instantiationService.get(IRemoteAgentService), instantiationService.get(IExtensionGalleryService), instantiationService.get(IConfigurationService), instantiationService.get(IProductService), instantiationService.get(ILogService));
}
get localExtensionManagementServer(): IExtensionManagementServer { return this._localExtensionManagementServer; }
set localExtensionManagementServer(server: IExtensionManagementServer) { }
@@ -113,7 +115,7 @@ suite('ExtensionsListView Tests', () => {
instantiationService.stubPromise(IExtensionTipsService, 'getOtherRecommendations', [
{ extensionId: otherRecommendationA.identifier.id }
]);
const reasons = {};
const reasons: { [key: string]: any } = {};
reasons[workspaceRecommendationA.identifier.id] = { reasonId: ExtensionRecommendationReason.Workspace };
reasons[workspaceRecommendationB.identifier.id] = { reasonId: ExtensionRecommendationReason.Workspace };
reasons[fileBasedRecommendationA.identifier.id] = { reasonId: ExtensionRecommendationReason.File };

View File

@@ -18,7 +18,7 @@ import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/ex
import { ExtensionManagementService } from 'vs/platform/extensionManagement/node/extensionManagementService';
import { ExtensionTipsService } from 'vs/workbench/contrib/extensions/electron-browser/extensionTipsService';
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/electron-browser/extensionEnablementService.test';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService';
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
import { IURLService } from 'vs/platform/url/common/url';
import { TestInstantiationService } from 'vs/platform/instantiation/test/common/instantiationServiceMock';
import { Event, Emitter } from 'vs/base/common/event';
@@ -30,8 +30,8 @@ import { TestContextService, TestWindowService, TestSharedProcessService } from
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { ILogService, NullLogService } from 'vs/platform/log/common/log';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IProgressService2 } from 'vs/platform/progress/common/progress';
import { ProgressService2 } from 'vs/workbench/services/progress/browser/progressService2';
import { IProgressService } from 'vs/platform/progress/common/progress';
import { ProgressService } from 'vs/workbench/services/progress/browser/progressService';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { URLService } from 'vs/platform/url/common/urlService';
import { URI } from 'vs/base/common/uri';
@@ -61,7 +61,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
instantiationService.stub(ITelemetryService, NullTelemetryService);
instantiationService.stub(ILogService, NullLogService);
instantiationService.stub(IWindowService, TestWindowService);
instantiationService.stub(IProgressService2, ProgressService2);
instantiationService.stub(IProgressService, ProgressService);
instantiationService.stub(IExtensionGalleryService, ExtensionGalleryService);
instantiationService.stub(IURLService, URLService);
@@ -129,7 +129,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
icon: { uri: 'uri:icon', fallbackUri: 'fallback:icon' },
license: { uri: 'uri:license', fallbackUri: 'fallback:license' },
repository: { uri: 'uri:repository', fallbackUri: 'fallback:repository' },
coreTranslations: {}
coreTranslations: []
});
testObject = await aWorkbenchService();
@@ -279,7 +279,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
icon: { uri: 'uri:icon', fallbackUri: 'fallback:icon' },
license: { uri: 'uri:license', fallbackUri: 'fallback:license' },
repository: { uri: 'uri:repository', fallbackUri: 'fallback:repository' },
coreTranslations: {}
coreTranslations: []
});
instantiationService.stubPromise(IExtensionManagementService, 'getInstalled', [local1, local2]);
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery1));
@@ -968,7 +968,7 @@ suite('ExtensionsWorkbenchServiceTest', () => {
manifest: null,
readme: null,
repository: null,
coreTranslations: null!
coreTranslations: []
};
function aGalleryExtension(name: string, properties: any = {}, galleryExtensionProperties: any = {}, assets: IGalleryExtensionAssets = noAssets): IGalleryExtension {