mirror of
https://github.com/Microsoft/vscode
synced 2024-10-12 14:30:13 +00:00
create workspace extension config service
This commit is contained in:
parent
1fd7ee15d3
commit
f57ac767b7
|
@ -6,7 +6,7 @@
|
|||
import { IExtensionTipsService, IConfigBasedExtensionTip } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
|
||||
import { localize } from 'vs/nls';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IWorkspaceContextService, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ import { isNonEmptyArray } from 'vs/base/common/arrays';
|
|||
import { IWorkspaceTagsService } from 'vs/workbench/contrib/tags/common/workspaceTags';
|
||||
import { isNumber } from 'vs/base/common/types';
|
||||
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { localize } from 'vs/nls';
|
||||
|
||||
type DynamicWorkspaceRecommendationsClassification = {
|
||||
|
|
|
@ -10,7 +10,7 @@ import { timeout } from 'vs/base/common/async';
|
|||
import { localize } from 'vs/nls';
|
||||
import { optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ITASExperimentService } from 'vs/workbench/services/experiment/common/experimentService';
|
||||
|
||||
type ExeExtensionRecommendationsClassification = {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { isNonEmptyArray } from 'vs/base/common/arrays';
|
||||
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IExperimentService, ExperimentActionType, ExperimentState } from 'vs/workbench/contrib/experiments/common/experimentService';
|
||||
|
||||
export class ExperimentalRecommendations extends ExtensionRecommendations {
|
||||
|
|
|
@ -19,7 +19,7 @@ import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
|||
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IExtensionManifest, IKeyBinding, IView, IViewContainer, ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { ResolvedKeybinding, KeyMod, KeyCode } from 'vs/base/common/keyCodes';
|
||||
import { ExtensionsInput } from 'vs/workbench/contrib/extensions/common/extensionsInput';
|
||||
|
|
|
@ -9,7 +9,8 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
|||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { localize } from 'vs/nls';
|
||||
import { SearchExtensionsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { EnablementState, ExtensionRecommendationSource, IExtensionRecommendationReson, IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { EnablementState, IWorkbenchExtensionEnablementService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationSource, IExtensionRecommendationReson } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IExtensionsConfiguration, ConfigurationKey, IExtension, IExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { IConfigurationService, ConfigurationTarget } from 'vs/platform/configuration/common/configuration';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, InstallOperation, DidInstallExtensionEvent } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService, ExtensionRecommendationReason, RecommendationChangeNotification, IExtensionRecommendation, ExtensionRecommendationSource } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService, ExtensionRecommendationReason, RecommendationChangeNotification, IExtensionRecommendation, ExtensionRecommendationSource } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IStorageService, StorageScope, IWorkspaceStorageChangeEvent } from 'vs/platform/storage/common/storage';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { ShowRecommendationsOnlyOnDemandKey } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
|
|
|
@ -9,7 +9,8 @@ import { Registry } from 'vs/platform/registry/common/platform';
|
|||
import { MenuRegistry, MenuId, registerAction2, Action2 } from 'vs/platform/actions/common/actions';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { ExtensionsLabel, ExtensionsLocalizedLabel, ExtensionsChannelId, IExtensionManagementService, IExtensionGalleryService, PreferencesLocalizedLabel } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServerService, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions, IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { IOutputChannelRegistry, Extensions as OutputExtensions } from 'vs/workbench/services/output/common/output';
|
||||
import { SyncDescriptor } from 'vs/platform/instantiation/common/descriptors';
|
||||
|
|
|
@ -12,10 +12,11 @@ import { Event } from 'vs/base/common/event';
|
|||
import * as json from 'vs/base/common/json';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { dispose, Disposable } from 'vs/base/common/lifecycle';
|
||||
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, AutoUpdateConfigurationKey, IExtensionContainer, EXTENSIONS_CONFIG, TOGGLE_IGNORE_EXTENSION_ACTION_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { IExtension, ExtensionState, IExtensionsWorkbenchService, VIEWLET_ID, IExtensionsViewPaneContainer, AutoUpdateConfigurationKey, IExtensionContainer, TOGGLE_IGNORE_EXTENSION_ACTION_ID } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { ExtensionsConfigurationInitialContent } from 'vs/workbench/contrib/extensions/common/extensionsFileTemplate';
|
||||
import { IGalleryExtension, IExtensionGalleryService, INSTALL_ERROR_MALICIOUS, INSTALL_ERROR_INCOMPATIBLE, IGalleryExtensionVersion, ILocalExtension, INSTALL_ERROR_NOT_SUPPORTED } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionRecommendationsService, IExtensionsConfigContent, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService, IExtensionsConfigContent } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { ExtensionType, ExtensionIdentifier, IExtensionDescription, IExtensionManifest, isLanguagePackExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
@ -60,6 +61,7 @@ import { IProgressService, ProgressLocation } from 'vs/platform/progress/common/
|
|||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { IViewsService } from 'vs/workbench/common/views';
|
||||
import { IActionViewItemOptions, ActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { EXTENSIONS_CONFIG } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig';
|
||||
|
||||
export function toExtensionDescription(local: ILocalExtension): IExtensionDescription {
|
||||
return {
|
||||
|
|
|
@ -9,7 +9,8 @@ import { Event, Emitter } from 'vs/base/common/event';
|
|||
import { isPromiseCanceledError, getErrorMessage } from 'vs/base/common/errors';
|
||||
import { PagedModel, IPagedModel, IPager, DelayedPagedModel } from 'vs/base/common/paging';
|
||||
import { SortBy, SortOrder, IQueryOptions, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService, IExtensionRecommendationsService, IExtensionRecommendation, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService, IExtensionRecommendation } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
|
|
|
@ -9,7 +9,8 @@ import { IExtension, IExtensionsWorkbenchService, IExtensionContainer } from 'vs
|
|||
import { append, $ } from 'vs/base/browser/dom';
|
||||
import * as platform from 'vs/base/common/platform';
|
||||
import { localize } from 'vs/nls';
|
||||
import { IExtensionRecommendationsService, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ILabelService } from 'vs/platform/label/common/label';
|
||||
import { extensionButtonProminentBackground, extensionButtonProminentForeground, ExtensionToolTipAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
|
||||
import { IThemeService, IColorTheme } from 'vs/platform/theme/common/themeService';
|
||||
|
|
|
@ -6,7 +6,8 @@
|
|||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
|
||||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { ExtensionRecommendationSource, ExtensionRecommendationReason, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationSource, ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { IExtensionsViewPaneContainer, IExtensionsWorkbenchService, IExtension } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { localize } from 'vs/nls';
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
|
||||
import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
|
||||
export class KeymapRecommendations extends ExtensionRecommendations {
|
||||
|
||||
|
|
|
@ -4,18 +4,16 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { EXTENSION_IDENTIFIER_PATTERN, IExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkspaceContextService, IWorkspaceFolder, IWorkspace, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { distinct, flatten, coalesce } from 'vs/base/common/arrays';
|
||||
import { IWorkspaceContextService, IWorkspaceFoldersChangeEvent } from 'vs/platform/workspace/common/workspace';
|
||||
import { distinct, flatten } from 'vs/base/common/arrays';
|
||||
import { ExtensionRecommendations, ExtensionRecommendation, PromptedExtensionRecommendations } from 'vs/workbench/contrib/extensions/browser/extensionRecommendations';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { IExtensionsConfigContent, ExtensionRecommendationSource, ExtensionRecommendationReason } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import { EXTENSIONS_CONFIG } from 'vs/workbench/contrib/extensions/common/extensions';
|
||||
import { IExtensionsConfigContent, ExtensionRecommendationReason } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { localize } from 'vs/nls';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { IWorkpsaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig';
|
||||
|
||||
export class WorkspaceRecommendations extends ExtensionRecommendations {
|
||||
|
||||
|
@ -31,9 +29,9 @@ export class WorkspaceRecommendations extends ExtensionRecommendations {
|
|||
constructor(
|
||||
promptedExtensionRecommendations: PromptedExtensionRecommendations,
|
||||
@IWorkspaceContextService private readonly contextService: IWorkspaceContextService,
|
||||
@IWorkpsaceExtensionsConfigService private readonly workpsaceExtensionsConfigService: IWorkpsaceExtensionsConfigService,
|
||||
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
|
||||
@ILogService private readonly logService: ILogService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
) {
|
||||
super(promptedExtensionRecommendations);
|
||||
|
@ -49,26 +47,26 @@ export class WorkspaceRecommendations extends ExtensionRecommendations {
|
|||
*/
|
||||
private async fetch(): Promise<void> {
|
||||
|
||||
const extensionsConfigBySource = await this.fetchExtensionsConfigBySource();
|
||||
const extensionsConfigs = await this.workpsaceExtensionsConfigService.getExtensionsConfigs();
|
||||
|
||||
const { invalidRecommendations, message } = await this.validateExtensions(extensionsConfigBySource.map(({ contents }) => contents));
|
||||
const { invalidRecommendations, message } = await this.validateExtensions(extensionsConfigs);
|
||||
if (invalidRecommendations.length) {
|
||||
this.notificationService.warn(`The ${invalidRecommendations.length} extension(s) below, in workspace recommendations have issues:\n${message}`);
|
||||
}
|
||||
|
||||
this._ignoredRecommendations = [];
|
||||
|
||||
for (const extensionsConfig of extensionsConfigBySource) {
|
||||
for (const unwantedRecommendation of extensionsConfig.contents.unwantedRecommendations) {
|
||||
for (const extensionsConfig of extensionsConfigs) {
|
||||
for (const unwantedRecommendation of extensionsConfig.unwantedRecommendations) {
|
||||
if (invalidRecommendations.indexOf(unwantedRecommendation) === -1) {
|
||||
this._ignoredRecommendations.push(unwantedRecommendation);
|
||||
}
|
||||
}
|
||||
for (const extensionId of extensionsConfig.contents.recommendations) {
|
||||
for (const extensionId of extensionsConfig.recommendations) {
|
||||
if (invalidRecommendations.indexOf(extensionId) === -1) {
|
||||
this._recommendations.push({
|
||||
extensionId,
|
||||
source: extensionsConfig.source,
|
||||
source: this.contextService.getWorkspace(),
|
||||
reason: {
|
||||
reasonId: ExtensionRecommendationReason.Workspace,
|
||||
reasonText: localize('workspaceRecommendation', "This extension is recommended by users of the current workspace.")
|
||||
|
@ -79,41 +77,6 @@ export class WorkspaceRecommendations extends ExtensionRecommendations {
|
|||
}
|
||||
}
|
||||
|
||||
private async fetchExtensionsConfigBySource(): Promise<{ contents: IExtensionsConfigContent, source: ExtensionRecommendationSource }[]> {
|
||||
const workspace = this.contextService.getWorkspace();
|
||||
const result = await Promise.all([
|
||||
this.resolveWorkspaceExtensionConfig(workspace),
|
||||
...workspace.folders.map(workspaceFolder => this.resolveWorkspaceFolderExtensionConfig(workspaceFolder))
|
||||
]);
|
||||
return coalesce(result);
|
||||
}
|
||||
|
||||
private async resolveWorkspaceExtensionConfig(workspace: IWorkspace): Promise<{ contents: IExtensionsConfigContent, source: ExtensionRecommendationSource } | null> {
|
||||
try {
|
||||
if (workspace.configuration) {
|
||||
const content = await this.fileService.readFile(workspace.configuration);
|
||||
const extensionsConfigContent = <IExtensionsConfigContent | undefined>parse(content.value.toString())['extensions'];
|
||||
const contents = this.parseExtensionConfig(extensionsConfigContent);
|
||||
if (contents) {
|
||||
return { contents, source: workspace };
|
||||
}
|
||||
}
|
||||
} catch (e) { /* Ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
private async resolveWorkspaceFolderExtensionConfig(workspaceFolder: IWorkspaceFolder): Promise<{ contents: IExtensionsConfigContent, source: ExtensionRecommendationSource } | null> {
|
||||
try {
|
||||
const content = await this.fileService.readFile(workspaceFolder.toResource(EXTENSIONS_CONFIG));
|
||||
const extensionsConfigContent = <IExtensionsConfigContent>parse(content.value.toString());
|
||||
const contents = this.parseExtensionConfig(extensionsConfigContent);
|
||||
if (contents) {
|
||||
return { contents, source: workspaceFolder };
|
||||
}
|
||||
} catch (e) { /* ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
private async validateExtensions(contents: IExtensionsConfigContent[]): Promise<{ validRecommendations: string[], invalidRecommendations: string[], message: string }> {
|
||||
|
||||
const validExtensions: string[] = [];
|
||||
|
@ -165,15 +128,5 @@ export class WorkspaceRecommendations extends ExtensionRecommendations {
|
|||
}
|
||||
}
|
||||
|
||||
private parseExtensionConfig(extensionsConfigContent: IExtensionsConfigContent | undefined): IExtensionsConfigContent | null {
|
||||
if (extensionsConfigContent) {
|
||||
return {
|
||||
recommendations: distinct((extensionsConfigContent.recommendations || []).map(e => e.toLowerCase())),
|
||||
unwantedRecommendations: distinct((extensionsConfigContent.unwantedRecommendations || []).map(e => e.toLowerCase()))
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,6 @@ import { IViewPaneContainer } from 'vs/workbench/common/views';
|
|||
|
||||
export const VIEWLET_ID = 'workbench.view.extensions';
|
||||
|
||||
export const EXTENSIONS_CONFIG = '.vscode/extensions.json';
|
||||
|
||||
export interface IExtensionsViewPaneContainer extends IViewPaneContainer {
|
||||
search(text: string, refresh?: boolean): void;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,8 @@ import { onUnexpectedError } from 'vs/base/common/errors';
|
|||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { IExtensionManagementService, ILocalExtension, IExtensionIdentifier, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IWorkbenchContribution } from 'vs/workbench/common/contributions';
|
||||
import { ServicesAccessor, IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
|
|
|
@ -58,6 +58,7 @@ import { IWorkspaceTagsService } from 'vs/workbench/contrib/tags/common/workspac
|
|||
import { IStorageKeysSyncRegistryService, StorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
import { ExtensionsWorkbenchService } from 'vs/workbench/contrib/extensions/browser/extensionsWorkbenchService';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { IWorkpsaceExtensionsConfigService, WorkspaceExtensionsConfigService } from 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig';
|
||||
|
||||
const mockExtensionGallery: IGalleryExtension[] = [
|
||||
aGalleryExtension('MockExtension1', {
|
||||
|
@ -301,6 +302,7 @@ suite('ExtensionRecommendationsService Test', () => {
|
|||
const myWorkspace = testWorkspace(URI.from({ scheme: 'file', path: folderDir }));
|
||||
workspaceService = new TestContextService(myWorkspace);
|
||||
instantiationService.stub(IWorkspaceContextService, workspaceService);
|
||||
instantiationService.stub(IWorkpsaceExtensionsConfigService, instantiationService.createInstance(WorkspaceExtensionsConfigService));
|
||||
const fileService = new FileService(new NullLogService());
|
||||
fileService.registerProvider(Schemas.file, new DiskFileSystemProvider(new NullLogService()));
|
||||
instantiationService.stub(IFileService, fileService);
|
||||
|
|
|
@ -12,7 +12,8 @@ import {
|
|||
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension,
|
||||
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, InstallOperation, IExtensionTipsService, IGalleryMetadata
|
||||
} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
|
||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||
|
|
|
@ -13,7 +13,8 @@ import {
|
|||
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension, IQueryOptions,
|
||||
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IExtensionIdentifier, SortBy
|
||||
} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer, IExtensionRecommendationsService, ExtensionRecommendationReason, IExtensionRecommendation } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService, ExtensionRecommendationReason, IExtensionRecommendation } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
|
||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||
|
|
|
@ -13,7 +13,8 @@ import {
|
|||
IExtensionManagementService, IExtensionGalleryService, ILocalExtension, IGalleryExtension,
|
||||
DidInstallExtensionEvent, DidUninstallExtensionEvent, InstallExtensionEvent, IGalleryExtensionAssets, IExtensionIdentifier, InstallOperation, IExtensionTipsService, IGalleryMetadata
|
||||
} from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionRecommendationsService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionManagementServerService, IExtensionManagementServer } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { TestExtensionEnablementService } from 'vs/workbench/services/extensionManagement/test/browser/extensionEnablementService.test';
|
||||
import { ExtensionGalleryService } from 'vs/platform/extensionManagement/common/extensionGalleryService';
|
||||
|
|
|
@ -23,7 +23,8 @@ import { Schemas } from 'vs/base/common/network';
|
|||
import { IBackupFileService } from 'vs/workbench/services/backup/common/backup';
|
||||
import { getInstalledExtensions, IExtensionStatus, onExtensionChanged, isKeymapExtension } from 'vs/workbench/contrib/extensions/common/extensionsUtils';
|
||||
import { IExtensionManagementService, IExtensionGalleryService, ILocalExtension } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState, IExtensionRecommendationsService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IWorkbenchExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionRecommendationsService } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ILifecycleService, StartupKind } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { splitName } from 'vs/base/common/labels';
|
||||
|
|
|
@ -38,7 +38,8 @@ import { isWindows, OS } from 'vs/base/common/platform';
|
|||
import { IWebviewService, WebviewContentOptions, WebviewElement, WebviewExtensionDescription, WebviewIcons, WebviewOptions, WebviewOverlay } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { ITextFileService } from 'vs/workbench/services/textfile/common/textfiles';
|
||||
import { AbstractTextFileService } from 'vs/workbench/services/textfile/browser/textFileService';
|
||||
import { ExtensionRecommendationReason, IExtensionManagementServer, IExtensionManagementServerService, IExtensionRecommendation } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionManagementServer, IExtensionManagementServerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { ExtensionRecommendationReason, IExtensionRecommendation } from 'vs/workbench/services/extensionRecommendations/common/extensionRecommendations';
|
||||
import { ITunnelProvider, ITunnelService, RemoteTunnel } from 'vs/platform/remote/common/tunnel';
|
||||
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { IManualSyncTask, IResourcePreview, ISyncResourceHandle, ISyncTask, IUserDataAutoSyncService, IUserDataSyncService, IUserDataSyncStore, IUserDataSyncStoreManagementService, SyncResource, SyncStatus, UserDataSyncStoreType } from 'vs/platform/userDataSync/common/userDataSync';
|
||||
|
|
|
@ -5,11 +5,8 @@
|
|||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IExtension, IScannedExtension, ExtensionType, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions';
|
||||
import { IExtensionManagementService, IGalleryExtension, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IWorkspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
|
||||
export const IExtensionManagementServerService = createDecorator<IExtensionManagementServerService>('extensionManagementServerService');
|
||||
|
||||
|
@ -88,63 +85,6 @@ export interface IWorkbenchExtensionEnablementService {
|
|||
setEnablement(extensions: IExtension[], state: EnablementState): Promise<boolean[]>;
|
||||
}
|
||||
|
||||
export interface IExtensionsConfigContent {
|
||||
recommendations: string[];
|
||||
unwantedRecommendations: string[];
|
||||
}
|
||||
|
||||
export type RecommendationChangeNotification = {
|
||||
extensionId: string,
|
||||
isRecommended: boolean
|
||||
};
|
||||
|
||||
export type DynamicRecommendation = 'dynamic';
|
||||
export type ConfigRecommendation = 'config';
|
||||
export type ExecutableRecommendation = 'executable';
|
||||
export type CachedRecommendation = 'cached';
|
||||
export type ApplicationRecommendation = 'application';
|
||||
export type ExperimentalRecommendation = 'experimental';
|
||||
export type ExtensionRecommendationSource = IWorkspace | IWorkspaceFolder | URI | DynamicRecommendation | ExecutableRecommendation | CachedRecommendation | ApplicationRecommendation | ExperimentalRecommendation | ConfigRecommendation;
|
||||
|
||||
export interface IExtensionRecommendation {
|
||||
extensionId: string;
|
||||
sources: ExtensionRecommendationSource[];
|
||||
}
|
||||
|
||||
export const enum ExtensionRecommendationReason {
|
||||
Workspace,
|
||||
File,
|
||||
Executable,
|
||||
WorkspaceConfig,
|
||||
DynamicWorkspace,
|
||||
Experimental,
|
||||
Application,
|
||||
}
|
||||
|
||||
export interface IExtensionRecommendationReson {
|
||||
reasonId: ExtensionRecommendationReason;
|
||||
reasonText: string;
|
||||
}
|
||||
|
||||
export const IExtensionRecommendationsService = createDecorator<IExtensionRecommendationsService>('extensionRecommendationsService');
|
||||
|
||||
export interface IExtensionRecommendationsService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
getAllRecommendationsWithReason(): IStringDictionary<IExtensionRecommendationReson>;
|
||||
getImportantRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getOtherRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getFileBasedRecommendations(): IExtensionRecommendation[];
|
||||
getExeBasedRecommendations(exe?: string): Promise<{ important: IExtensionRecommendation[], others: IExtensionRecommendation[] }>;
|
||||
getConfigBasedRecommendations(): Promise<{ important: IExtensionRecommendation[], others: IExtensionRecommendation[] }>;
|
||||
getWorkspaceRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getKeymapRecommendations(): IExtensionRecommendation[];
|
||||
|
||||
toggleIgnoredRecommendation(extensionId: string, shouldIgnore: boolean): void;
|
||||
getIgnoredRecommendations(): ReadonlyArray<string>;
|
||||
onRecommendationChange: Event<RecommendationChangeNotification>;
|
||||
}
|
||||
|
||||
export const IWebExtensionsScannerService = createDecorator<IWebExtensionsScannerService>('IWebExtensionsScannerService');
|
||||
export interface IWebExtensionsScannerService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IWorkspace, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { IStringDictionary } from 'vs/base/common/collections';
|
||||
|
||||
export interface IExtensionsConfigContent {
|
||||
recommendations: string[];
|
||||
unwantedRecommendations: string[];
|
||||
}
|
||||
|
||||
export type RecommendationChangeNotification = {
|
||||
extensionId: string,
|
||||
isRecommended: boolean
|
||||
};
|
||||
|
||||
export type DynamicRecommendation = 'dynamic';
|
||||
export type ConfigRecommendation = 'config';
|
||||
export type ExecutableRecommendation = 'executable';
|
||||
export type CachedRecommendation = 'cached';
|
||||
export type ApplicationRecommendation = 'application';
|
||||
export type ExperimentalRecommendation = 'experimental';
|
||||
export type ExtensionRecommendationSource = IWorkspace | IWorkspaceFolder | URI | DynamicRecommendation | ExecutableRecommendation | CachedRecommendation | ApplicationRecommendation | ExperimentalRecommendation | ConfigRecommendation;
|
||||
|
||||
export interface IExtensionRecommendation {
|
||||
extensionId: string;
|
||||
sources: ExtensionRecommendationSource[];
|
||||
}
|
||||
|
||||
export const enum ExtensionRecommendationReason {
|
||||
Workspace,
|
||||
File,
|
||||
Executable,
|
||||
WorkspaceConfig,
|
||||
DynamicWorkspace,
|
||||
Experimental,
|
||||
Application,
|
||||
}
|
||||
|
||||
export interface IExtensionRecommendationReson {
|
||||
reasonId: ExtensionRecommendationReason;
|
||||
reasonText: string;
|
||||
}
|
||||
|
||||
export const IExtensionRecommendationsService = createDecorator<IExtensionRecommendationsService>('extensionRecommendationsService');
|
||||
|
||||
export interface IExtensionRecommendationsService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
getAllRecommendationsWithReason(): IStringDictionary<IExtensionRecommendationReson>;
|
||||
getImportantRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getOtherRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getFileBasedRecommendations(): IExtensionRecommendation[];
|
||||
getExeBasedRecommendations(exe?: string): Promise<{ important: IExtensionRecommendation[], others: IExtensionRecommendation[] }>;
|
||||
getConfigBasedRecommendations(): Promise<{ important: IExtensionRecommendation[], others: IExtensionRecommendation[] }>;
|
||||
getWorkspaceRecommendations(): Promise<IExtensionRecommendation[]>;
|
||||
getKeymapRecommendations(): IExtensionRecommendation[];
|
||||
|
||||
toggleIgnoredRecommendation(extensionId: string, shouldIgnore: boolean): void;
|
||||
getIgnoredRecommendations(): ReadonlyArray<string>;
|
||||
onRecommendationChange: Event<RecommendationChangeNotification>;
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { coalesce, distinct, flatten } from 'vs/base/common/arrays';
|
||||
import { parse } from 'vs/base/common/json';
|
||||
import { IFileService } from 'vs/platform/files/common/files';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IWorkspace, IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
|
||||
export const EXTENSIONS_CONFIG = '.vscode/extensions.json';
|
||||
|
||||
export interface IExtensionsConfigContent {
|
||||
recommendations: string[];
|
||||
unwantedRecommendations: string[];
|
||||
}
|
||||
|
||||
export const IWorkpsaceExtensionsConfigService = createDecorator<IWorkpsaceExtensionsConfigService>('IWorkpsaceExtensionsConfigService');
|
||||
|
||||
export interface IWorkpsaceExtensionsConfigService {
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
getExtensionsConfigs(): Promise<IExtensionsConfigContent[]>;
|
||||
getUnwantedRecommendations(): Promise<string[]>;
|
||||
|
||||
}
|
||||
|
||||
export class WorkspaceExtensionsConfigService implements IWorkpsaceExtensionsConfigService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
constructor(
|
||||
@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,
|
||||
@IFileService private readonly fileService: IFileService,
|
||||
) { }
|
||||
|
||||
async getExtensionsConfigs(): Promise<IExtensionsConfigContent[]> {
|
||||
const workspace = this.workspaceContextService.getWorkspace();
|
||||
const result = await Promise.all([
|
||||
this.resolveWorkspaceExtensionConfig(workspace),
|
||||
...workspace.folders.map(workspaceFolder => this.resolveWorkspaceFolderExtensionConfig(workspaceFolder))
|
||||
]);
|
||||
return coalesce(result);
|
||||
}
|
||||
|
||||
async getUnwantedRecommendations(): Promise<string[]> {
|
||||
const configs = await this.getExtensionsConfigs();
|
||||
return distinct(flatten(configs.map(c => c.unwantedRecommendations)));
|
||||
}
|
||||
|
||||
private async resolveWorkspaceExtensionConfig(workspace: IWorkspace): Promise<IExtensionsConfigContent | null> {
|
||||
try {
|
||||
if (workspace.configuration) {
|
||||
const content = await this.fileService.readFile(workspace.configuration);
|
||||
const extensionsConfigContent = <IExtensionsConfigContent | undefined>parse(content.value.toString())['extensions'];
|
||||
return this.parseExtensionConfig(extensionsConfigContent);
|
||||
}
|
||||
} catch (e) { /* Ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
private async resolveWorkspaceFolderExtensionConfig(workspaceFolder: IWorkspaceFolder): Promise<IExtensionsConfigContent | null> {
|
||||
try {
|
||||
const content = await this.fileService.readFile(workspaceFolder.toResource(EXTENSIONS_CONFIG));
|
||||
const extensionsConfigContent = <IExtensionsConfigContent>parse(content.value.toString());
|
||||
return this.parseExtensionConfig(extensionsConfigContent);
|
||||
} catch (e) { /* ignore */ }
|
||||
return null;
|
||||
}
|
||||
|
||||
private parseExtensionConfig(extensionsConfigContent: IExtensionsConfigContent | undefined): IExtensionsConfigContent | null {
|
||||
if (extensionsConfigContent) {
|
||||
return {
|
||||
recommendations: distinct((extensionsConfigContent.recommendations || []).map(e => e.toLowerCase())),
|
||||
unwantedRecommendations: distinct((extensionsConfigContent.unwantedRecommendations || []).map(e => e.toLowerCase()))
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
registerSingleton(IWorkpsaceExtensionsConfigService, WorkspaceExtensionsConfigService);
|
|
@ -75,6 +75,7 @@ import 'vs/workbench/services/label/common/labelService';
|
|||
import 'vs/workbench/services/extensionManagement/common/webExtensionsScannerService';
|
||||
import 'vs/workbench/services/extensionManagement/common/extensionEnablementService';
|
||||
import 'vs/workbench/services/extensionManagement/browser/builtinExtensionsScannerService';
|
||||
import 'vs/workbench/services/extensionRecommendations/common/workspaceExtensionsConfig';
|
||||
import 'vs/workbench/services/notification/common/notificationService';
|
||||
import 'vs/workbench/services/userDataSync/common/userDataSyncUtil';
|
||||
import 'vs/workbench/services/remote/common/remoteExplorerService';
|
||||
|
|
Loading…
Reference in a new issue