use stableSort in code-lens

This commit is contained in:
Johannes Rieken 2017-05-16 17:46:53 +02:00
parent a26e004467
commit 8ac7e555d1
3 changed files with 43 additions and 1 deletions

View file

@ -66,6 +66,33 @@ export function findFirst<T>(array: T[], p: (x: T) => boolean): number {
return low;
}
/**
* Like `Array#sort` but always stable. Comes at a cost: iterates 2n-times,
* creates n-objects in addition to sorting (log(n))
*/
export function stableSort<T>(data: T[], compare: (a: T, b: T) => number): T[] {
let data2: { idx: number; e: T }[] = <any>data;
for (let idx = 0; idx < data2.length; idx++) {
data2[idx] = { idx, e: data[idx] };
}
data2.sort((a, b) => {
let ret = compare(a.e, b.e);
if (ret === 0) {
ret = a.idx - b.idx;
}
return ret;
});
for (let idx = 0; idx < data2.length; idx++) {
data[idx] = data2[idx].e;
}
return data;
}
export function groupBy<T>(data: T[], compare: (a: T, b: T) => number): T[][] {
const result: T[][] = [];
let currentGroup: T[];

View file

@ -33,6 +33,19 @@ suite('Arrays', () => {
assert.equal(array[idx], 1);
});
test('stableSort', function () {
let counter = 0;
let data = arrays.fill(10000, () => ({ n: 1, m: counter++ }));
arrays.stableSort(data, (a, b) => a.n - b.n);
let lastM = -1;
for (const element of data) {
assert.ok(lastM < element.m);
lastM = element.m;
}
});
test('delta', function () {
function compare(a: number, b: number): number {
return a - b;

View file

@ -6,6 +6,7 @@
'use strict';
import { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors';
import { stableSort } from 'vs/base/common/arrays';
import URI from 'vs/base/common/uri';
import { TPromise } from 'vs/base/common/winjs.base';
import { IModel } from 'vs/editor/common/editorCommon';
@ -33,7 +34,8 @@ export function getCodeLensData(model: IModel): TPromise<ICodeLensData[]> {
}, onUnexpectedExternalError));
return TPromise.join(promises).then(() => {
return symbols.sort((a, b) => {
return stableSort(symbols, (a, b) => {
// sort by lineNumber, provider-rank, and column
if (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) {
return -1;