Merge from vscode cfbd1999769f4f08dce29629fb92fdc0fac53829

This commit is contained in:
ADS Merger
2020-08-06 07:08:52 +00:00
parent 9c67832880
commit 540046ba00
362 changed files with 7588 additions and 6584 deletions

View File

@@ -12,11 +12,11 @@ import { URI } from 'vs/base/common/uri';
import { getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
interface IScannedBuiltinExtension {
extensionPath: string,
packageJSON: IExtensionManifest,
packageNLSPath?: string,
readmePath?: string,
changelogPath?: string,
extensionPath: string;
packageJSON: IExtensionManifest;
packageNLS?: any;
readmePath?: string;
changelogPath?: string;
}
export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScannerService {
@@ -54,7 +54,7 @@ export class BuiltinExtensionsScannerService implements IBuiltinExtensionsScanne
location: uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.extensionPath),
type: ExtensionType.System,
packageJSON: e.packageJSON,
packageNLSUrl: e.packageNLSPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.packageNLSPath) : undefined,
packageNLS: e.packageNLS,
readmeUrl: e.readmePath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.readmePath) : undefined,
changelogUrl: e.changelogPath ? uriIdentityService.extUri.joinPath(builtinExtensionsServiceUrl!, e.changelogPath) : undefined,
}));

View File

