Merge from vscode 6268feb42ba4f2e2fa15484e88c9af60d254998c (#6530)

This commit is contained in:
Anthony Dresser
2019-07-29 21:03:02 -07:00
committed by GitHub
parent 2c8a22bb0d
commit 6db84eefa3
104 changed files with 1797 additions and 3740 deletions

View File

@@ -13,9 +13,9 @@ 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 { dispose, toDisposable, Disposable, DisposableStore } from 'vs/base/common/lifecycle';
import { dispose, toDisposable, Disposable, DisposableStore, IDisposable } 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 { append, $, addClass, removeClass, finalHandler, join, toggleClass, hide, show, addDisposableListener, EventType } from 'vs/base/browser/dom';
import { BaseEditor } from 'vs/workbench/browser/parts/editor/baseEditor';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
@@ -52,6 +52,7 @@ 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';
import { StandardKeyboardEvent } from 'vs/base/browser/keyboardEvent';
// {{SQL CARBON EDIT}}
import { renderDashboardContributions } from 'sql/workbench/parts/extensions/browser/contributionRenders';
@@ -280,6 +281,20 @@ export class ExtensionEditor extends BaseEditor {
this.content = append(body, $('.content'));
}
private onClick(element: HTMLElement, callback: () => void): IDisposable {
const disposables: DisposableStore = new DisposableStore();
disposables.add(addDisposableListener(element, EventType.CLICK, finalHandler(callback)));
disposables.add(addDisposableListener(element, EventType.KEY_UP, e => {
const keyboardEvent = new StandardKeyboardEvent(e);
if (keyboardEvent.equals(KeyCode.Space) || keyboardEvent.equals(KeyCode.Enter)) {
e.preventDefault();
e.stopPropagation();
callback();
}
}));
return disposables;
}
async setInput(input: ExtensionsInput, options: EditorOptions, token: CancellationToken): Promise<void> {
const runningExtensions = await this.extensionService.getExtensions();
const colorThemes = await this.workbenchThemeService.getColorThemes();
@@ -328,26 +343,21 @@ export class ExtensionEditor extends BaseEditor {
toggleClass(this.publisher, 'clickable', !!extension.url);
toggleClass(this.rating, 'clickable', !!extension.url);
if (extension.url) {
this.name.onclick = finalHandler(() => window.open(extension.url));
this.rating.onclick = finalHandler(() => window.open(`${extension.url}#review-details`));
this.publisher.onclick = finalHandler(() => {
this.transientDisposables.add(this.onClick(this.name, () => window.open(extension.url)));
this.transientDisposables.add(this.onClick(this.rating, () => window.open(`${extension.url}#review-details`)));
this.transientDisposables.add(this.onClick(this.publisher, () => {
this.viewletService.openViewlet(VIEWLET_ID, true)
.then(viewlet => viewlet as IExtensionsViewlet)
.then(viewlet => viewlet.search(`publisher:"${extension.publisherDisplayName}"`));
});
}));
if (extension.licenseUrl) {
this.license.onclick = finalHandler(() => window.open(extension.licenseUrl));
this.transientDisposables.add(this.onClick(this.license, () => window.open(extension.licenseUrl)));
this.license.style.display = 'initial';
} else {
this.license.onclick = null;
this.license.style.display = 'none';
}
} else {
this.name.onclick = null;
this.rating.onclick = null;
this.publisher.onclick = null;
this.license.onclick = null;
this.license.style.display = 'none';
}
@@ -362,11 +372,10 @@ export class ExtensionEditor extends BaseEditor {
// {{SQL CARBON EDIT}} - End
if (extension.repository) {
this.repository.onclick = finalHandler(() => window.open(extension.repository));
this.transientDisposables.add(this.onClick(this.repository, () => window.open(extension.repository)));
this.repository.style.display = 'initial';
}
else {
this.repository.onclick = null;
this.repository.style.display = 'none';
}
@@ -712,7 +721,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('settings', "Settings ({0})", contrib.length)),
$('summary', { tabindex: '0' }, localize('settings', "Settings ({0})", contrib.length)),
$('table', undefined,
$('tr', undefined,
$('th', undefined, localize('setting name', "Name")),
@@ -740,7 +749,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('debuggers', "Debuggers ({0})", contrib.length)),
$('summary', { tabindex: '0' }, localize('debuggers', "Debuggers ({0})", contrib.length)),
$('table', undefined,
$('tr', undefined,
$('th', undefined, localize('debugger name', "Name")),
@@ -771,7 +780,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('viewContainers', "View Containers ({0})", viewContainers.length)),
$('summary', { tabindex: '0' }, localize('viewContainers', "View Containers ({0})", viewContainers.length)),
$('table', undefined,
$('tr', undefined, $('th', undefined, localize('view container id', "ID")), $('th', undefined, localize('view container title', "Title")), $('th', undefined, localize('view container location', "Where"))),
...viewContainers.map(viewContainer => $('tr', undefined, $('td', undefined, viewContainer.id), $('td', undefined, viewContainer.title), $('td', undefined, viewContainer.location)))
@@ -797,7 +806,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('views', "Views ({0})", views.length)),
$('summary', { tabindex: '0' }, localize('views', "Views ({0})", views.length)),
$('table', undefined,
$('tr', undefined, $('th', undefined, localize('view id', "ID")), $('th', undefined, localize('view name', "Name")), $('th', undefined, localize('view location', "Where"))),
...views.map(view => $('tr', undefined, $('td', undefined, view.id), $('td', undefined, view.name), $('td', undefined, view.location)))
@@ -817,7 +826,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('localizations', "Localizations ({0})", localizations.length)),
$('summary', { tabindex: '0' }, localize('localizations', "Localizations ({0})", localizations.length)),
$('table', undefined,
$('tr', undefined, $('th', undefined, localize('localizations language id', "Language Id")), $('th', undefined, localize('localizations language name', "Language Name")), $('th', undefined, localize('localizations localized language name', "Language Name (Localized)"))),
...localizations.map(localization => $('tr', undefined, $('td', undefined, localization.languageId), $('td', undefined, localization.languageName || ''), $('td', undefined, localization.localizedLanguageName || '')))
@@ -837,7 +846,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('colorThemes', "Color Themes ({0})", contrib.length)),
$('summary', { tabindex: '0' }, localize('colorThemes', "Color Themes ({0})", contrib.length)),
$('ul', undefined, ...contrib.map(theme => $('li', undefined, theme.label)))
);
@@ -854,7 +863,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('iconThemes', "Icon Themes ({0})", contrib.length)),
$('summary', { tabindex: '0' }, localize('iconThemes', "Icon Themes ({0})", contrib.length)),
$('ul', undefined, ...contrib.map(theme => $('li', undefined, theme.label)))
);
@@ -883,7 +892,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('colors', "Colors ({0})", colors.length)),
$('summary', { tabindex: '0' }, localize('colors', "Colors ({0})", colors.length)),
$('table', undefined,
$('tr', undefined,
$('th', undefined, localize('colorId', "Id")),
@@ -916,7 +925,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('JSON Validation', "JSON Validation ({0})", contrib.length)),
$('summary', { tabindex: '0' }, localize('JSON Validation', "JSON Validation ({0})", contrib.length)),
$('table', undefined,
$('tr', undefined,
$('th', undefined, localize('fileMatch', "File Match")),
@@ -990,7 +999,7 @@ export class ExtensionEditor extends BaseEditor {
};
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('commands', "Commands ({0})", commands.length)),
$('summary', { tabindex: '0' }, localize('commands', "Commands ({0})", commands.length)),
$('table', undefined,
$('tr', undefined,
$('th', undefined, localize('command name', "Name")),
@@ -1057,7 +1066,7 @@ export class ExtensionEditor extends BaseEditor {
}
const details = $('details', { open: true, ontoggle: onDetailsToggle },
$('summary', undefined, localize('languages', "Languages ({0})", languages.length)),
$('summary', { tabindex: '0' }, localize('languages', "Languages ({0})", languages.length)),
$('table', undefined,
$('tr', undefined,
$('th', undefined, localize('language id', "ID")),

View File

@@ -10,7 +10,7 @@ import { Event, Emitter } from 'vs/base/common/event';
import { isPromiseCanceledError, getErrorMessage } from 'vs/base/common/errors';
import { PagedModel, IPagedModel, IPager, DelayedPagedModel } from 'vs/base/common/paging';
import { SortBy, SortOrder, IQueryOptions } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionManagementServer, IExtensionManagementServerService, IExtensionTipsService, IExtensionRecommendation } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IExtensionManagementServer, IExtensionManagementServerService, IExtensionTipsService, IExtensionRecommendation, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
@@ -44,11 +44,11 @@ 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 { CancelablePromise, createCancelablePromise } from 'vs/base/common/async';
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';
// {{SQL CARBON EDIT}}
import product from 'vs/platform/product/node/product';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import product from 'vs/platform/product/node/product'; // {{SQL CARBON EDIT}}
class ExtensionsViewState extends Disposable implements IExtensionsViewState {
@@ -104,8 +104,9 @@ export class ExtensionsListView extends ViewletPanel {
@IWorkbenchThemeService private readonly workbenchThemeService: IWorkbenchThemeService,
@IExtensionManagementServerService protected readonly extensionManagementServerService: IExtensionManagementServerService,
@IProductService protected readonly productService: IProductService,
@IContextKeyService contextKeyService: IContextKeyService,
) {
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService);
super({ ...(options as IViewletPanelOptions), ariaHeaderLabel: options.title }, keybindingService, contextMenuService, configurationService, contextKeyService);
this.server = options.server;
}
@@ -934,9 +935,10 @@ export class ServerExtensionsView extends ExtensionsListView {
@IExtensionsWorkbenchService extensionsWorkbenchService: IExtensionsWorkbenchService,
@IExtensionManagementServerService extensionManagementServerService: IExtensionManagementServerService,
@IProductService productService: IProductService,
@IContextKeyService contextKeyService: IContextKeyService,
) {
options.server = server;
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService);
super(options, notificationService, keybindingService, contextMenuService, instantiationService, themeService, extensionService, extensionsWorkbenchService, editorService, tipsService, telemetryService, configurationService, contextService, experimentService, workbenchThemeService, extensionManagementServerService, productService, contextKeyService);
this._register(onDidChangeTitle(title => this.updateTitle(title)));
}
@@ -1080,10 +1082,14 @@ export class WorkspaceRecommendedExtensionsView extends ExtensionsListView {
return this.tipsService.getWorkspaceRecommendations()
.then(recommendations => recommendations.filter(({ extensionId }) => {
const extension = this.extensionsWorkbenchService.local.filter(i => areSameExtensions({ id: extensionId }, i.identifier))[0];
if (!extension || !extension.local || extension.state !== ExtensionState.Installed) {
if (!extension
|| !extension.local
|| extension.state !== ExtensionState.Installed
|| extension.enablementState === EnablementState.DisabledByExtensionKind
) {
return true;
}
return isUIExtension(extension.local.manifest, this.productService, this.configurationService) ? extension.server !== this.extensionManagementServerService.localExtensionManagementServer : extension.server !== this.extensionManagementServerService.remoteExtensionManagementServer;
return false;
}));
}
}

View File

@@ -256,11 +256,8 @@
font-weight: bold;
font-size: 120%;
border-bottom: 1px solid rgba(128, 128, 128, 0.22);
padding-bottom: 6px;
}
.extension-editor > .body > .content details > summary:focus {
outline: none;
padding: 3px 6px;
line-height: 22px;
}
.extension-editor > .body > .content details > summary::-webkit-details-marker {
@@ -386,4 +383,4 @@
font-size: 90%;
font-weight: 600;
opacity: 0.6;
}
}

View File

@@ -12,12 +12,13 @@ export class Query {
}
static suggestions(query: string): string[] {
const commands = ['installed', 'outdated', 'enabled', 'disabled', 'builtin', 'recommended', 'sort', 'category', 'tag', 'ext'];
const commands = ['installed', 'outdated', 'enabled', 'disabled', 'builtin', 'recommended', 'sort', 'category', 'tag', 'ext', 'id'];
const subcommands = {
'sort': ['installs', 'rating', 'name'],
'category': ['"programming languages"', 'snippets', 'linters', 'themes', 'debuggers', 'formatters', 'keymaps', '"scm providers"', 'other', '"extension packs"', '"language packs"'],
'tag': [''],
'ext': ['']
'ext': [''],
'id': ['']
};
let queryContains = (substr: string) => query.indexOf(substr) > -1;
@@ -77,4 +78,4 @@ export class Query {
equals(other: Query): boolean {
return this.value === other.value && this.sortBy === other.sortBy;
}
}
}

View File

@@ -10,7 +10,7 @@ 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, EXTENSION_IDENTIFIER_PATTERN, InstallOperation, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IExtensionTipsService, ExtensionRecommendationReason, IExtensionsConfigContent, RecommendationChangeNotification, IExtensionRecommendation, ExtensionRecommendationSource } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IExtensionTipsService, ExtensionRecommendationReason, IExtensionsConfigContent, RecommendationChangeNotification, IExtensionRecommendation, ExtensionRecommendationSource, IExtensionEnablementService, EnablementState } from 'vs/workbench/services/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';
@@ -101,6 +101,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
@IModelService private readonly _modelService: IModelService,
@IStorageService private readonly storageService: IStorageService,
@IExtensionManagementService private readonly extensionsService: IExtensionManagementService,
@IExtensionEnablementService private readonly extensionEnablementService: IExtensionEnablementService,
@IInstantiationService private readonly instantiationService: IInstantiationService,
@IFileService private readonly fileService: IFileService,
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
@@ -433,6 +434,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
}
this.extensionsService.getInstalled(ExtensionType.User).then(local => {
local = local.filter(l => this.extensionEnablementService.getEnablementState(l) !== EnablementState.DisabledByExtensionKind); // Filter extensions disabled by kind
const recommendations = filteredRecs.filter(({ extensionId }) => local.every(local => !areSameExtensions({ id: extensionId }, local.identifier)));
if (!recommendations.length) {

View File

@@ -44,6 +44,8 @@ import { ISharedProcessService } from 'vs/platform/ipc/electron-browser/sharedPr
import { ExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/electron-browser/extensionManagementServerService';
import { IProductService } from 'vs/platform/product/common/product';
import { ILabelService } from 'vs/platform/label/common/label';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { MockContextKeyService } from 'vs/platform/keybinding/test/common/mockKeybindingService';
suite('ExtensionsListView Tests', () => {
@@ -93,6 +95,7 @@ suite('ExtensionsListView Tests', () => {
instantiationService.stub(IExtensionManagementService, 'onUninstallExtension', uninstallEvent.event);
instantiationService.stub(IExtensionManagementService, 'onDidUninstallExtension', didUninstallEvent.event);
instantiationService.stub(IRemoteAgentService, RemoteAgentService);
instantiationService.stub(IContextKeyService, MockContextKeyService);
instantiationService.stub(IExtensionManagementServerService, new class extends ExtensionManagementServerService {
private _localExtensionManagementServer: IExtensionManagementServer = { extensionManagementService: instantiationService.get(IExtensionManagementService), label: 'local', authority: 'vscode-local' };