Refresh master with initial release/0.24 snapshot (#332)

* Initial port of release/0.24 source code

* Fix additional headers

* Fix a typo in launch.json
This commit is contained in:
Karl Burtram
2017-12-15 15:38:57 -08:00
committed by GitHub
parent 271b3a0b82
commit 6ad0df0e3e
7118 changed files with 107999 additions and 56466 deletions

View File

@@ -5,16 +5,16 @@
import { localize } from 'vs/nls';
import { TPromise } from 'vs/base/common/winjs.base';
import { distinct } from 'vs/base/common/arrays';
import { distinct, coalesce } from 'vs/base/common/arrays';
import Event, { Emitter } from 'vs/base/common/event';
import { IDisposable, dispose } from 'vs/base/common/lifecycle';
import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { adoptToGalleryExtensionId, getIdAndVersionFromLocalExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
import { IExtensionManagementService, DidUninstallExtensionEvent, IExtensionEnablementService, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
import { adoptToGalleryExtensionId, getIdAndVersionFromLocalExtensionId, areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
const DISABLED_EXTENSIONS_STORAGE_PATH = 'extensions/disabled';
const DISABLED_EXTENSIONS_STORAGE_PATH = 'extensionsIdentifiers/disabled';
export class ExtensionEnablementService implements IExtensionEnablementService {
@@ -22,8 +22,8 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
private disposables: IDisposable[] = [];
private _onEnablementChanged = new Emitter<string>();
public onEnablementChanged: Event<string> = this._onEnablementChanged.event;
private _onEnablementChanged = new Emitter<IExtensionIdentifier>();
public onEnablementChanged: Event<IExtensionIdentifier> = this._onEnablementChanged.event;
constructor(
@IStorageService private storageService: IStorageService,
@@ -35,31 +35,31 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
}
private get hasWorkspace(): boolean {
return this.contextService.hasWorkspace();
return this.contextService.getWorkbenchState() !== WorkbenchState.EMPTY;
}
public getGloballyDisabledExtensions(): string[] {
getGloballyDisabledExtensions(): IExtensionIdentifier[] {
return this.getDisabledExtensions(StorageScope.GLOBAL);
}
public getWorkspaceDisabledExtensions(): string[] {
getWorkspaceDisabledExtensions(): IExtensionIdentifier[] {
return this.getDisabledExtensions(StorageScope.WORKSPACE);
}
public canEnable(identifier: string): boolean {
canEnable(identifier: IExtensionIdentifier): boolean {
if (this.environmentService.disableExtensions) {
return false;
}
if (this.getGloballyDisabledExtensions().indexOf(identifier) !== -1) {
if (this.getGloballyDisabledExtensions().some(d => areSameExtensions(d, identifier))) {
return true;
}
if (this.getWorkspaceDisabledExtensions().indexOf(identifier) !== -1) {
if (this.getWorkspaceDisabledExtensions().some(d => areSameExtensions(d, identifier))) {
return true;
}
return false;
}
public setEnablement(identifier: string, enable: boolean, workspace: boolean = false): TPromise<boolean> {
setEnablement(identifier: IExtensionIdentifier, enable: boolean, workspace: boolean = false): TPromise<boolean> {
if (workspace && !this.hasWorkspace) {
return TPromise.wrapError<boolean>(new Error(localize('noWorkspace', "No workspace.")));
}
@@ -83,10 +83,16 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
}
}
private disableExtension(identifier: string, scope: StorageScope): TPromise<boolean> {
migrateToIdentifiers(installed: IExtensionIdentifier[]): void {
this.migrateDisabledExtensions(installed, StorageScope.GLOBAL);
if (this.hasWorkspace) {
this.migrateDisabledExtensions(installed, StorageScope.WORKSPACE);
}
}
private disableExtension(identifier: IExtensionIdentifier, scope: StorageScope): TPromise<boolean> {
let disabledExtensions = this.getDisabledExtensions(scope);
const index = disabledExtensions.indexOf(identifier);
if (index === -1) {
if (disabledExtensions.every(e => !areSameExtensions(e, identifier))) {
disabledExtensions.push(identifier);
this.setDisabledExtensions(disabledExtensions, scope, identifier);
return TPromise.wrap(true);
@@ -94,28 +100,30 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
return TPromise.wrap(false);
}
private enableExtension(identifier: string, scope: StorageScope, fireEvent = true): TPromise<boolean> {
private enableExtension(identifier: IExtensionIdentifier, scope: StorageScope, fireEvent = true): TPromise<boolean> {
let disabledExtensions = this.getDisabledExtensions(scope);
const index = disabledExtensions.indexOf(identifier);
if (index !== -1) {
disabledExtensions.splice(index, 1);
this.setDisabledExtensions(disabledExtensions, scope, identifier, fireEvent);
return TPromise.wrap(true);
for (let index = 0; index < disabledExtensions.length; index++) {
const disabledExtension = disabledExtensions[index];
if (areSameExtensions(disabledExtension, identifier)) {
disabledExtensions.splice(index, 1);
this.setDisabledExtensions(disabledExtensions, scope, identifier, fireEvent);
return TPromise.wrap(true);
}
}
return TPromise.wrap(false);
}
private getDisabledExtensions(scope: StorageScope): string[] {
private getDisabledExtensions(scope: StorageScope): IExtensionIdentifier[] {
if (scope === StorageScope.WORKSPACE && !this.hasWorkspace) {
return [];
}
const value = this.storageService.get(DISABLED_EXTENSIONS_STORAGE_PATH, scope, '');
return value ? distinct(value.split(',')).map(id => adoptToGalleryExtensionId(id)) : [];
return value ? JSON.parse(value) : [];
}
private setDisabledExtensions(disabledExtensions: string[], scope: StorageScope, extension: string, fireEvent = true): void {
private setDisabledExtensions(disabledExtensions: IExtensionIdentifier[], scope: StorageScope, extension: IExtensionIdentifier, fireEvent = true): void {
if (disabledExtensions.length) {
this.storageService.store(DISABLED_EXTENSIONS_STORAGE_PATH, disabledExtensions.join(','), scope);
this.storageService.store(DISABLED_EXTENSIONS_STORAGE_PATH, JSON.stringify(disabledExtensions.map(({ id, uuid }) => (<IExtensionIdentifier>{ id, uuid }))), scope);
} else {
this.storageService.remove(DISABLED_EXTENSIONS_STORAGE_PATH, scope);
}
@@ -124,12 +132,28 @@ export class ExtensionEnablementService implements IExtensionEnablementService {
}
}
private onDidUninstallExtension({ id, error }: DidUninstallExtensionEvent): void {
private migrateDisabledExtensions(installedExtensions: IExtensionIdentifier[], scope: StorageScope): void {
const oldValue = this.storageService.get('extensions/disabled', scope, '');
if (oldValue) {
const extensionIdentifiers = coalesce(distinct(oldValue.split(',')).map(id => {
id = adoptToGalleryExtensionId(id);
const matched = installedExtensions.filter(installed => areSameExtensions({ id }, { id: installed.id }))[0];
return matched ? { id: matched.id, uuid: matched.uuid } : null;
}));
if (extensionIdentifiers.length) {
this.storageService.store(DISABLED_EXTENSIONS_STORAGE_PATH, JSON.stringify(extensionIdentifiers), scope);
}
}
this.storageService.remove('extensions/disabled', scope);
}
private onDidUninstallExtension({ identifier, error }: DidUninstallExtensionEvent): void {
if (!error) {
id = getIdAndVersionFromLocalExtensionId(id).id;
const id = getIdAndVersionFromLocalExtensionId(identifier.id).id;
if (id) {
this.enableExtension(id, StorageScope.WORKSPACE, false);
this.enableExtension(id, StorageScope.GLOBAL, false);
const extension = { id, uuid: identifier.uuid };
this.enableExtension(extension, StorageScope.WORKSPACE, false);
this.enableExtension(extension, StorageScope.GLOBAL, false);
}
}
}

View File

@@ -79,6 +79,12 @@ export interface IView {
name: string;
}
export interface IColor {
id: string;
description: string;
defaults: { light: string, dark: string, highContrast: string };
}
export interface IExtensionContributions {
commands?: ICommand[];
configuration?: IConfiguration;
@@ -90,7 +96,9 @@ export interface IExtensionContributions {
menus?: { [context: string]: IMenu[] };
snippets?: ISnippet[];
themes?: ITheme[];
iconThemes?: ITheme[];
views?: { [location: string]: IView[] };
colors: IColor[];
}
export interface IExtensionManifest {
@@ -127,10 +135,14 @@ export interface IGalleryExtensionAssets {
license: IGalleryExtensionAsset;
}
export interface IGalleryExtension {
uuid: string;
export interface IExtensionIdentifier {
id: string;
uuid?: string;
}
export interface IGalleryExtension {
name: string;
identifier: IExtensionIdentifier;
version: string;
date: string;
displayName: string;
@@ -159,7 +171,7 @@ export enum LocalExtensionType {
export interface ILocalExtension {
type: LocalExtensionType;
id: string;
identifier: IExtensionIdentifier;
manifest: IExtensionManifest;
metadata: IGalleryMetadata;
path: string;
@@ -209,28 +221,28 @@ export interface IExtensionGalleryService {
reportStatistic(publisher: string, name: string, version: string, type: StatisticType): TPromise<void>;
getReadme(extension: IGalleryExtension): TPromise<string>;
getManifest(extension: IGalleryExtension): TPromise<IExtensionManifest>;
getChangelog(extension: IGalleryMetadata): TPromise<string>;
getChangelog(extension: IGalleryExtension): TPromise<string>;
loadCompatibleVersion(extension: IGalleryExtension): TPromise<IGalleryExtension>;
getAllDependencies(extension: IGalleryExtension): TPromise<IGalleryExtension[]>;
}
export interface InstallExtensionEvent {
id: string;
identifier: IExtensionIdentifier;
zipPath?: string;
gallery?: IGalleryExtension;
}
export interface DidInstallExtensionEvent {
id: string;
identifier: IExtensionIdentifier;
zipPath?: string;
gallery?: IGalleryExtension;
local?: ILocalExtension;
error?: Error;
error?: string;
}
export interface DidUninstallExtensionEvent {
id: string;
error?: Error;
identifier: IExtensionIdentifier;
error?: string;
}
export interface IExtensionManagementService {
@@ -238,13 +250,15 @@ export interface IExtensionManagementService {
onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onUninstallExtension: Event<string>;
onUninstallExtension: Event<IExtensionIdentifier>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
install(zipPath: string): TPromise<void>;
installFromGallery(extension: IGalleryExtension, promptToInstallDependencies?: boolean): TPromise<void>;
installFromGallery(extension: IGalleryExtension): TPromise<void>;
uninstall(extension: ILocalExtension, force?: boolean): TPromise<void>;
getInstalled(type?: LocalExtensionType): TPromise<ILocalExtension[]>;
updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): TPromise<ILocalExtension>;
}
export const IExtensionEnablementService = createDecorator<IExtensionEnablementService>('extensionEnablementService');
@@ -256,24 +270,24 @@ export interface IExtensionEnablementService {
/**
* Event to listen on for extension enablement changes
*/
onEnablementChanged: Event<string>;
onEnablementChanged: Event<IExtensionIdentifier>;
/**
* Returns all globally disabled extension identifiers.
* Returns an empty array if none exist.
*/
getGloballyDisabledExtensions(): string[];
getGloballyDisabledExtensions(): IExtensionIdentifier[];
/**
* Returns all workspace disabled extension identifiers.
* Returns an empty array if none exist or workspace does not exist.
*/
getWorkspaceDisabledExtensions(): string[];
getWorkspaceDisabledExtensions(): IExtensionIdentifier[];
/**
* Returns `true` if given extension can be enabled by calling `setEnablement`, otherwise false`.
*/
canEnable(identifier: string): boolean;
canEnable(identifier: IExtensionIdentifier): boolean;
/**
* Enable or disable the given extension.
@@ -284,14 +298,18 @@ export interface IExtensionEnablementService {
*
* Throws error if enablement is requested for workspace and there is no workspace
*/
setEnablement(identifier: string, enable: boolean, workspace?: boolean): TPromise<boolean>;
setEnablement(identifier: IExtensionIdentifier, enable: boolean, workspace?: boolean): TPromise<boolean>;
migrateToIdentifiers(installed: IExtensionIdentifier[]): void;
}
export const IExtensionTipsService = createDecorator<IExtensionTipsService>('extensionTipsService');
export interface IExtensionTipsService {
_serviceBrand: any;
getRecommendations(): string[];
getAllRecommendationsWithReason(): { [id: string]: string; };
getFileBasedRecommendations(): string[];
getOtherRecommendations(): string[];
getWorkspaceRecommendations(): TPromise<string[]>;
getKeymapRecommendations(): string[];
getKeywordsForExtension(extension: string): string[];

View File

@@ -7,7 +7,7 @@
import { TPromise } from 'vs/base/common/winjs.base';
import { IChannel, eventToCall, eventFromCall } from 'vs/base/parts/ipc/common/ipc';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent } from './extensionManagement';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, IGalleryExtension, LocalExtensionType, DidUninstallExtensionEvent, IExtensionIdentifier, IGalleryMetadata } from './extensionManagement';
import Event, { buffer } from 'vs/base/common/event';
export interface IExtensionManagementChannel extends IChannel {
@@ -26,7 +26,7 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel {
onInstallExtension: Event<InstallExtensionEvent>;
onDidInstallExtension: Event<DidInstallExtensionEvent>;
onUninstallExtension: Event<string>;
onUninstallExtension: Event<IExtensionIdentifier>;
onDidUninstallExtension: Event<DidUninstallExtensionEvent>;
constructor(private service: IExtensionManagementService) {
@@ -43,9 +43,10 @@ export class ExtensionManagementChannel implements IExtensionManagementChannel {
case 'event:onUninstallExtension': return eventToCall(this.onUninstallExtension);
case 'event:onDidUninstallExtension': return eventToCall(this.onDidUninstallExtension);
case 'install': return this.service.install(arg);
case 'installFromGallery': return this.service.installFromGallery(arg[0], arg[1]);
case 'installFromGallery': return this.service.installFromGallery(arg[0]);
case 'uninstall': return this.service.uninstall(arg[0], arg[1]);
case 'getInstalled': return this.service.getInstalled(arg);
case 'updateMetadata': return this.service.updateMetadata(arg[0], arg[1]);
}
return undefined;
}
@@ -63,8 +64,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
private _onDidInstallExtension = eventFromCall<DidInstallExtensionEvent>(this.channel, 'event:onDidInstallExtension');
get onDidInstallExtension(): Event<DidInstallExtensionEvent> { return this._onDidInstallExtension; }
private _onUninstallExtension = eventFromCall<string>(this.channel, 'event:onUninstallExtension');
get onUninstallExtension(): Event<string> { return this._onUninstallExtension; }
private _onUninstallExtension = eventFromCall<IExtensionIdentifier>(this.channel, 'event:onUninstallExtension');
get onUninstallExtension(): Event<IExtensionIdentifier> { return this._onUninstallExtension; }
private _onDidUninstallExtension = eventFromCall<DidUninstallExtensionEvent>(this.channel, 'event:onDidUninstallExtension');
get onDidUninstallExtension(): Event<DidUninstallExtensionEvent> { return this._onDidUninstallExtension; }
@@ -73,8 +74,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
return this.channel.call('install', zipPath);
}
installFromGallery(extension: IGalleryExtension, promptToInstallDependencies: boolean = true): TPromise<void> {
return this.channel.call('installFromGallery', [extension, promptToInstallDependencies]);
installFromGallery(extension: IGalleryExtension): TPromise<void> {
return this.channel.call('installFromGallery', [extension]);
}
uninstall(extension: ILocalExtension, force = false): TPromise<void> {
@@ -84,4 +85,8 @@ export class ExtensionManagementChannelClient implements IExtensionManagementSer
getInstalled(type: LocalExtensionType = null): TPromise<ILocalExtension[]> {
return this.channel.call('getInstalled', type);
}
updateMetadata(local: ILocalExtension, metadata: IGalleryMetadata): TPromise<ILocalExtension> {
return this.channel.call('updateMetadata', [local, metadata]);
}
}

View File

@@ -5,10 +5,13 @@
'use strict';
import { ILocalExtension, IGalleryExtension, IExtensionManifest, EXTENSION_IDENTIFIER_REGEX, IExtensionEnablementService } from 'vs/platform/extensionManagement/common/extensionManagement';
import { ILocalExtension, IGalleryExtension, EXTENSION_IDENTIFIER_REGEX, IExtensionEnablementService, IExtensionIdentifier } from 'vs/platform/extensionManagement/common/extensionManagement';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
export function areSameExtensions(a: { id: string }, b: { id: string }): boolean {
export function areSameExtensions(a: IExtensionIdentifier, b: IExtensionIdentifier): boolean {
if (a.uuid && b.uuid) {
return a.uuid === b.uuid;
}
if (a.id === b.id) {
return true;
}
@@ -19,14 +22,6 @@ export function getGalleryExtensionId(publisher: string, name: string): string {
return `${publisher}.${name.toLocaleLowerCase()}`;
}
export function getLocalExtensionIdFromGallery(extension: IGalleryExtension, version: string): string {
return getLocalExtensionId(extension.id, version);
}
export function getLocalExtensionIdFromManifest(manifest: IExtensionManifest): string {
return getLocalExtensionId(getGalleryExtensionId(manifest.publisher, manifest.name), manifest.version);
}
export function getGalleryExtensionIdFromLocal(local: ILocalExtension): string {
return getGalleryExtensionId(local.manifest.publisher, local.manifest.name);
}
@@ -46,10 +41,6 @@ export function adoptToGalleryExtensionId(id: string): string {
return id.replace(EXTENSION_IDENTIFIER_REGEX, (match, publisher: string, name: string) => getGalleryExtensionId(publisher, name));
}
function getLocalExtensionId(id: string, version: string): string {
return `${id}-${version}`;
}
export function getLocalExtensionTelemetryData(extension: ILocalExtension): any {
return {
id: getGalleryExtensionIdFromLocal(extension),
@@ -62,11 +53,26 @@ export function getLocalExtensionTelemetryData(extension: ILocalExtension): any
};
}
/* __GDPR__FRAGMENT__
"GalleryExtensionTelemetryData" : {
"id" : { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"name": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"galleryId": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"publisherId": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"publisherName": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight" },
"publisherDisplayName": { "classification": "PublicPersonalData", "purpose": "FeatureInsight" },
"dependencies": { "classification": "SystemMetaData", "purpose": "FeatureInsight" },
"${include}": [
"${GalleryExtensionTelemetryData2}"
]
}
*/
export function getGalleryExtensionTelemetryData(extension: IGalleryExtension): any {
return {
id: extension.id,
id: extension.identifier.id,
name: extension.name,
galleryId: extension.uuid,
galleryId: extension.identifier.uuid,
publisherId: extension.publisherId,
publisherName: extension.publisher,
publisherDisplayName: extension.publisherDisplayName,
@@ -87,9 +93,9 @@ export function getGloballyDisabledExtensions(extensionEnablementService: IExten
const globallyDisabled = extensionEnablementService.getGloballyDisabledExtensions();
if (!storageService.getBoolean(BetterMergeCheckKey, StorageScope.GLOBAL, false)) {
storageService.store(BetterMergeCheckKey, true);
if (globallyDisabled.indexOf(BetterMergeId) === -1 && installedExtensions.some(d => d.id === BetterMergeId)) {
globallyDisabled.push(BetterMergeId);
extensionEnablementService.setEnablement(BetterMergeId, false);
if (globallyDisabled.every(disabled => disabled.id !== BetterMergeId) && installedExtensions.some(d => d.id === BetterMergeId)) {
globallyDisabled.push({ id: BetterMergeId });
extensionEnablementService.setEnablement({ id: BetterMergeId }, false);
storageService.store(BetterMergeDisabledNowKey, true);
}
}