mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-03-30 00:30:29 -04:00
Merge from vscode 81d7885dc2e9dc617e1522697a2966bc4025a45d (#5949)
* Merge from vscode 81d7885dc2e9dc617e1522697a2966bc4025a45d * Fix vs unit tests and hygiene issue * Fix strict null check issue
This commit is contained in:
@@ -255,7 +255,7 @@ export class ExtensionData implements IExtensionData {
|
||||
toQuery.push(id);
|
||||
}
|
||||
}
|
||||
const galleryResult = await this.extensionsWorkbenchService.queryGallery({ names: this.childrenExtensionIds, pageSize: this.childrenExtensionIds.length }, CancellationToken.None);
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -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[]> {
|
||||
|
||||
@@ -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 { IDisposable, dispose, toDisposable, Disposable } 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';
|
||||
@@ -89,9 +89,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 +99,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 {
|
||||
@@ -132,10 +133,6 @@ class NavBar {
|
||||
this.actions.forEach(a => a.enabled = a.id !== id);
|
||||
return Promise.resolve(undefined);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
dispose(this.actionbar);
|
||||
}
|
||||
}
|
||||
|
||||
const NavbarSection = {
|
||||
|
||||
@@ -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, IDisposable, toDisposable } 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 profilingStatusBarIndicatorLabelUpdater: IDisposable | undefined;
|
||||
|
||||
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,48 @@ 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 {
|
||||
if (this.profilingStatusBarIndicatorLabelUpdater) {
|
||||
this.profilingStatusBarIndicatorLabelUpdater.dispose();
|
||||
this.profilingStatusBarIndicatorLabelUpdater = undefined;
|
||||
}
|
||||
|
||||
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 = 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 +172,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)
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ 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';
|
||||
@@ -90,7 +90,7 @@ export class ExtensionTipsService extends Disposable implements IExtensionTipsSe
|
||||
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;
|
||||
|
||||
@@ -597,8 +597,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,231 +610,244 @@ 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(() => {
|
||||
|
||||
let recommendationsToSuggest: string[] = [];
|
||||
const now = Date.now();
|
||||
forEach(this._availableRecommendations, entry => {
|
||||
let { key: pattern, value: ids } = entry;
|
||||
if (match(pattern, 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);
|
||||
}
|
||||
this._fileBasedRecommendations[id.toLowerCase()] = filedBasedRecommendation;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.storageService.store(
|
||||
'extensionsAssistant/recommendations',
|
||||
JSON.stringify(Object.keys(this._fileBasedRecommendations).reduce((result, key) => { result[key] = this._fileBasedRecommendations[key].recommendedTime; return result; }, {})),
|
||||
StorageScope.GLOBAL
|
||||
);
|
||||
|
||||
const config = this.configurationService.getValue<IExtensionsConfiguration>(ConfigurationKey);
|
||||
if (config.ignoreRecommendations || config.showRecommendationsOnlyOnDemand) {
|
||||
// re-schedule this bit of the operation to be off the critical path - in case glob-match is slow
|
||||
setImmediate(async () => {
|
||||
const installed = await this.extensionManagementService.getInstalled(ExtensionType.User);
|
||||
if (await this.promptRecommendedExtensionForFileType(model, installed)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const importantRecommendationsIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/importantRecommendationsIgnore', StorageScope.GLOBAL, '[]'));
|
||||
recommendationsToSuggest = recommendationsToSuggest.filter(id => importantRecommendationsIgnoreList.indexOf(id) === -1 && this.isExtensionAllowedToBeRecommended(id));
|
||||
if (fileExtension) {
|
||||
fileExtension = fileExtension.substr(1); // Strip the dot
|
||||
}
|
||||
if (!fileExtension) {
|
||||
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'];
|
||||
await this.extensionService.whenInstalledExtensionsRegistered();
|
||||
const mimeTypes = await guessMimeTypes(uri.fsPath);
|
||||
if (mimeTypes.length !== 1 || mimeTypes[0] !== MIME_UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Indicates we have a suggested extension via the whitelist
|
||||
hasSuggestion = true;
|
||||
this.promptRecommendedExtensionForFileExtension(fileExtension, installed);
|
||||
});
|
||||
}
|
||||
|
||||
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);
|
||||
private async promptRecommendedExtensionForFileType(model: ITextModel, installed: ILocalExtension[]): Promise<boolean> {
|
||||
let recommendationsToSuggest: string[] = [];
|
||||
const now = Date.now();
|
||||
forEach(this._availableRecommendations, entry => {
|
||||
let { key: pattern, value: ids } = entry;
|
||||
if (match(pattern, model.uri.path)) {
|
||||
for (let id of ids) {
|
||||
if (caseInsensitiveGet(product.extensionImportantTips, id)) {
|
||||
recommendationsToSuggest.push(id);
|
||||
}
|
||||
};
|
||||
|
||||
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 filedBasedRecommendation = this._fileBasedRecommendations[id.toLowerCase()] || { recommendedTime: now, sources: [] };
|
||||
filedBasedRecommendation.recommendedTime = now;
|
||||
if (!filedBasedRecommendation.sources.some(s => s instanceof URI && s.toString() === model.uri.toString())) {
|
||||
filedBasedRecommendation.sources.push(model.uri);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
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._fileBasedRecommendations[id.toLowerCase()] = filedBasedRecommendation;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (hasSuggestion ||
|
||||
!fileExtension ||
|
||||
mimeTypes.length !== 1 ||
|
||||
mimeTypes[0] !== MIME_UNKNOWN ||
|
||||
fileExtensionSuggestionIgnoreList.indexOf(fileExtension) > -1
|
||||
) {
|
||||
return;
|
||||
}
|
||||
this.storageService.store(
|
||||
'extensionsAssistant/recommendations',
|
||||
JSON.stringify(Object.keys(this._fileBasedRecommendations).reduce((result, key) => { result[key] = this._fileBasedRecommendations[key].recommendedTime; return result; }, {})),
|
||||
StorageScope.GLOBAL
|
||||
);
|
||||
|
||||
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;
|
||||
const config = this.configurationService.getValue<IExtensionsConfiguration>(ConfigurationKey);
|
||||
if (config.ignoreRecommendations || config.showRecommendationsOnlyOnDemand) {
|
||||
return false;
|
||||
}
|
||||
|
||||
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.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('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
|
||||
@@ -1001,8 +1012,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 });
|
||||
|
||||
@@ -50,6 +50,7 @@ import { ExtensionsAutoProfiler } from 'vs/workbench/contrib/extensions/electron
|
||||
import { onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { ExtensionDependencyChecker } from 'vs/workbench/contrib/extensions/electron-browser/extensionsDependencyChecker';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
|
||||
// Singletons
|
||||
registerSingleton(IExtensionsWorkbenchService, ExtensionsWorkbenchService);
|
||||
@@ -421,3 +422,34 @@ 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -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';
|
||||
@@ -58,10 +58,11 @@ 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';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
@@ -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 {
|
||||
@@ -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 {
|
||||
@@ -688,8 +668,6 @@ export class ExtensionActionViewItem extends ActionViewItem {
|
||||
|
||||
export abstract class ExtensionDropDownAction extends ExtensionAction {
|
||||
|
||||
protected disposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@@ -713,17 +691,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 +723,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 {
|
||||
@@ -1208,8 +1174,6 @@ 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,
|
||||
@@ -1220,7 +1184,7 @@ export class UpdateAllAction extends Action {
|
||||
) {
|
||||
super(id, label, '', false);
|
||||
|
||||
this.disposables.push(this.extensionsWorkbenchService.onChange(() => this.update()));
|
||||
this._register(this.extensionsWorkbenchService.onChange(() => this.update()));
|
||||
this.update();
|
||||
}
|
||||
|
||||
@@ -1243,11 +1207,6 @@ export class UpdateAllAction extends Action {
|
||||
return promptDownloadManually(extension.gallery, localize('failedToUpdate', "Failed to update \'{0}\'.", extension.identifier.id), err, this.instantiationService, this.notificationService, this.openerService);
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
||||
|
||||
export class ReloadAction extends ExtensionAction {
|
||||
@@ -1256,7 +1215,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 +1224,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();
|
||||
}
|
||||
|
||||
@@ -1350,7 +1309,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 +1342,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 +1353,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 +1362,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 +1408,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 +1415,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 +1428,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 +1474,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 +1571,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 +1580,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 +1595,6 @@ export class ClearExtensionsInputAction extends Action {
|
||||
viewlet.focus();
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
||||
|
||||
export class ShowBuiltInExtensionsAction extends Action {
|
||||
@@ -1772,7 +1708,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 +1736,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) {
|
||||
@@ -1862,7 +1799,6 @@ export class IgnoreExtensionRecommendationAction extends Action {
|
||||
|
||||
private static readonly Class = 'extension-action ignore';
|
||||
|
||||
private disposables: IDisposable[] = [];
|
||||
extension: IExtension;
|
||||
|
||||
constructor(
|
||||
@@ -1879,11 +1815,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 +1823,6 @@ export class UndoIgnoreExtensionRecommendationAction extends Action {
|
||||
|
||||
private static readonly Class = 'extension-action undo-ignore';
|
||||
|
||||
private disposables: IDisposable[] = [];
|
||||
extension: IExtension;
|
||||
|
||||
constructor(
|
||||
@@ -1909,11 +1839,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 +1914,6 @@ export class ShowAzureExtensionsAction extends Action {
|
||||
export class ChangeSortAction extends Action {
|
||||
|
||||
private query: Query;
|
||||
private disposables: IDisposable[] = [];
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
@@ -2006,7 +1930,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 +2235,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 +2247,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 +2264,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 +2271,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 +2284,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 +2303,6 @@ export class ConfigureWorkspaceFolderRecommendedExtensionsAction extends Abstrac
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables = dispose(this.disposables);
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
export class AddToWorkspaceFolderRecommendationsAction extends AbstractConfigureRecommendedExtensionsAction {
|
||||
@@ -2679,7 +2591,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 +2599,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();
|
||||
}
|
||||
|
||||
@@ -2722,11 +2633,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 +2642,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();
|
||||
}
|
||||
@@ -2785,7 +2691,7 @@ export class SystemDisabledWarningAction extends ExtensionAction {
|
||||
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 +2703,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 +2726,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 +2733,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 +2741,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 +2751,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 +2758,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 +2766,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 +2777,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 +2784,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 +2792,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 +2802,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 +2809,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 +2818,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 +2829,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 {
|
||||
|
||||
@@ -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,
|
||||
) {
|
||||
|
||||
|
||||
@@ -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';
|
||||
@@ -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);
|
||||
|
||||
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;
|
||||
|
||||
@@ -28,7 +28,7 @@ import { IExtensionManagementService, IExtensionManagementServerService, IExtens
|
||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||
import { ExtensionsListView, EnabledExtensionsView, DisabledExtensionsView, RecommendedExtensionsView, WorkspaceRecommendedExtensionsView, BuiltInExtensionsView, BuiltInThemesExtensionsView, BuiltInBasicsExtensionsView, ServerExtensionsView, DefaultRecommendedExtensionsView } from './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;
|
||||
@@ -343,12 +344,12 @@ export class ExtensionsViewlet extends ViewContainerViewlet implements IExtensio
|
||||
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,
|
||||
|
||||
@@ -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';
|
||||
@@ -24,14 +24,13 @@ 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 { 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';
|
||||
@@ -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>> {
|
||||
@@ -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>> {
|
||||
@@ -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;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,22 +81,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 {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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; }
|
||||
}
|
||||
|
||||
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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 |
@@ -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,7 +17,7 @@ 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';
|
||||
@@ -29,13 +29,14 @@ 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';
|
||||
|
||||
// {{SQL CARBON EDIT}}
|
||||
import { isEngineValid } from 'vs/platform/extensions/node/extensionValidator';
|
||||
@@ -497,7 +498,6 @@ 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; }
|
||||
@@ -516,10 +516,11 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
||||
@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
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@IModeService private readonly modeService: IModeService
|
||||
) {
|
||||
super();
|
||||
this.localExtensions = this._register(instantiationService.createInstance(Extensions, extensionManagementServerService.localExtensionManagementServer));
|
||||
@@ -536,7 +537,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 +549,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
||||
this.checkForUpdates();
|
||||
}
|
||||
}
|
||||
}, this, this.disposables);
|
||||
}, this));
|
||||
|
||||
this.queryLocal().then(() => {
|
||||
this.resetIgnoreAutoUpdateExtensions();
|
||||
@@ -602,6 +603,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 +620,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 = 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}"`;
|
||||
});
|
||||
}
|
||||
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));
|
||||
}
|
||||
@@ -1116,7 +1139,7 @@ export class ExtensionsWorkbenchService extends Disposable implements IExtension
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
this.syncDelayer.cancel();
|
||||
this.disposables = dispose(this.disposables);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +113,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 };
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user