Files
azuredatastudio/src/vs/editor/contrib/quickOpen/quickOpen.ts
Anthony Dresser 4ba6a979ba Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781 (#8649)
* Merge from vscode a4177f50c475fc0fa278a78235e3bee9ffdec781

* distro

* fix tests
2019-12-11 22:42:23 -08:00

82 lines
2.9 KiB
TypeScript

/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { DocumentSymbol } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { CancellationToken } from 'vs/base/common/cancellation';
import { ITextModelService } from 'vs/editor/common/services/resolverService';
import { OutlineModel, OutlineElement } from 'vs/editor/contrib/documentSymbols/outlineModel';
import { values } from 'vs/base/common/collections';
import { CommandsRegistry } from 'vs/platform/commands/common/commands';
import { assertType } from 'vs/base/common/types';
export async function getDocumentSymbols(document: ITextModel, flat: boolean, token: CancellationToken): Promise<DocumentSymbol[]> {
const model = await OutlineModel.create(document, token);
const roots: DocumentSymbol[] = [];
for (const child of values(model.children)) {
if (child instanceof OutlineElement) {
roots.push(child.symbol);
} else {
roots.push(...values(child.children).map(child => child.symbol));
}
}
let flatEntries: DocumentSymbol[] = [];
if (token.isCancellationRequested) {
return flatEntries;
}
if (flat) {
flatten(flatEntries, roots, '');
} else {
flatEntries = roots;
}
return flatEntries.sort(compareEntriesUsingStart);
}
function compareEntriesUsingStart(a: DocumentSymbol, b: DocumentSymbol): number {
return Range.compareRangesUsingStarts(a.range, b.range);
}
function flatten(bucket: DocumentSymbol[], entries: DocumentSymbol[], overrideContainerLabel: string): void {
for (let entry of entries) {
bucket.push({
kind: entry.kind,
tags: entry.tags,
name: entry.name,
detail: entry.detail,
containerName: entry.containerName || overrideContainerLabel,
range: entry.range,
selectionRange: entry.selectionRange,
children: undefined, // we flatten it...
});
if (entry.children) {
flatten(bucket, entry.children, entry.name);
}
}
}
CommandsRegistry.registerCommand('_executeDocumentSymbolProvider', async function (accessor, ...args) {
const [resource] = args;
assertType(URI.isUri(resource));
const model = accessor.get(IModelService).getModel(resource);
if (model) {
return getDocumentSymbols(model, false, CancellationToken.None);
}
const reference = await accessor.get(ITextModelService).createModelReference(resource);
try {
return await getDocumentSymbols(reference.object.textEditorModel, false, CancellationToken.None);
} finally {
reference.dispose();
}
});