@@ -6,7 +6,7 @@
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 } from 'vs/platform/extensions/common/extensions';
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';
@@ -128,6 +128,7 @@ export interface IExtensionRecommendationsService {
getAllRecommendationsWithReason(): IStringDictionary<IExtensionRecommendationReson>;
getFileBasedRecommendations(): IExtensionRecommendation[];
getImportantRecommendations(): Promise<IExtensionRecommendation[]>;
getConfigBasedRecommendations(): Promise<IExtensionRecommendation[]>;
getOtherRecommendations(): Promise<IExtensionRecommendation[]>;
getWorkspaceRecommendations(): Promise<IExtensionRecommendation[]>;
@@ -145,6 +146,7 @@ export const IWebExtensionsScannerService = createDecorator<IWebExtensionsScanne
export interface IWebExtensionsScannerService {
readonly _serviceBrand: undefined;
scanExtensions(type?: ExtensionType): Promise<IScannedExtension[]>;
scanAndTranslateExtensions(type?: ExtensionType): Promise<ITranslatedScannedExtension[]>;
addExtension(galleryExtension: IGalleryExtension): Promise<IScannedExtension>;
removeExtension(identifier: IExtensionIdentifier, version?: string): Promise<void>;
}

View File

@@ -3,13 +3,10 @@
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { ExtensionType, IExtensionIdentifier, IExtensionManifest, IScannedExtension } from 'vs/platform/extensions/common/extensions';
import { ExtensionType, IExtensionIdentifier, IExtensionManifest, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions';
import { IExtensionManagementService, ILocalExtension, InstallExtensionEvent, DidInstallExtensionEvent, DidUninstallExtensionEvent, IGalleryExtension, IReportedExtension, IGalleryMetadata, InstallOperation } from 'vs/platform/extensionManagement/common/extensionManagement';
import { Event, Emitter } from 'vs/base/common/event';
import { URI } from 'vs/base/common/uri';
import { IRequestService, isSuccess, asText } from 'vs/platform/request/common/request';
import { CancellationToken } from 'vs/base/common/cancellation';
import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls';
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { ILogService } from 'vs/platform/log/common/log';
@@ -33,14 +30,13 @@ export class WebExtensionManagementService extends Disposable implements IExtens
constructor(
@IWebExtensionsScannerService private readonly webExtensionsScannerService: IWebExtensionsScannerService,
@IRequestService private readonly requestService: IRequestService,
@ILogService private readonly logService: ILogService,
) {
super();
}
async getInstalled(type?: ExtensionType): Promise<ILocalExtension[]> {
const extensions = await this.webExtensionsScannerService.scanExtensions(type);
const extensions = await this.webExtensionsScannerService.scanAndTranslateExtensions(type);
return Promise.all(extensions.map(e => this.toLocalExtension(e)));
}
@@ -83,23 +79,11 @@ export class WebExtensionManagementService extends Disposable implements IExtens
return userExtensions.find(e => areSameExtensions(e.identifier, identifier));
}
private async toLocalExtension(scannedExtension: IScannedExtension): Promise<ILocalExtension> {
let manifest = scannedExtension.packageJSON;
if (scannedExtension.packageNLSUrl) {
try {
const context = await this.requestService.request({ type: 'GET', url: scannedExtension.packageNLSUrl.toString() }, CancellationToken.None);
if (isSuccess(context)) {
const content = await asText(context);
if (content) {
manifest = localizeManifest(manifest, JSON.parse(content));
}
}
} catch (error) { /* ignore */ }
}
private async toLocalExtension(scannedExtension: ITranslatedScannedExtension): Promise<ILocalExtension> {
return <ILocalExtension>{
type: scannedExtension.type,
identifier: scannedExtension.identifier,
manifest,
manifest: scannedExtension.packageJSON,
location: scannedExtension.location,
isMachineScoped: false,
publisherId: null,

View File

@@ -4,7 +4,7 @@
*--------------------------------------------------------------------------------------------*/
import * as semver from 'semver-umd';
import { IBuiltinExtensionsScannerService, IScannedExtension, ExtensionType, IExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
import { IBuiltinExtensionsScannerService, IScannedExtension, ExtensionType, IExtensionIdentifier, ITranslatedScannedExtension } from 'vs/platform/extensions/common/extensions';
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
import { IWebExtensionsScannerService } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
import { isWeb } from 'vs/base/common/platform';
@@ -21,6 +21,9 @@ import { IGalleryExtension } from 'vs/platform/extensionManagement/common/extens
import { groupByExtension, areSameExtensions, getGalleryExtensionId } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IStaticExtension } from 'vs/workbench/workbench.web.api';
import { Disposable } from 'vs/base/common/lifecycle';
import { Event } from 'vs/base/common/event';
import { localizeManifest } from 'vs/platform/extensionManagement/common/extensionNls';
interface IUserExtension {
identifier: IExtensionIdentifier;
@@ -44,7 +47,7 @@ const AssetTypeWebResource = 'Microsoft.VisualStudio.Code.WebResources';
function getExtensionLocation(assetUri: URI): URI { return joinPath(assetUri, AssetTypeWebResource, 'extension'); }
export class WebExtensionsScannerService implements IWebExtensionsScannerService {
export class WebExtensionsScannerService extends Disposable implements IWebExtensionsScannerService {
declare readonly _serviceBrand: undefined;
@@ -53,6 +56,8 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
private readonly extensionsResource: URI | undefined = undefined;
private readonly userExtensionsResourceLimiter: Queue<IUserExtension[]> = new Queue<IUserExtension[]>();
private userExtensionsPromise: Promise<IScannedExtension[]> | undefined;
constructor(
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
@IBuiltinExtensionsScannerService private readonly builtinExtensionsScannerService: IBuiltinExtensionsScannerService,
@@ -61,22 +66,48 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
@ILogService private readonly logService: ILogService,
@IConfigurationService private readonly configurationService: IConfigurationService,
) {
super();
if (isWeb) {
this.extensionsResource = joinPath(environmentService.userRoamingDataHome, 'extensions.json');
this.systemExtensionsPromise = this.builtinExtensionsScannerService.scanBuiltinExtensions();
this.systemExtensionsPromise = this.readSystemExtensions();
this.defaultExtensionsPromise = this.readDefaultExtensions();
if (this.extensionsResource) {
this._register(Event.filter(this.fileService.onDidFilesChange, e => e.contains(this.extensionsResource!))(() => this.userExtensionsPromise = undefined));
}
}
}
private async readDefaultExtensions(): Promise<IScannedExtension[]> {
private async readSystemExtensions(): Promise<IScannedExtension[]> {
const extensions = await this.builtinExtensionsScannerService.scanBuiltinExtensions();
return extensions.concat(this.getStaticExtensions(true));
}
/**
* All extensions defined via `staticExtensions`
*/
private getStaticExtensions(builtin: boolean): IScannedExtension[] {
const staticExtensions = this.environmentService.options && Array.isArray(this.environmentService.options.staticExtensions) ? this.environmentService.options.staticExtensions : [];
return (
staticExtensions
.filter(e => Boolean(e.isBuiltin) === builtin)
.map(e => ({
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
location: e.extensionLocation,
type: ExtensionType.System,
packageJSON: e.packageJSON,
}))
);
}
private async readDefaultExtensions(): Promise<IScannedExtension[]> {
const defaultUserWebExtensions = await this.readDefaultUserWebExtensions();
return [...staticExtensions, ...defaultUserWebExtensions].map<IScannedExtension>(e => ({
const extensions = defaultUserWebExtensions.map(e => ({
identifier: { id: getGalleryExtensionId(e.packageJSON.publisher, e.packageJSON.name) },
location: e.extensionLocation,
type: ExtensionType.User,
packageJSON: e.packageJSON,
}));
return extensions.concat(this.getStaticExtensions(false));
}
private async readDefaultUserWebExtensions(): Promise<IStaticExtension[]> {
@@ -113,12 +144,52 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
if (type === undefined || type === ExtensionType.User) {
const staticExtensions = await this.defaultExtensionsPromise;
extensions.push(...staticExtensions);
const userExtensions = await this.scanUserExtensions();
if (!this.userExtensionsPromise) {
this.userExtensionsPromise = this.scanUserExtensions();
}
const userExtensions = await this.userExtensionsPromise;
extensions.push(...userExtensions);
}
return extensions;
}
async scanAndTranslateExtensions(type?: ExtensionType): Promise<ITranslatedScannedExtension[]> {
const extensions = await this.scanExtensions(type);
return Promise.all(extensions.map((ext) => this._translateScannedExtension(ext)));
}
private async _translateScannedExtension(scannedExtension: IScannedExtension): Promise<ITranslatedScannedExtension> {
let manifest = scannedExtension.packageJSON;
if (scannedExtension.packageNLS) {
// package.nls.json is inlined
try {
manifest = localizeManifest(manifest, scannedExtension.packageNLS);
} catch (error) {
console.log(error);
/* ignore */
}
} else if (scannedExtension.packageNLSUrl) {
// package.nls.json needs to be fetched
try {
const context = await this.requestService.request({ type: 'GET', url: scannedExtension.packageNLSUrl.toString() }, CancellationToken.None);
if (isSuccess(context)) {
const content = await asText(context);
if (content) {
manifest = localizeManifest(manifest, JSON.parse(content));
}
}
} catch (error) { /* ignore */ }
}
return {
identifier: scannedExtension.identifier,
location: scannedExtension.location,
type: scannedExtension.type,
packageJSON: manifest,
readmeUrl: scannedExtension.readmeUrl,
changelogUrl: scannedExtension.changelogUrl
};
}
async addExtension(galleryExtension: IGalleryExtension): Promise<IScannedExtension> {
if (!galleryExtension.assetTypes.some(type => type.startsWith(AssetTypeWebResource))) {
throw new Error(`Missing ${AssetTypeWebResource} asset type`);
@@ -149,7 +220,7 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
async removeExtension(identifier: IExtensionIdentifier, version?: string): Promise<void> {
let userExtensions = await this.readUserExtensions();
userExtensions = userExtensions.filter(extension => !(areSameExtensions(extension.identifier, identifier) && version ? extension.version === version : true));
userExtensions = userExtensions.filter(extension => !(areSameExtensions(extension.identifier, identifier) && (version ? extension.version === version : true)));
await this.writeUserExtensions(userExtensions);
}
@@ -226,6 +297,7 @@ export class WebExtensionsScannerService implements IWebExtensionsScannerService
packageNLSUri: e.packageNLSUri?.toJSON(),
}));
await this.fileService.writeFile(this.extensionsResource!, VSBuffer.fromString(JSON.stringify(storedUserExtensions)));
this.userExtensionsPromise = undefined;
return userExtensions;
});
}

View File

@@ -397,7 +397,7 @@ suite('ExtensionEnablementService Test', () => {
assert.ok(!testObject.canChangeEnablement(extension));
});
test('test extension is disabled when disabled in enviroment', async () => {
test('test extension is disabled when disabled in environment', async () => {
const extension = aLocalExtension('pub.a');
instantiationService.stub(IWorkbenchEnvironmentService, { disableExtensions: ['pub.a'] } as IWorkbenchEnvironmentService);
instantiationService.stub(IExtensionManagementService, { onDidUninstallExtension: didUninstallEvent.event, getInstalled: () => Promise.resolve([extension, aLocalExtension('pub.b')]) } as IExtensionManagementService);