Path: blob/main/src/vs/workbench/contrib/extensions/browser/configBasedRecommendations.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { IExtensionTipsService, IConfigBasedExtensionTip } from '../../../../platform/extensionManagement/common/extensionManagement.js';6import { ExtensionRecommendations, ExtensionRecommendation } from './extensionRecommendations.js';7import { localize } from '../../../../nls.js';8import { ExtensionRecommendationReason } from '../../../services/extensionRecommendations/common/extensionRecommendations.js';9import { IWorkspaceContextService, IWorkspaceFoldersChangeEvent } from '../../../../platform/workspace/common/workspace.js';10import { Emitter } from '../../../../base/common/event.js';1112type ConfigBasedExtensionRecommendation = ExtensionRecommendation & { whenNotInstalled: string[] | undefined };1314export class ConfigBasedRecommendations extends ExtensionRecommendations {1516private importantTips: IConfigBasedExtensionTip[] = [];17private otherTips: IConfigBasedExtensionTip[] = [];1819private _onDidChangeRecommendations = this._register(new Emitter<void>());20readonly onDidChangeRecommendations = this._onDidChangeRecommendations.event;2122private _otherRecommendations: ConfigBasedExtensionRecommendation[] = [];23get otherRecommendations(): ReadonlyArray<ConfigBasedExtensionRecommendation> { return this._otherRecommendations; }2425private _importantRecommendations: ConfigBasedExtensionRecommendation[] = [];26get importantRecommendations(): ReadonlyArray<ConfigBasedExtensionRecommendation> { return this._importantRecommendations; }2728get recommendations(): ReadonlyArray<ConfigBasedExtensionRecommendation> { return [...this.importantRecommendations, ...this.otherRecommendations]; }2930constructor(31@IExtensionTipsService private readonly extensionTipsService: IExtensionTipsService,32@IWorkspaceContextService private readonly workspaceContextService: IWorkspaceContextService,33) {34super();35}3637protected async doActivate(): Promise<void> {38await this.fetch();39this._register(this.workspaceContextService.onDidChangeWorkspaceFolders(e => this.onWorkspaceFoldersChanged(e)));40}4142private async fetch(): Promise<void> {43const workspace = this.workspaceContextService.getWorkspace();44const importantTips: Map<string, IConfigBasedExtensionTip> = new Map<string, IConfigBasedExtensionTip>();45const otherTips: Map<string, IConfigBasedExtensionTip> = new Map<string, IConfigBasedExtensionTip>();46for (const folder of workspace.folders) {47const configBasedTips = await this.extensionTipsService.getConfigBasedTips(folder.uri);48for (const tip of configBasedTips) {49if (tip.important) {50importantTips.set(tip.extensionId, tip);51} else {52otherTips.set(tip.extensionId, tip);53}54}55}56this.importantTips = [...importantTips.values()];57this.otherTips = [...otherTips.values()].filter(tip => !importantTips.has(tip.extensionId));58this._otherRecommendations = this.otherTips.map(tip => this.toExtensionRecommendation(tip));59this._importantRecommendations = this.importantTips.map(tip => this.toExtensionRecommendation(tip));60}6162private async onWorkspaceFoldersChanged(event: IWorkspaceFoldersChangeEvent): Promise<void> {63if (event.added.length) {64const oldImportantRecommended = this.importantTips;65await this.fetch();66// Suggest only if at least one of the newly added recommendations was not suggested before67if (this.importantTips.some(current => oldImportantRecommended.every(old => current.extensionId !== old.extensionId))) {68this._onDidChangeRecommendations.fire();69}70}71}7273private toExtensionRecommendation(tip: IConfigBasedExtensionTip): ConfigBasedExtensionRecommendation {74return {75extension: tip.extensionId,76reason: {77reasonId: ExtensionRecommendationReason.WorkspaceConfig,78reasonText: localize('exeBasedRecommendation', "This extension is recommended because of the current workspace configuration")79},80whenNotInstalled: tip.whenNotInstalled81};82}8384}858687