diff --git a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts index f6a9dfaccf..9d447dcdd8 100644 --- a/src/vs/platform/extensionManagement/node/extensionGalleryService.ts +++ b/src/vs/platform/extensionManagement/node/extensionGalleryService.ts @@ -456,6 +456,8 @@ export class ExtensionGalleryService implements IExtensionGalleryService { * @param galleryExtensions */ private createQueryResult(query: Query, galleryExtensions: IRawGalleryExtension[]): { galleryExtensions: IRawGalleryExtension[], total: number; } { + + // Filtering let filteredExtensions = galleryExtensions; if (query.criteria) { const ids = query.criteria.filter(x => x.filterType === FilterType.ExtensionId).map(v => v.value.toLocaleLowerCase()); @@ -466,12 +468,60 @@ export class ExtensionGalleryService implements IExtensionGalleryService { if (names && names.length > 0) { filteredExtensions = filteredExtensions.filter(e => e.extensionName && e.publisher.publisherName && names.includes(`${e.publisher.publisherName.toLocaleLowerCase()}.${e.extensionName.toLocaleLowerCase()}`)); } + const searchTexts = query.criteria.filter(x => x.filterType === FilterType.SearchText).map(v => v.value.toLocaleLowerCase()); + if (searchTexts && searchTexts.length > 0) { + searchTexts.forEach(searchText => { + if (searchText !== '@allmarketplace') { + filteredExtensions = filteredExtensions.filter( + e => e.extensionName && e.extensionName.includes(searchText) || + e.publisher && e.publisher.publisherName && e.publisher.publisherName.includes(searchText) || + e.publisher && e.publisher.displayName && e.publisher.displayName.includes(searchText) || + e.displayName && e.displayName.includes(searchText) || + e.shortDescription && e.shortDescription.includes(searchText) || + e.extensionId && e.extensionId.includes(searchText) + ); + } + }); + } + } + + // Sorting + switch (query.sortBy) { + case SortBy.PublisherName: + filteredExtensions.sort( (a, b) => ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName')); + break; + case SortBy.Title: + default: + filteredExtensions.sort( (a, b) => ExtensionGalleryService.compareByField(a, b, 'displayName')); + break; } let actualTotal = filteredExtensions.length; return { galleryExtensions: filteredExtensions, total: actualTotal }; } + public static compareByField(a: any, b: any, fieldName: string): number { + if (a && !b) { + return 1; + } + if (b && !a) { + return -1; + } + if (a && a[fieldName] && (!b || !b[fieldName])) { + return 1; + } + if (b && b[fieldName] && (!a || !a[fieldName])) { + return -1; + } + if (!b || !b[fieldName] && (!a || !a[fieldName])) { + return 0; + } + if (a[fieldName] === b[fieldName]) { + return 0; + } + return a[fieldName] < b[fieldName] ? -1 : 1; + } + private queryGallery(query: Query): TPromise<{ galleryExtensions: IRawGalleryExtension[], total: number; }> { return this.commonHeadersPromise.then(commonHeaders => { const data = JSON.stringify(query.raw); diff --git a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts index 967f630f3b..644ba0684e 100644 --- a/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts +++ b/src/vs/platform/extensionManagement/test/node/extensionGalleryService.test.ts @@ -13,7 +13,8 @@ import { parseArgs } from 'vs/platform/environment/node/argv'; import { getRandomTestPath } from 'vs/workbench/test/workbenchTestServices'; import { join } from 'path'; import { mkdirp } from 'vs/base/node/pfs'; -import { resolveMarketplaceHeaders } from 'vs/platform/extensionManagement/node/extensionGalleryService'; +// {{SQL CARBON EDIT}} +import { resolveMarketplaceHeaders, ExtensionGalleryService } from 'vs/platform/extensionManagement/node/extensionGalleryService'; import { isUUID } from 'vs/base/common/uuid'; suite('Extension Gallery Service', () => { @@ -48,4 +49,49 @@ suite('Extension Gallery Service', () => { }); }); }); + + // {{SQL CARBON EDIT}} + test('sortByField', () => { + let a = { + extensionId: undefined, + extensionName: undefined, + displayName: undefined, + shortDescription: undefined, + publisher: undefined + }; + let b = { + extensionId: undefined, + extensionName: undefined, + displayName: undefined, + shortDescription: undefined, + publisher: undefined + }; + + + assert.equal(ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName'), 0); + + a.publisher = { displayName: undefined, publisherId: undefined, publisherName: undefined}; + assert.equal(ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName'), 1); + + b.publisher = { displayName: undefined, publisherId: undefined, publisherName: undefined}; + assert.equal(ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName'), 0); + + a.publisher.publisherName = 'a'; + assert.equal(ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName'), 1); + + b.publisher.publisherName = 'b'; + assert.equal(ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName'), -1); + + b.publisher.publisherName = 'a'; + assert.equal(ExtensionGalleryService.compareByField(a.publisher, b.publisher, 'publisherName'), 0); + + a.displayName = 'test1'; + assert.equal(ExtensionGalleryService.compareByField(a, b, 'displayName'), 1); + + b.displayName = 'test2'; + assert.equal(ExtensionGalleryService.compareByField(a, b, 'displayName'), -1); + + b.displayName = 'test1'; + assert.equal(ExtensionGalleryService.compareByField(a, b, 'displayName'), 0); + }); }); \ No newline at end of file diff --git a/src/vs/workbench/parts/extensions/common/extensions.ts b/src/vs/workbench/parts/extensions/common/extensions.ts index 9bef2fb12f..1133ce18f2 100644 --- a/src/vs/workbench/parts/extensions/common/extensions.ts +++ b/src/vs/workbench/parts/extensions/common/extensions.ts @@ -37,6 +37,8 @@ export interface IExtension { description: string; url: string; downloadUrl: string; + // {{SQL CARBON EDIT}} + downloadPage: string; repository: string; iconUrl: string; iconUrlFallback: string; diff --git a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts index bd6b7f704a..961b7a8446 100644 --- a/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts +++ b/src/vs/workbench/parts/extensions/node/extensionsWorkbenchService.ts @@ -127,6 +127,16 @@ class Extension implements IExtension { //return `${product.extensionsGallery.serviceUrl}/publishers/${this.publisher}/vsextensions/${this.name}/${this.latestVersion}/vspackage`; } + // {{SQL CARBON EDIT}} + get downloadPage(): string { + if (!product.extensionsGallery) { + return null; + } + + // {{SQL CARBON EDIT}} + return this.gallery && this.gallery.assets && this.gallery.assets.downloadPage && this.gallery.assets.downloadPage.uri; + } + get iconUrl(): string { return this.galleryIconUrl || this.localIconUrl || this.defaultIconUrl; } @@ -570,7 +580,8 @@ export class ExtensionsWorkbenchService implements IExtensionsWorkbenchService { return TPromise.as(null); } - const toUpdate = this.local.filter(e => e.outdated && (e.state !== ExtensionState.Installing)); + // {{SQL CARBON EDIT}} + const toUpdate = this.local.filter(e => e.outdated && (e.state !== ExtensionState.Installing) && !e.downloadPage); return TPromise.join(toUpdate.map(e => this.install(e))); }