Merge from vscode 2e5312cd61ff99c570299ecc122c52584265eda2

This commit is contained in:
ADS Merger
2020-04-23 02:50:35 +00:00
committed by Anthony Dresser
parent 3603f55d97
commit 7f1d8fc32f
659 changed files with 22709 additions and 12497 deletions

View File

@@ -0,0 +1,133 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Disposable } from 'vs/base/common/lifecycle';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
import { localize } from 'vs/nls';
import { InstallRecommendedExtensionAction, ShowRecommendedExtensionsAction } from 'vs/workbench/contrib/extensions/browser/extensionsActions';
import { ExtensionRecommendationSource, IExtensionRecommendationReson } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { IExtensionsConfiguration, ConfigurationKey } 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';
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
type ExtensionRecommendationsNotificationClassification = {
userReaction: { classification: 'SystemMetaData', purpose: 'FeatureInsight' };
extensionId: { classification: 'PublicNonPersonalData', purpose: 'FeatureInsight' };
};
const ignoreImportantExtensionRecommendation = 'extensionsAssistant/importantRecommendationsIgnore';
const choiceNever = localize('neverShowAgain', "Don't Show Again");
export type ExtensionRecommendation = {
readonly extensionId: string,
readonly source: ExtensionRecommendationSource;
readonly reason: IExtensionRecommendationReson;
};
export abstract class ExtensionRecommendations extends Disposable {
readonly abstract recommendations: ReadonlyArray<ExtensionRecommendation>;
protected abstract doActivate(): Promise<void>;
constructor(
protected readonly isExtensionAllowedToBeRecommended: (extensionId: string) => boolean,
@IInstantiationService protected readonly instantiationService: IInstantiationService,
@IConfigurationService protected readonly configurationService: IConfigurationService,
@INotificationService protected readonly notificationService: INotificationService,
@ITelemetryService protected readonly telemetryService: ITelemetryService,
@IStorageService protected readonly storageService: IStorageService,
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
) {
super();
storageKeysSyncRegistryService.registerStorageKey({ key: ignoreImportantExtensionRecommendation, version: 1 });
}
private _activationPromise: Promise<void> | null = null;
get activated(): boolean { return this._activationPromise !== null; }
activate(): Promise<void> {
if (!this._activationPromise) {
this._activationPromise = this.doActivate();
}
return this._activationPromise;
}
protected promptImportantExtensionInstallNotification(extensionId: string, message: string): void {
this.notificationService.prompt(Severity.Info, message,
[{
label: localize('install', 'Install'),
run: () => {
this.telemetryService.publicLog2<{ userReaction: string, extensionId: string }, ExtensionRecommendationsNotificationClassification>('extensionRecommendations:popup', { userReaction: 'install', extensionId });
this.instantiationService.createInstance(InstallRecommendedExtensionAction, extensionId).run();
}
}, {
label: localize('showRecommendations', "Show Recommendations"),
run: () => {
this.telemetryService.publicLog2<{ userReaction: string, extensionId: string }, ExtensionRecommendationsNotificationClassification>('extensionRecommendations:popup', { userReaction: 'show', extensionId });
const recommendationsAction = this.instantiationService.createInstance(ShowRecommendedExtensionsAction, ShowRecommendedExtensionsAction.ID, localize('showRecommendations', "Show Recommendations"));
recommendationsAction.run();
recommendationsAction.dispose();
}
}, {
label: choiceNever,
isSecondary: true,
run: () => {
this.addToImportantRecommendationsIgnore(extensionId);
this.telemetryService.publicLog2<{ userReaction: string, extensionId: string }, ExtensionRecommendationsNotificationClassification>('extensionRecommendations:popup', { userReaction: 'neverShowAgain', extensionId });
this.notificationService.prompt(
Severity.Info,
localize('ignoreExtensionRecommendations', "Do you want to ignore all extension recommendations?"),
[{
label: localize('ignoreAll', "Yes, Ignore All"),
run: () => this.setIgnoreRecommendationsConfig(true)
}, {
label: localize('no', "No"),
run: () => this.setIgnoreRecommendationsConfig(false)
}]
);
}
}],
{
sticky: true,
onCancel: () => {
this.telemetryService.publicLog2<{ userReaction: string, extensionId: string }, ExtensionRecommendationsNotificationClassification>('extensionRecommendations:popup', { userReaction: 'cancelled', extensionId });
}
}
);
}
protected hasToIgnoreRecommendationNotifications(): boolean {
const config = this.configurationService.getValue<IExtensionsConfiguration>(ConfigurationKey);
return config.ignoreRecommendations || config.showRecommendationsOnlyOnDemand;
}
protected filterIgnoredOrNotAllowed(recommendationsToSuggest: string[]): string[] {
const importantRecommendationsIgnoreList = (<string[]>JSON.parse(this.storageService.get(ignoreImportantExtensionRecommendation, StorageScope.GLOBAL, '[]'))).map(e => e.toLowerCase());
return recommendationsToSuggest.filter(id => {
if (importantRecommendationsIgnoreList.indexOf(id) !== -1) {
return false;
}
if (!this.isExtensionAllowedToBeRecommended(id)) {
return false;
}
return true;
});
}
private addToImportantRecommendationsIgnore(id: string) {
const importantRecommendationsIgnoreList = <string[]>JSON.parse(this.storageService.get(ignoreImportantExtensionRecommendation, StorageScope.GLOBAL, '[]'));
importantRecommendationsIgnoreList.push(id.toLowerCase());
this.storageService.store(ignoreImportantExtensionRecommendation, JSON.stringify(importantRecommendationsIgnoreList), StorageScope.GLOBAL);
}
private setIgnoreRecommendationsConfig(configVal: boolean) {
this.configurationService.updateValue('extensions.ignoreRecommendations', configVal, ConfigurationTarget.USER);
}
}