use a parent pointer instead of 2d array, #67872
This commit is contained in:
parent
a86ff6a4da
commit
4f8dbd4544
9 changed files with 51 additions and 24 deletions
|
@ -81,16 +81,17 @@ export function activate(context: ExtensionContext) {
|
|||
|
||||
documentSelector.forEach(selector => {
|
||||
context.subscriptions.push(languages.registerSelectionRangeProvider(selector, {
|
||||
async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise<SelectionRange[][]> {
|
||||
async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise<SelectionRange[]> {
|
||||
const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(document);
|
||||
const rawResult = await client.sendRequest<SelectionRange[][]>('$/textDocument/selectionRanges', { textDocument, positions: positions.map(client.code2ProtocolConverter.asPosition) });
|
||||
if (Array.isArray(rawResult)) {
|
||||
return rawResult.map(rawSelectionRanges => {
|
||||
return rawSelectionRanges.map(selectionRange => {
|
||||
return rawSelectionRanges.reduceRight((parent: SelectionRange | undefined, selectionRange: SelectionRange) => {
|
||||
return {
|
||||
range: client.protocol2CodeConverter.asRange(selectionRange.range)
|
||||
range: client.protocol2CodeConverter.asRange(selectionRange.range),
|
||||
parent
|
||||
};
|
||||
});
|
||||
}, undefined)!;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
|
|
|
@ -90,16 +90,17 @@ export function activate(context: ExtensionContext) {
|
|||
|
||||
documentSelector.forEach(selector => {
|
||||
context.subscriptions.push(languages.registerSelectionRangeProvider(selector, {
|
||||
async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise<SelectionRange[][]> {
|
||||
async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise<SelectionRange[]> {
|
||||
const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(document);
|
||||
const rawResult = await client.sendRequest<SelectionRange[][]>('$/textDocument/selectionRanges', { textDocument, positions: positions.map(client.code2ProtocolConverter.asPosition) });
|
||||
if (Array.isArray(rawResult)) {
|
||||
return rawResult.map(rawSelectionRanges => {
|
||||
return rawSelectionRanges.map(selectionRange => {
|
||||
return rawSelectionRanges.reduceRight((parent: SelectionRange | undefined, selectionRange: SelectionRange) => {
|
||||
return {
|
||||
range: client.protocol2CodeConverter.asRange(selectionRange.range),
|
||||
parent
|
||||
};
|
||||
});
|
||||
}, undefined)!;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
|
|
|
@ -214,16 +214,17 @@ export function activate(context: ExtensionContext) {
|
|||
|
||||
documentSelector.forEach(selector => {
|
||||
toDispose.push(languages.registerSelectionRangeProvider(selector, {
|
||||
async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise<SelectionRange[][]> {
|
||||
async provideSelectionRanges(document: TextDocument, positions: Position[]): Promise<SelectionRange[]> {
|
||||
const textDocument = client.code2ProtocolConverter.asTextDocumentIdentifier(document);
|
||||
const rawResult = await client.sendRequest<SelectionRange[][]>('$/textDocument/selectionRanges', { textDocument, positions: positions.map(client.code2ProtocolConverter.asPosition) });
|
||||
if (Array.isArray(rawResult)) {
|
||||
return rawResult.map(rawSelectionRanges => {
|
||||
return rawSelectionRanges.map(selectionRange => {
|
||||
return rawSelectionRanges.reduceRight((parent: SelectionRange | undefined, selectionRange: SelectionRange) => {
|
||||
return {
|
||||
range: client.protocol2CodeConverter.asRange(selectionRange.range),
|
||||
parent,
|
||||
};
|
||||
});
|
||||
}, undefined)!;
|
||||
});
|
||||
}
|
||||
return [];
|
||||
|
|
|
@ -22,6 +22,7 @@ import { IDisposable, dispose } from 'vs/base/common/lifecycle';
|
|||
import { WordSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/wordSelections';
|
||||
import { BracketSelectionRangeProvider } from 'vs/editor/contrib/smartSelect/bracketSelections';
|
||||
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
|
||||
import { onUnexpectedExternalError } from 'vs/base/common/errors';
|
||||
|
||||
class SelectionRanges {
|
||||
|
||||
|
@ -237,7 +238,7 @@ export function provideSelectionRanges(model: ITextModel, positions: Position[],
|
|||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}, onUnexpectedExternalError));
|
||||
}
|
||||
|
||||
return Promise.all(work).then(() => {
|
||||
|
|
5
src/vs/vscode.proposed.d.ts
vendored
5
src/vs/vscode.proposed.d.ts
vendored
|
@ -86,7 +86,8 @@ declare module 'vscode' {
|
|||
|
||||
export class SelectionRange {
|
||||
range: Range;
|
||||
constructor(range: Range);
|
||||
parent?: SelectionRange;
|
||||
constructor(range: Range, parent?: SelectionRange);
|
||||
}
|
||||
|
||||
export interface SelectionRangeProvider {
|
||||
|
@ -97,7 +98,7 @@ declare module 'vscode' {
|
|||
*
|
||||
* todo@joh
|
||||
*/
|
||||
provideSelectionRanges(document: TextDocument, positions: Position[], token: CancellationToken): ProviderResult<SelectionRange[][]>;
|
||||
provideSelectionRanges(document: TextDocument, positions: Position[], token: CancellationToken): ProviderResult<SelectionRange[]>;
|
||||
}
|
||||
|
||||
export namespace languages {
|
||||
|
|
|
@ -944,14 +944,19 @@ class SelectionRangeAdapter {
|
|||
const oneResult: modes.SelectionRange[] = [];
|
||||
allResults.push(oneResult);
|
||||
|
||||
const oneProviderRanges = allProviderRanges[i];
|
||||
let last: vscode.Position | vscode.Range = positions[i];
|
||||
for (const selectionRange of oneProviderRanges) {
|
||||
let selectionRange = allProviderRanges[i];
|
||||
|
||||
while (true) {
|
||||
if (!selectionRange.range.contains(last)) {
|
||||
throw new Error('INVALID selection range, must contain the previous range');
|
||||
}
|
||||
oneResult.push(typeConvert.SelectionRange.from(selectionRange));
|
||||
if (!selectionRange.parent) {
|
||||
break;
|
||||
}
|
||||
last = selectionRange.range;
|
||||
selectionRange = selectionRange.parent;
|
||||
}
|
||||
}
|
||||
return allResults;
|
||||
|
|
|
@ -1098,9 +1098,11 @@ CodeActionKind.SourceFixAll = CodeActionKind.Source.append('fixAll');
|
|||
export class SelectionRange {
|
||||
|
||||
range: Range;
|
||||
parent?: SelectionRange;
|
||||
|
||||
constructor(range: Range) {
|
||||
constructor(range: Range, parent?: SelectionRange) {
|
||||
this.range = range;
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -799,10 +799,9 @@ suite('ExtHostLanguageFeatureCommands', function () {
|
|||
|
||||
disposables.push(extHost.registerSelectionRangeProvider(nullExtensionDescription, defaultSelector, <vscode.SelectionRangeProvider>{
|
||||
provideSelectionRanges() {
|
||||
return [[
|
||||
new types.SelectionRange(new types.Range(0, 10, 0, 18)),
|
||||
new types.SelectionRange(new types.Range(0, 2, 0, 20))
|
||||
]];
|
||||
return [
|
||||
new types.SelectionRange(new types.Range(0, 10, 0, 18), new types.SelectionRange(new types.Range(0, 2, 0, 20))),
|
||||
];
|
||||
}
|
||||
}));
|
||||
|
||||
|
|
|
@ -1104,10 +1104,9 @@ suite('ExtHostLanguageFeatures', function () {
|
|||
test('Selection Ranges, data conversion', async () => {
|
||||
disposables.push(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, new class implements vscode.SelectionRangeProvider {
|
||||
provideSelectionRanges() {
|
||||
return [[
|
||||
new types.SelectionRange(new types.Range(0, 10, 0, 18)),
|
||||
new types.SelectionRange(new types.Range(0, 2, 0, 20))
|
||||
]];
|
||||
return [
|
||||
new types.SelectionRange(new types.Range(0, 10, 0, 18), new types.SelectionRange(new types.Range(0, 2, 0, 20))),
|
||||
];
|
||||
}
|
||||
}));
|
||||
|
||||
|
@ -1118,4 +1117,21 @@ suite('ExtHostLanguageFeatures', function () {
|
|||
assert.ok(ranges[0].length >= 2);
|
||||
});
|
||||
});
|
||||
|
||||
test('Selection Ranges, bad data', async () => {
|
||||
disposables.push(extHost.registerSelectionRangeProvider(defaultExtension, defaultSelector, new class implements vscode.SelectionRangeProvider {
|
||||
provideSelectionRanges() {
|
||||
return [
|
||||
new types.SelectionRange(new types.Range(0, 10, 0, 18),
|
||||
new types.SelectionRange(new types.Range(0, 11, 0, 18))),
|
||||
];
|
||||
}
|
||||
}));
|
||||
|
||||
await rpcProtocol.sync();
|
||||
|
||||
provideSelectionRanges(model, [new Position(1, 17)], CancellationToken.None).then(ranges => {
|
||||
assert.equal(ranges.length, 0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue