Merge from vscode 817eb6b0c720a4ecbc13c020afbbebfed667aa09 (#7356)

This commit is contained in:
Anthony Dresser
2019-09-24 21:36:17 -07:00
committed by GitHub
parent a29ae4d3b9
commit 6a6048d40f
541 changed files with 7045 additions and 7287 deletions

View File

@@ -5,7 +5,6 @@
import 'vs/css!./media/extensionEditor';
import { localize } from 'vs/nls';
import * as marked from 'vs/base/common/marked/marked';
import { createCancelablePromise } from 'vs/base/common/async';
import * as arrays from 'vs/base/common/arrays';
import { OS } from 'vs/base/common/platform';
@@ -56,6 +55,11 @@ import { renderDashboardContributions } from 'sql/workbench/parts/extensions/bro
import { generateUuid } from 'vs/base/common/uuid';
import { platform } from 'vs/base/common/process';
import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { renderMarkdownDocument } from 'vs/workbench/common/markdownDocumentRenderer';
import { IModeService } from 'vs/editor/common/services/modeService';
import { TokenizationRegistry } from 'vs/editor/common/modes';
import { generateTokensCSSForColorMap } from 'vs/editor/common/modes/supports/tokenization';
function removeEmbeddedSVGs(documentContent: string): string {
const newDocument = new DOMParser().parseFromString(documentContent, 'text/html');
@@ -187,7 +191,8 @@ export class ExtensionEditor extends BaseEditor {
@IStorageService storageService: IStorageService,
@IExtensionService private readonly extensionService: IExtensionService,
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IWebviewService private readonly webviewService: IWebviewService
@IWebviewService private readonly webviewService: IWebviewService,
@IModeService private readonly modeService: IModeService,
) {
super(ExtensionEditor.ID, telemetryService, themeService, storageService);
this.extensionReadme = null;
@@ -580,44 +585,68 @@ export class ExtensionEditor extends BaseEditor {
return Promise.resolve(null);
}
private openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate): Promise<IActiveElement> {
return this.loadContents(() => cacheResult, template)
.then(marked.parse)
.then(content => this.renderBody(content))
.then(removeEmbeddedSVGs)
.then(body => {
const webviewElement = this.webviewService.createWebview('extensionEditor',
{
enableFindWidget: true,
},
{});
webviewElement.mountTo(template.content);
this.contentDisposables.add(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, webviewElement);
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
webviewElement.html = body;
private async openMarkdown(cacheResult: CacheResult<string>, noContentCopy: string, template: IExtensionEditorTemplate): Promise<IActiveElement> {
try {
const body = await this.renderMarkdown(cacheResult, template);
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 === ShowCurrentReleaseNotesActionId)) {
this.openerService.open(link);
}
}, null, this.contentDisposables));
this.contentDisposables.add(webviewElement);
return webviewElement;
})
.then(undefined, () => {
const p = append(template.content, $('p.nocontent'));
p.textContent = noContentCopy;
return p;
const webviewElement = this.contentDisposables.add(this.webviewService.createWebviewEditorOverlay('extensionEditor', {
enableFindWidget: true,
}, {}));
webviewElement.claim(this);
webviewElement.layoutWebviewOverElement(template.content);
webviewElement.html = body;
this.contentDisposables.add(webviewElement.onDidFocus(() => this.fireOnDidFocus()));
const removeLayoutParticipant = arrays.insert(this.layoutParticipants, {
layout: () => {
webviewElement.layout();
webviewElement.layoutWebviewOverElement(template.content);
}
});
this.contentDisposables.add(toDisposable(removeLayoutParticipant));
let isDisposed = false;
this.contentDisposables.add(toDisposable(() => { isDisposed = true; }));
this.contentDisposables.add(this.themeService.onThemeChange(async () => {
// Render again since syntax highlighting of code blocks may have changed
const body = await this.renderMarkdown(cacheResult, template);
if (!isDisposed) { // Make sure we weren't disposed of in the meantime
webviewElement.html = body;
}
}));
this.contentDisposables.add(webviewElement.onDidClickLink(link => {
if (!link) {
return;
}
// Whitelist supported schemes for links
if ([Schemas.http, Schemas.https, Schemas.mailto].indexOf(link.scheme) >= 0 || (link.scheme === 'command' && link.path === ShowCurrentReleaseNotesActionId)) {
this.openerService.open(link);
}
}, null, this.contentDisposables));
return webviewElement;
} catch (e) {
const p = append(template.content, $('p.nocontent'));
p.textContent = noContentCopy;
return p;
}
}
private async renderMarkdown(cacheResult: CacheResult<string>, template: IExtensionEditorTemplate) {
const contents = await this.loadContents(() => cacheResult, template);
const content = await renderMarkdownDocument(contents, this.extensionService, this.modeService);
const documentContent = await this.renderBody(content);
return removeEmbeddedSVGs(documentContent);
}
private async renderBody(body: string): Promise<string> {
const nonce = generateUuid();
const colorMap = TokenizationRegistry.getColorMap();
const css = colorMap ? generateTokensCSSForColorMap(colorMap) : '';
return `<!DOCTYPE html>
<html>
<head>
@@ -695,14 +724,9 @@ export class ExtensionEditor extends BaseEditor {
}
code {
font-family: Menlo, Monaco, Consolas, "Droid Sans Mono", "Courier New", monospace, "Droid Sans Fallback";
font-size: 14px;
line-height: 19px;
}
.mac code {
font-size: 12px;
line-height: 18px;
font-family: var(--vscode-editor-font-family);
font-weight: var(--vscode-editor-font-weight);
font-size: var(--vscode-editor-font-size);
}
code > div {
@@ -711,6 +735,10 @@ export class ExtensionEditor extends BaseEditor {
overflow: auto;
}
.monaco-tokenized-source {
white-space: pre;
}
#scroll-to-top {
position: fixed;
width: 40px;
@@ -795,6 +823,7 @@ export class ExtensionEditor extends BaseEditor {
border-color: rgba(255, 255, 255, 0.18);
}
${css}
</style>
</head>
<body>

View File

@@ -26,7 +26,7 @@ import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { Query } from 'vs/workbench/contrib/extensions/common/extensionQuery';
import { IFileService, IFileContent } from 'vs/platform/files/common/files';
import { IWorkspaceContextService, WorkbenchState, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { URI } from 'vs/base/common/uri';
import { CommandsRegistry, ICommandService } from 'vs/platform/commands/common/commands';
@@ -1178,7 +1178,7 @@ export class ReloadAction extends ExtensionAction {
constructor(
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@IExtensionService private readonly extensionService: IExtensionService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService
@@ -1230,7 +1230,7 @@ export class ReloadAction extends ExtensionAction {
if (this.extension.local) {
const isEnabled = this.extensionEnablementService.isEnabled(this.extension.local);
// Extension is runningÎ
// Extension is running
if (runningExtension) {
if (isEnabled) {
if (!this.extensionService.canAddExtension(toExtensionDescription(this.extension.local))) {
@@ -1241,11 +1241,6 @@ export class ReloadAction extends ExtensionAction {
// {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
this.tooltip = localize('postUpdateTooltip', "Please reload Azure Data Studio to enable the updated extension.");
}
} else {
this.enabled = true;
this.label = localize('reloadRequired', "Reload Required");
// {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
this.tooltip = localize('postEnableTooltip', "Please reload Azure Data Studio to enable this extension.");
}
}
} else {
@@ -1285,7 +1280,7 @@ export class ReloadAction extends ExtensionAction {
}
run(): Promise<any> {
return Promise.resolve(this.windowService.reloadWindow());
return Promise.resolve(this.hostService.reload());
}
}
@@ -1634,6 +1629,29 @@ export class ShowRecommendedExtensionsAction extends Action {
}
}
export class ShowSyncedExtensionsAction extends Action {
static readonly ID = 'workbench.extensions.action.listSyncedExtensions';
static LABEL = localize('showSyncedExtensions', "Show My Accoount Extensions");
constructor(
id: string,
label: string,
@IViewletService private readonly viewletService: IViewletService
) {
super(id, label, undefined, true);
}
run(): Promise<void> {
return this.viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => {
viewlet.search('@myaccount ');
viewlet.focus();
});
}
}
export class InstallWorkspaceRecommendedExtensionsAction extends Action {
static readonly ID = 'workbench.extensions.action.installWorkspaceRecommendedExtensions';
@@ -2622,11 +2640,10 @@ export class SystemDisabledWarningAction extends ExtensionAction {
constructor(
@IExtensionManagementServerService private readonly extensionManagementServerService: IExtensionManagementServerService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IProductService private readonly productService: IProductService,
@ILabelService private readonly labelService: ILabelService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionService private readonly extensionService: IExtensionService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
) {
super('extensions.install', '', `${SystemDisabledWarningAction.CLASS} hide`, false);
this._register(this.labelService.onDidChangeFormatters(() => this.update(), this));
@@ -2662,32 +2679,24 @@ export class SystemDisabledWarningAction extends ExtensionAction {
return;
}
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.productService, this.configurationService)) {
if (runningExtensionServer === this.extensionManagementServerService.remoteExtensionManagementServer) {
if (!runningExtension && this.extension.enablementState === EnablementState.DisabledByExtensionKind) {
this.class = `${SystemDisabledWarningAction.WARNING_CLASS}`;
const server = this.extensionManagementServerService.localExtensionManagementServer === this.extension.server ? this.extensionManagementServerService.remoteExtensionManagementServer : this.extensionManagementServerService.localExtensionManagementServer;
this.tooltip = localize('Install in other server to enable', "Install the extension on '{0}' to enable.", server.label);
return;
}
if (this.extensionEnablementService.isEnabled(this.extension.local)) {
const runningExtensionServer = runningExtension ? this.extensionManagementServerService.getExtensionManagementServer(runningExtension.extensionLocation) : null;
if (this.extension.server === this.extensionManagementServerService.localExtensionManagementServer && runningExtensionServer === this.extensionManagementServerService.remoteExtensionManagementServer) {
this.class = `${SystemDisabledWarningAction.INFO_CLASS}`;
this.tooltip = localize('disabled locally', "Extension is enabled on '{0}' and disabled locally.", this.extensionManagementServerService.remoteExtensionManagementServer.label);
return;
}
if (localExtensionServer !== this.extensionManagementServerService.remoteExtensionManagementServer) {
this.class = `${SystemDisabledWarningAction.WARNING_CLASS}`;
this.tooltip = localize('Install in remote server', "Install the extension on '{0}' to enable.", this.extensionManagementServerService.remoteExtensionManagementServer.label);
return;
}
}
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && isUIExtension(this.extension.local.manifest, this.productService, this.configurationService)) {
if (runningExtensionServer === this.extensionManagementServerService.localExtensionManagementServer) {
if (this.extension.server === this.extensionManagementServerService.remoteExtensionManagementServer && runningExtensionServer === this.extensionManagementServerService.localExtensionManagementServer) {
this.class = `${SystemDisabledWarningAction.INFO_CLASS}`;
this.tooltip = localize('disabled remotely', "Extension is enabled locally and disabled on '{0}'.", this.extensionManagementServerService.remoteExtensionManagementServer.label);
return;
}
if (localExtensionServer !== this.extensionManagementServerService.localExtensionManagementServer) {
this.class = `${SystemDisabledWarningAction.WARNING_CLASS}`;
this.tooltip = localize('Install in local server', "Install the extension locally to enable.");
return;
}
}
}
@@ -2810,10 +2819,9 @@ export class InstallVSIXAction extends Action {
label = InstallVSIXAction.LABEL,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@IFileDialogService private readonly fileDialogService: IFileDialogService,
@IExtensionService private readonly extensionService: IExtensionService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
// {{SQL CARBON EDIT}}
@IConfigurationService private configurationService: IConfigurationService,
@IStorageService private storageService: IStorageService
@@ -2825,17 +2833,17 @@ export class InstallVSIXAction extends Action {
// {{SQL CARBON EDIT}} - Replace run body
let extensionPolicy = this.configurationService.getValue<string>(ExtensionsPolicyKey);
if (extensionPolicy === ExtensionsPolicy.allowAll) {
return Promise.resolve(this.windowService.showOpenDialog({
return Promise.resolve(this.fileDialogService.showOpenDialog({
title: localize('installFromVSIX', "Install from VSIX"),
filters: [{ name: 'VSIX Extensions', extensions: ['vsix'] }],
properties: ['openFile'],
buttonLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
canSelectFiles: true,
openLabel: mnemonicButtonLabel(localize({ key: 'installButton', comment: ['&& denotes a mnemonic'] }, "&&Install"))
}).then(result => {
if (!result) {
return Promise.resolve();
}
return Promise.all(result.map(vsix => {
if (!this.storageService.getBoolean(vsix, StorageScope.GLOBAL)) {
if (!this.storageService.getBoolean(vsix.fsPath, StorageScope.GLOBAL)) {
this.notificationService.prompt(
Severity.Warning,
localize('thirdPartyExtension.vsix', 'This is a third party extension and might involve security risks. Are you sure you want to install this extension?'),
@@ -2843,13 +2851,13 @@ export class InstallVSIXAction extends Action {
{
label: localize('thirdPartExt.yes', 'Yes'),
run: () => {
this.extensionsWorkbenchService.install(URI.file(vsix)).then(extension => {
this.extensionsWorkbenchService.install(vsix).then(extension => {
const requireReload = !(extension.local && this.extensionService.canAddExtension(toExtensionDescription(extension.local)));
const message = requireReload ? localize('InstallVSIXAction.successReload', "Please reload Azure Data Studio to complete installing the extension {0}.", extension.identifier.id)
: localize('InstallVSIXAction.success', "Completed installing the extension {0}.", extension.identifier.id);
const actions = requireReload ? [{
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
run: () => this.windowService.reloadWindow()
run: () => this.hostService.reload()
}] : [];
this.notificationService.prompt(
Severity.Info,
@@ -2868,7 +2876,7 @@ export class InstallVSIXAction extends Action {
label: localize('thirdPartyExt.dontShowAgain', 'Don\'t Show Again'),
isSecondary: true,
run: () => {
this.storageService.store(vsix, true, StorageScope.GLOBAL);
this.storageService.store(vsix.fsPath, true, StorageScope.GLOBAL);
return Promise.resolve();
}
}
@@ -2876,13 +2884,13 @@ export class InstallVSIXAction extends Action {
{ sticky: true }
);
} else {
this.extensionsWorkbenchService.install(URI.file(vsix)).then(extension => {
this.extensionsWorkbenchService.install(vsix).then(extension => {
const requireReload = !(extension.local && this.extensionService.canAddExtension(toExtensionDescription(extension.local)));
const message = requireReload ? localize('InstallVSIXAction.successReload', "Please reload Azure Data Studio to complete installing the extension {0}.", extension.identifier.id)
: localize('InstallVSIXAction.success', "Completed installing the extension {0}.", extension.identifier.id);
const actions = requireReload ? [{
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
run: () => this.windowService.reloadWindow()
run: () => this.hostService.reload()
}] : [];
this.notificationService.prompt(
Severity.Info,
@@ -2912,7 +2920,7 @@ export class ReinstallAction extends Action {
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IExtensionService private readonly extensionService: IExtensionService
) {
@@ -2956,7 +2964,7 @@ export class ReinstallAction extends Action {
: localize('ReinstallAction.success', "Reinstalling the extension {0} is completed.", extension.identifier.id);
const actions = requireReload ? [{
label: localize('InstallVSIXAction.reloadNow', "Reload Now"),
run: () => this.windowService.reloadWindow()
run: () => this.hostService.reload()
}] : [];
this.notificationService.prompt(
Severity.Info,
@@ -2980,7 +2988,7 @@ export class InstallSpecificVersionOfExtensionAction extends Action {
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IExtensionService private readonly extensionService: IExtensionService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@@ -3042,7 +3050,7 @@ export class InstallSpecificVersionOfExtensionAction extends Action {
: localize('InstallAnotherVersionExtensionAction.success', "Installing the extension {0} is completed.", extension.identifier.id);
const actions = requireReload ? [{
label: localize('InstallAnotherVersionExtensionAction.reloadNow', "Reload Now"),
run: () => this.windowService.reloadWindow()
run: () => this.hostService.reload()
}] : [];
this.notificationService.prompt(
Severity.Info,
@@ -3069,7 +3077,7 @@ export class InstallLocalExtensionsInRemoteAction extends Action {
@IExtensionGalleryService private readonly extensionGalleryService: IExtensionGalleryService,
@IQuickInputService private readonly quickInputService: IQuickInputService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@IProgressService private readonly progressService: IProgressService,
@IInstantiationService private readonly instantiationService: IInstantiationService
) {
@@ -3182,7 +3190,7 @@ export class InstallLocalExtensionsInRemoteAction extends Action {
message: localize('finished installing', "Successfully installed extensions in {0}. Please reload the window to enable them.", this.extensionManagementServerService.remoteExtensionManagementServer!.label),
actions: {
primary: [new Action('realod', localize('reload', "Reload Window"), '', true,
() => this.windowService.reloadWindow())]
() => this.hostService.reload())]
}
});
}

View File

@@ -13,7 +13,7 @@ import { values } from 'vs/base/common/map';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { Action } from 'vs/base/common/actions';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { Disposable } from 'vs/base/common/lifecycle';
import { CancellationToken } from 'vs/base/common/cancellation';
@@ -23,7 +23,7 @@ export class ExtensionDependencyChecker extends Disposable implements IWorkbench
@IExtensionService private readonly extensionService: IExtensionService,
@IExtensionsWorkbenchService private readonly extensionsWorkbenchService: IExtensionsWorkbenchService,
@INotificationService private readonly notificationService: INotificationService,
@IWindowService private readonly windowService: IWindowService
@IHostService private readonly hostService: IHostService
) {
super();
CommandsRegistry.registerCommand('workbench.extensions.installMissingDepenencies', () => this.installMissingDependencies());
@@ -69,7 +69,7 @@ export class ExtensionDependencyChecker extends Disposable implements IWorkbench
message: localize('finished installing missing deps', "Finished installing missing dependencies. Please reload the window now."),
actions: {
primary: [new Action('realod', localize('reload', "Reload Window"), '', true,
() => this.windowService.reloadWindow())]
() => this.hostService.reload())]
}
});
}

View File

@@ -22,12 +22,12 @@ import { IExtensionsWorkbenchService, IExtensionsViewlet, VIEWLET_ID, AutoUpdate
import {
ShowEnabledExtensionsAction, ShowInstalledExtensionsAction, ShowRecommendedExtensionsAction, ShowPopularExtensionsAction, ShowDisabledExtensionsAction,
ShowOutdatedExtensionsAction, ClearExtensionsInputAction, ChangeSortAction, UpdateAllAction, CheckForUpdatesAction, DisableAllAction, EnableAllAction,
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction
EnableAutoUpdateAction, DisableAutoUpdateAction, ShowBuiltInExtensionsAction, InstallVSIXAction, ShowSyncedExtensionsAction
} from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionEnablementService, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView, SyncedExtensionsView } from 'vs/workbench/contrib/extensions/browser/extensionsViews';
import { OpenGlobalSettingsAction } from 'vs/workbench/contrib/preferences/browser/preferencesActions';
import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/progress';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
@@ -43,7 +43,7 @@ import { IContextMenuService } from 'vs/platform/contextview/browser/contextView
import { getMaliciousExtensionsSet } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { ILogService } from 'vs/platform/log/common/log';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { IHostService } from 'vs/workbench/services/host/browser/host';
import { IWorkbenchLayoutService } from 'vs/workbench/services/layout/browser/layoutService';
import { IAddedViewDescriptorRef } from 'vs/workbench/browser/parts/views/views';
import { ViewletPanel } from 'vs/workbench/browser/parts/views/panelViewlet';
@@ -58,6 +58,7 @@ import { ViewContainerViewlet } from 'vs/workbench/browser/parts/views/viewsView
import { RemoteNameContext } from 'vs/workbench/browser/contextkeys';
import { ILabelService } from 'vs/platform/label/common/label';
import { MementoObject } from 'vs/workbench/common/memento';
import { SyncStatus, CONTEXT_SYNC_STATE } from 'vs/platform/userDataSync/common/userDataSync';
const NonEmptyWorkspaceContext = new RawContextKey<boolean>('nonEmptyWorkspace', false);
const DefaultViewsContext = new RawContextKey<boolean>('defaultExtensionViews', true);
@@ -70,6 +71,7 @@ const HasInstalledExtensionsContext = new RawContextKey<boolean>('hasInstalledEx
const SearchBuiltInExtensionsContext = new RawContextKey<boolean>('searchBuiltInExtensions', false);
const RecommendedExtensionsContext = new RawContextKey<boolean>('recommendedExtensions', false);
const DefaultRecommendedExtensionsContext = new RawContextKey<boolean>('defaultRecommendedExtensions', false);
const SyncedExtensionsContext = new RawContextKey<boolean>('syncedExtensions', false);
const viewIdNameMappings: { [id: string]: string } = {
'extensions.listView': localize('marketPlace', "Marketplace"),
'extensions.enabledExtensionList': localize('enabledExtensions', "Enabled"),
@@ -84,6 +86,7 @@ const viewIdNameMappings: { [id: string]: string } = {
'extensions.builtInExtensionsList': localize('builtInExtensions', "Features"),
'extensions.builtInThemesExtensionsList': localize('builtInThemesExtensions', "Themes"),
'extensions.builtInBasicsExtensionsList': localize('builtInBasicsExtensions', "Programming Languages"),
'extensions.syncedExtensionsList': localize('syncedExtensions', "My Account"),
};
export class ExtensionsViewletViewsContribution implements IWorkbenchContribution {
@@ -110,6 +113,7 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
viewDescriptors.push(this.createDefaultRecommendedExtensionsListViewDescriptor());
viewDescriptors.push(this.createOtherRecommendedExtensionsListViewDescriptor());
viewDescriptors.push(this.createWorkspaceRecommendedExtensionsListViewDescriptor());
viewDescriptors.push(this.createSyncedExtensionsViewDescriptor());
if (this.extensionManagementServerService.localExtensionManagementServer) {
viewDescriptors.push(...this.createExtensionsViewDescriptorsForServer(this.extensionManagementServerService.localExtensionManagementServer));
@@ -314,6 +318,17 @@ export class ExtensionsViewletViewsContribution implements IWorkbenchContributio
weight: 100
};
}
private createSyncedExtensionsViewDescriptor(): IViewDescriptor {
const id = 'extensions.syncedExtensionsList';
return {
id,
name: viewIdNameMappings[id],
ctorDescriptor: { ctor: SyncedExtensionsView },
when: ContextKeyExpr.and(CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized), ContextKeyExpr.has('config.userConfiguration.enableSync'), ContextKeyExpr.has('syncedExtensions')),
weight: 100
};
}
}
export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensionsViewlet {
@@ -330,6 +345,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private hasInstalledExtensionsContextKey: IContextKey<boolean>;
private searchBuiltInExtensionsContextKey: IContextKey<boolean>;
private recommendedExtensionsContextKey: IContextKey<boolean>;
private syncedExtensionsContextKey: IContextKey<boolean>;
private defaultRecommendedExtensionsContextKey: IContextKey<boolean>;
private searchDelayer: Delayer<void>;
@@ -371,6 +387,7 @@ 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.syncedExtensionsContextKey = SyncedExtensionsContext.bindTo(contextKeyService);
this._register(this.viewletService.onDidViewletOpen(this.onViewletOpen, this));
this.searchViewletState = this.getMemento(StorageScope.WORKSPACE);
@@ -469,8 +486,8 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.instantiationService.createInstance(ShowDisabledExtensionsAction, ShowDisabledExtensionsAction.ID, ShowDisabledExtensionsAction.LABEL),
this.instantiationService.createInstance(ShowBuiltInExtensionsAction, ShowBuiltInExtensionsAction.ID, ShowBuiltInExtensionsAction.LABEL),
this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, ShowRecommendedExtensionsAction.LABEL),
// {{SQL CARBON EDIT}}
// this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL),
// this.instantiationService.createInstance(ShowPopularExtensionsAction, ShowPopularExtensionsAction.ID, ShowPopularExtensionsAction.LABEL), // {{SQL CARBON EDIT}}
this.instantiationService.createInstance(ShowSyncedExtensionsAction, ShowSyncedExtensionsAction.ID, ShowSyncedExtensionsAction.LABEL),
new Separator(),
// {{SQL CARBON EDIT}}
//this.instantiationService.createInstance(ChangeSortAction, 'extensions.sort.install', localize('sort by installs', "Sort By: Install Count"), this.onSearchChange, 'installs'),
@@ -519,6 +536,7 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
private doSearch(): Promise<void> {
const value = this.normalizedQuery();
const isSyncedExtensionsQuery = ExtensionsListView.isSyncedExtensionsQuery(value);
const isRecommendedExtensionsQuery = ExtensionsListView.isRecommendedExtensionsQuery(value);
this.searchInstalledExtensionsContextKey.set(ExtensionsListView.isInstalledExtensionsQuery(value));
this.searchOutdatedExtensionsContextKey.set(ExtensionsListView.isOutdatedExtensionsQuery(value));
@@ -526,7 +544,8 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
this.searchDisabledExtensionsContextKey.set(ExtensionsListView.isDisabledExtensionsQuery(value));
this.searchBuiltInExtensionsContextKey.set(ExtensionsListView.isBuiltInExtensionsQuery(value));
this.recommendedExtensionsContextKey.set(isRecommendedExtensionsQuery);
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery);
this.syncedExtensionsContextKey.set(isSyncedExtensionsQuery);
this.searchMarketplaceExtensionsContextKey.set(!!value && !ExtensionsListView.isLocalExtensionsQuery(value) && !isRecommendedExtensionsQuery && !isSyncedExtensionsQuery);
this.nonEmptyWorkspaceContextKey.set(this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY);
this.defaultViewsContextKey.set(!value);
@@ -647,7 +666,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
constructor(
@IExtensionManagementService private readonly extensionsManagementService: IExtensionManagementService,
@IWindowService private readonly windowService: IWindowService,
@IHostService private readonly hostService: IHostService,
@ILogService private readonly logService: ILogService,
@INotificationService private readonly notificationService: INotificationService,
@IEnvironmentService private readonly environmentService: IEnvironmentService
@@ -678,7 +697,7 @@ export class MaliciousExtensionChecker implements IWorkbenchContribution {
localize('malicious warning', "We have uninstalled '{0}' which was reported to be problematic.", e.identifier.id),
[{
label: localize('reloadNow', "Reload Now"),
run: () => this.windowService.reloadWindow()
run: () => this.hostService.reload()
}],
{ sticky: true }
);

View File

@@ -47,6 +47,7 @@ import { CancelablePromise, createCancelablePromise } from 'vs/base/common/async
import { IProductService } from 'vs/platform/product/common/productService';
import { SeverityIcon } from 'vs/platform/severityIcon/common/severityIcon';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { IUserDataSyncService } from 'vs/platform/userDataSync/common/userDataSync';
class ExtensionsViewState extends Disposable implements IExtensionsViewState {
@@ -104,6 +105,7 @@ export class ExtensionsListView extends ViewletPanel {
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
@IProductService protected readonly productService: IProductService,
@IContextKeyService contextKeyService: IContextKeyService,
@IUserDataSyncService private readonly userDataSyncService: IUserDataSyncService,
) {
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title, showActionsAlways: true }, keybindingService, contextMenuService, configurationService, contextKeyService);
this.server = options.server;
@@ -456,8 +458,10 @@ export class ExtensionsListView extends ViewletPanel {
} else if (ExtensionsListView.isRecommendedExtensionsQuery(query.value)) {
return this.getRecommendationsModel(query, options, token);
// {{SQL CARBON EDIT}}
} else if (ExtensionsListView.isAllMarketplaceExtensionsQuery(query.value)) {
} else if (ExtensionsListView.isAllMarketplaceExtensionsQuery(query.value)) { // {{SQL CARBON EDIT}} add if
return this.getAllMarketplaceModel(query, options, token);
} else if (ExtensionsListView.isSyncedExtensionsQuery(query.value)) {
return this.getSyncedExtensionsModel(query, options, token);
}
if (/\bcurated:([^\s]+)\b/.test(query.value)) {
@@ -765,6 +769,23 @@ export class ExtensionsListView extends ViewletPanel {
.then(result => this.getPagedModel(result));
}
private async getSyncedExtensionsModel(query: Query, options: IQueryOptions, token: CancellationToken): Promise<IPagedModel<IExtension>> {
const syncedExtensions = await this.userDataSyncService.getRemoteExtensions();
if (!syncedExtensions.length) {
return this.showEmptyModel();
}
const ids: string[] = [], names: string[] = [];
for (const installed of syncedExtensions) {
if (installed.identifier.uuid) {
ids.push(installed.identifier.uuid);
} else {
names.push(installed.identifier.id);
}
}
const pager = await this.extensionsWorkbenchService.queryGallery({ ids, names, pageSize: ids.length }, token);
return this.getPagedModel(pager || []);
}
// Sorts the firstPage of the pager in the same order as given array of extension ids
private sortFirstPage(pager: IPager<IExtension>, ids: string[]) {
ids = ids.map(x => x.toLowerCase());
@@ -904,6 +925,10 @@ export class ExtensionsListView extends ViewletPanel {
return /@recommended:keymaps/i.test(query);
}
static isSyncedExtensionsQuery(query: string): boolean {
return /@myaccount/i.test(query);
}
focus(): void {
super.focus();
if (!this.list) {
@@ -944,10 +969,11 @@ export class ServerExtensionsView extends ExtensionsListView {
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService,
@IProductService productService: IProductService,
@IContextKeyService contextKeyService: IContextKeyService
@IContextKeyService contextKeyService: IContextKeyService,
@IUserDataSyncService userDataSyncService: IUserDataSyncService
) {
options.server = server;
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService, contextKeyService);
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService, contextKeyService, userDataSyncService);
this._register(onDidChangeTitle(title => this.updateTitle(title)));
}
@@ -1003,6 +1029,14 @@ export class BuiltInBasicsExtensionsView extends ExtensionsListView {
}
}
export class SyncedExtensionsView extends ExtensionsListView {
async show(query: string): Promise<IPagedModel<IExtension>> {
query = query || '@myaccount';
return ExtensionsListView.isSyncedExtensionsQuery(query) ? super.show(query) : this.showEmptyModel();
}
}
export class DefaultRecommendedExtensionsView extends ExtensionsListView {
// {{SQL CARBON EDIT}}
private readonly recommendedExtensionsQuery = '@allmarketplace';

View File

@@ -11,7 +11,7 @@ export const ExtensionsConfigurationSchemaId = 'vscode://schemas/extensions';
export const ExtensionsConfigurationSchema: IJSONSchema = {
id: ExtensionsConfigurationSchemaId,
allowComments: true,
allowsTrailingCommas: true,
allowTrailingCommas: true,
type: 'object',
title: localize('app.extensions.json.title', "Extensions"),
additionalProperties: false,
@@ -39,7 +39,7 @@ export const ExtensionsConfigurationSchema: IJSONSchema = {
export const ExtensionsConfigurationInitialContent: string = [
'{',
'\t// See http://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.',
'\t// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.',
'\t// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp',
'',
'\t// List of extensions which should be recommended for users of this workspace.',

View File

@@ -12,7 +12,7 @@ import { onUnexpectedError } from 'vs/base/common/errors';
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';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
import { randomPort } from 'vs/base/node/ports';
import product from 'vs/platform/product/common/product';
@@ -46,7 +46,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
@IExtensionService private readonly _extensionService: IExtensionService,
@IEditorService private readonly _editorService: IEditorService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IWindowsService private readonly _windowsService: IWindowsService,
@IElectronService private readonly _electronService: IElectronService,
@IDialogService private readonly _dialogService: IDialogService,
@IStatusbarService private readonly _statusbarService: IStatusbarService,
) {
@@ -122,7 +122,7 @@ export class ExtensionHostProfileService extends Disposable implements IExtensio
secondaryButton: nls.localize('cancel', "Cancel")
}).then(res => {
if (res.confirmed) {
this._windowsService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
this._electronService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
}
});
}

View File

@@ -24,7 +24,7 @@ import { RunOnceScheduler } from 'vs/base/common/async';
import { clipboard } from 'electron';
import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
import { IWindowService, IWindowsService } from 'vs/platform/windows/common/windows';
import { IElectronService } from 'vs/platform/electron/node/electron';
import { writeFile } from 'vs/base/node/pfs';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { memoize } from 'vs/base/common/decorators';
@@ -307,7 +307,7 @@ export class RuntimeExtensionsEditor extends BaseEditor {
const activationTimes = element.status.activationTimes!;
let syncTime = activationTimes.codeLoadingTime + activationTimes.activateCallTime;
data.activationTime.textContent = activationTimes.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
data.activationTime.textContent = activationTimes.activationReason.startup ? `Startup Activation: ${syncTime}ms` : `Activation: ${syncTime}ms`;
data.actionbar.clear();
if (element.unresponsiveProfile) {
@@ -318,43 +318,45 @@ export class RuntimeExtensionsEditor extends BaseEditor {
}
let title: string;
if (activationTimes.activationEvent === '*') {
title = nls.localize('starActivation', "Activated on start-up");
} else if (/^workspaceContains:/.test(activationTimes.activationEvent)) {
let fileNameOrGlob = activationTimes.activationEvent.substr('workspaceContains:'.length);
const activationId = activationTimes.activationReason.extensionId.value;
const activationEvent = activationTimes.activationReason.activationEvent;
if (activationEvent === '*') {
title = nls.localize('starActivation', "Activated by {0} on start-up", activationId);
} else if (/^workspaceContains:/.test(activationEvent)) {
let fileNameOrGlob = activationEvent.substr('workspaceContains:'.length);
if (fileNameOrGlob.indexOf('*') >= 0 || fileNameOrGlob.indexOf('?') >= 0) {
title = nls.localize({
key: 'workspaceContainsGlobActivation',
comment: [
'{0} will be a glob pattern'
]
}, "Activated because a file matching {0} exists in your workspace", fileNameOrGlob);
}, "Activated by {1} because a file matching {1} exists in your workspace", fileNameOrGlob, activationId);
} else {
title = nls.localize({
key: 'workspaceContainsFileActivation',
comment: [
'{0} will be a file name'
]
}, "Activated because file {0} exists in your workspace", fileNameOrGlob);
}, "Activated by {1} because file {0} exists in your workspace", fileNameOrGlob, activationId);
}
} else if (/^workspaceContainsTimeout:/.test(activationTimes.activationEvent)) {
const glob = activationTimes.activationEvent.substr('workspaceContainsTimeout:'.length);
} else if (/^workspaceContainsTimeout:/.test(activationEvent)) {
const glob = activationEvent.substr('workspaceContainsTimeout:'.length);
title = nls.localize({
key: 'workspaceContainsTimeout',
comment: [
'{0} will be a glob pattern'
]
}, "Activated because searching for {0} took too long", glob);
} else if (/^onLanguage:/.test(activationTimes.activationEvent)) {
let language = activationTimes.activationEvent.substr('onLanguage:'.length);
title = nls.localize('languageActivation', "Activated because you opened a {0} file", language);
}, "Activated by {1} because searching for {0} took too long", glob, activationId);
} else if (/^onLanguage:/.test(activationEvent)) {
let language = activationEvent.substr('onLanguage:'.length);
title = nls.localize('languageActivation', "Activated by {1} because you opened a {0} file", language, activationId);
} else {
title = nls.localize({
key: 'workspaceGenericActivation',
comment: [
'The {0} placeholder will be an activation event, like e.g. \'language:typescript\', \'debug\', etc.'
]
}, "Activated on {0}", activationTimes.activationEvent);
}, "Activated by {1} on {0}", activationEvent, activationId);
}
data.activationTime.title = title;
@@ -536,7 +538,7 @@ export class DebugExtensionHostAction extends Action {
constructor(
@IDebugService private readonly _debugService: IDebugService,
@IWindowsService private readonly _windowsService: IWindowsService,
@IElectronService private readonly _electronService: IElectronService,
@IDialogService private readonly _dialogService: IDialogService,
@IExtensionService private readonly _extensionService: IExtensionService,
) {
@@ -555,7 +557,7 @@ export class DebugExtensionHostAction extends Action {
secondaryButton: nls.localize('cancel', "Cancel")
});
if (res.confirmed) {
this._windowsService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
this._electronService.relaunch({ addArgs: [`--inspect-extensions=${randomPort()}`] });
}
}
@@ -609,7 +611,7 @@ export class SaveExtensionHostProfileAction extends Action {
constructor(
id: string = SaveExtensionHostProfileAction.ID, label: string = SaveExtensionHostProfileAction.LABEL,
@IWindowService private readonly _windowService: IWindowService,
@IElectronService private readonly _electronService: IElectronService,
@IEnvironmentService private readonly _environmentService: IEnvironmentService,
@IExtensionHostProfileService private readonly _extensionHostProfileService: IExtensionHostProfileService,
) {
@@ -624,7 +626,7 @@ export class SaveExtensionHostProfileAction extends Action {
}
private async _asyncRun(): Promise<any> {
let picked = await this._windowService.showSaveDialog({
let picked = await this._electronService.showSaveDialog({
title: 'Save Extension Host Profile',
buttonLabel: 'Save',
defaultPath: `CPU-${new Date().toISOString().replace(/[\-:]/g, '')}.cpuprofile`,
@@ -634,13 +636,15 @@ export class SaveExtensionHostProfileAction extends Action {
}]
});
if (!picked) {
if (!picked || !picked.filePath || picked.canceled) {
return;
}
const profileInfo = this._extensionHostProfileService.lastProfile;
let dataToWrite: object = profileInfo ? profileInfo.data : {};
let savePath = picked.filePath;
if (this._environmentService.isBuilt) {
const profiler = await import('v8-inspect-profiler');
// when running from a not-development-build we remove
@@ -651,9 +655,9 @@ export class SaveExtensionHostProfileAction extends Action {
let tmp = profiler.rewriteAbsolutePaths({ profile: dataToWrite as any }, 'piiRemoved');
dataToWrite = tmp.profile;
picked = picked + '.txt';
savePath = savePath + '.txt';
}
return writeFile(picked, JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'));
return writeFile(savePath, JSON.stringify(profileInfo ? profileInfo.data : {}, null, '\t'));
}
}

View File

@@ -1465,7 +1465,7 @@ suite('ExtensionsActions Test', () => {
assert.equal(testObject.tooltip, 'Please reload Azure Data Studio to enable this extension.'); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
});
test('Test ReloadAction when ui extension is disabled on remote server and installed in local server', async () => {
test('Test ReloadAction is disabled when remote ui extension is installed in local server', async () => {
// multi server setup
const gallery = aGalleryExtension('a');
const localExtensionManagementService = createExtensionManagementService([]);
@@ -1480,7 +1480,7 @@ suite('ExtensionsActions Test', () => {
const onDidChangeExtensionsEmitter: Emitter<void> = new Emitter<void>();
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{
getExtensions: () => Promise.resolve([]),
getExtensions: () => Promise.resolve([ExtensionsActions.toExtensionDescription(remoteExtension)]),
onDidChangeExtensions: onDidChangeExtensionsEmitter.event,
canAddExtension: (extension) => false
});
@@ -1497,8 +1497,69 @@ suite('ExtensionsActions Test', () => {
const localExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a') });
onDidInstallEvent.fire({ identifier: localExtension.identifier, local: localExtension, operation: InstallOperation.Install });
assert.ok(testObject.enabled);
assert.equal(testObject.tooltip, 'Please reload Azure Data Studio to enable this extension.'); // {{SQL CARBON EDIT}} - replace Visual Studio Code with Azure Data Studio
assert.ok(!testObject.enabled);
});
test('Test ReloadAction for remote ui extension is disabled when it is installed and enabled in local server', async () => {
// multi server setup
const gallery = aGalleryExtension('a');
const localExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a') });
const localExtensionManagementService = createExtensionManagementService([localExtension]);
const onDidInstallEvent = new Emitter<DidInstallExtensionEvent>();
localExtensionManagementService.onDidInstallExtension = onDidInstallEvent.event;
const remoteExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a').with({ scheme: Schemas.vscodeRemote }) });
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, localExtensionManagementService, createExtensionManagementService([remoteExtension]));
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
const workbenchService: IExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
instantiationService.set(IExtensionsWorkbenchService, workbenchService);
const onDidChangeExtensionsEmitter: Emitter<void> = new Emitter<void>();
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{
getExtensions: () => Promise.resolve([ExtensionsActions.toExtensionDescription(localExtension)]),
onDidChangeExtensions: onDidChangeExtensionsEmitter.event,
canAddExtension: (extension) => false
});
const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction);
instantiationService.createInstance(ExtensionContainers, [testObject]);
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
await workbenchService.queryGallery(CancellationToken.None);
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
testObject.extension = extensions[0];
assert.ok(testObject.extension);
assert.ok(!testObject.enabled);
});
test('Test ReloadAction for local ui extension is disabled when it is installed and enabled in remote server', async () => {
// multi server setup
const gallery = aGalleryExtension('a');
const localExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a') });
const localExtensionManagementService = createExtensionManagementService([localExtension]);
const onDidInstallEvent = new Emitter<DidInstallExtensionEvent>();
localExtensionManagementService.onDidInstallExtension = onDidInstallEvent.event;
const remoteExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file('pub.a').with({ scheme: Schemas.vscodeRemote }) });
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, localExtensionManagementService, createExtensionManagementService([remoteExtension]));
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
const workbenchService: IExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
instantiationService.set(IExtensionsWorkbenchService, workbenchService);
const onDidChangeExtensionsEmitter: Emitter<void> = new Emitter<void>();
instantiationService.stub(IExtensionService, <Partial<IExtensionService>>{
getExtensions: () => Promise.resolve([ExtensionsActions.toExtensionDescription(remoteExtension)]),
onDidChangeExtensions: onDidChangeExtensionsEmitter.event,
canAddExtension: (extension) => false
});
const testObject: ExtensionsActions.ReloadAction = instantiationService.createInstance(ExtensionsActions.ReloadAction);
instantiationService.createInstance(ExtensionContainers, [testObject]);
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
await workbenchService.queryGallery(CancellationToken.None);
const extensions = await workbenchService.queryLocal(extensionManagementServerService.localExtensionManagementServer!);
testObject.extension = extensions[0];
assert.ok(testObject.extension);
assert.ok(!testObject.enabled);
});
test('Test remote install action is enabled for local workspace extension', async () => {
@@ -1854,7 +1915,7 @@ suite('ExtensionsActions Test', () => {
assert.ok(!testObject.enabled);
});
test('Test local install action is enabled for remote ui extension', async () => {
test('Test local install action is disabled for remote ui extension', async () => {
// multi server setup
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteUIExtension]));
@@ -1870,9 +1931,7 @@ suite('ExtensionsActions Test', () => {
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
await workbenchService.queryGallery(CancellationToken.None);
testObject.extension = extensions[0];
assert.ok(testObject.enabled);
assert.equal('Install Locally', testObject.label);
assert.equal('extension-action prominent install', testObject.class);
assert.ok(!testObject.enabled);
});
test('Test local install action when installing remote ui extension', async () => {
@@ -1896,54 +1955,10 @@ suite('ExtensionsActions Test', () => {
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
await workbenchService.queryGallery(CancellationToken.None);
testObject.extension = extensions[0];
assert.ok(testObject.enabled);
assert.equal('Install Locally', testObject.label);
assert.equal('extension-action prominent install', testObject.class);
onInstallExtension.fire({ identifier: remoteUIExtension.identifier, gallery });
assert.ok(testObject.enabled);
assert.equal('Installing', testObject.label);
assert.equal('extension-action install installing', testObject.class);
});
test('Test local install action when installing remote ui extension is finished', async () => {
// multi server setup
const localExtensionManagementService: IExtensionManagementService = createExtensionManagementService();
const onInstallExtension = new Emitter<InstallExtensionEvent>();
localExtensionManagementService.onInstallExtension = onInstallExtension.event;
const onDidInstallEvent = new Emitter<DidInstallExtensionEvent>();
localExtensionManagementService.onDidInstallExtension = onDidInstallEvent.event;
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, localExtensionManagementService, createExtensionManagementService([remoteUIExtension]));
instantiationService.stub(IExtensionManagementServerService, extensionManagementServerService);
instantiationService.stub(IExtensionEnablementService, new TestExtensionEnablementService(instantiationService));
const workbenchService: IExtensionsWorkbenchService = instantiationService.createInstance(ExtensionsWorkbenchService);
instantiationService.stub(IExtensionsWorkbenchService, workbenchService, 'open', undefined);
instantiationService.set(IExtensionsWorkbenchService, workbenchService);
const gallery = aGalleryExtension('a', { identifier: remoteUIExtension.identifier });
instantiationService.stubPromise(IExtensionGalleryService, 'query', aPage(gallery));
const testObject: ExtensionsActions.InstallAction = instantiationService.createInstance(ExtensionsActions.LocalInstallAction);
instantiationService.createInstance(ExtensionContainers, [testObject]);
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
await workbenchService.queryGallery(CancellationToken.None);
testObject.extension = extensions[0];
assert.ok(testObject.enabled);
assert.equal('Install Locally', testObject.label);
assert.equal('extension-action prominent install', testObject.class);
onInstallExtension.fire({ identifier: remoteUIExtension.identifier, gallery });
assert.ok(testObject.enabled);
assert.equal('Installing', testObject.label);
assert.equal('extension-action install installing', testObject.class);
const installedExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`) });
onDidInstallEvent.fire({ identifier: installedExtension.identifier, local: installedExtension, operation: InstallOperation.Install });
assert.ok(!testObject.enabled);
});
test('Test local install action is enabled for disabled remote ui extension', async () => {
test('Test local install action is disabled for disabled remote ui extension', async () => {
// multi server setup
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteUIExtension]));
@@ -1960,9 +1975,7 @@ suite('ExtensionsActions Test', () => {
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
await workbenchService.queryGallery(CancellationToken.None);
testObject.extension = extensions[0];
assert.ok(testObject.enabled);
assert.equal('Install Locally', testObject.label);
assert.equal('extension-action prominent install', testObject.class);
assert.ok(!testObject.enabled);
});
test('Test local install action is disabled when extension is not set', async () => {
@@ -2062,7 +2075,7 @@ suite('ExtensionsActions Test', () => {
assert.ok(!testObject.enabled);
});
test('Test local install action is disabled for remoteUI extension if it is uninstalled locally', async () => {
test('Test local install action is disabled for remote UI extension if it uninstalled locally', async () => {
// multi server setup
const extensionManagementService = instantiationService.get(IExtensionManagementService);
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), extensionManagementService);
@@ -2080,14 +2093,13 @@ suite('ExtensionsActions Test', () => {
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
await workbenchService.queryGallery(CancellationToken.None);
testObject.extension = extensions[0];
assert.ok(testObject.enabled);
assert.equal('Install Locally', testObject.label);
assert.ok(!testObject.enabled);
uninstallEvent.fire(remoteUIExtension.identifier);
assert.ok(!testObject.enabled);
});
test('Test local install action is enabled for remote UI extension if it has gallery', async () => {
test('Test local install action is disabled for remote UI extension if it has gallery', async () => {
// multi server setup
const remoteUIExtension = aLocalExtension('a', { extensionKind: 'ui' }, { location: URI.file(`pub.a`).with({ scheme: Schemas.vscodeRemote }) });
const extensionManagementServerService = aMultiExtensionManagementServerService(instantiationService, createExtensionManagementService(), createExtensionManagementService([remoteUIExtension]));
@@ -2103,7 +2115,7 @@ suite('ExtensionsActions Test', () => {
const extensions = await workbenchService.queryLocal(extensionManagementServerService.remoteExtensionManagementServer!);
testObject.extension = extensions[0];
assert.ok(testObject.extension);
assert.ok(testObject.enabled);
assert.ok(!testObject.enabled);
});
test('Test local install action is disabled for remote UI system extension', async () => {