Files
azuredatastudio/src/vs/editor/contrib/quickOpen/quickOpen.ts
2019-02-21 17:56:04 -08:00

78 lines
2.6 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 { illegalArgument, onUnexpectedExternalError } from 'vs/base/common/errors';
import { URI } from 'vs/base/common/uri';
import { Range } from 'vs/editor/common/core/range';
import { ITextModel } from 'vs/editor/common/model';
import { registerLanguageCommand } from 'vs/editor/browser/editorExtensions';
import { DocumentSymbol, DocumentSymbolProviderRegistry } from 'vs/editor/common/modes';
import { IModelService } from 'vs/editor/common/services/modelService';
import { CancellationToken } from 'vs/base/common/cancellation';
export function getDocumentSymbols(model: ITextModel, flat: boolean, token: CancellationToken): Thenable<DocumentSymbol[]> {
let roots: DocumentSymbol[] = [];
let promises = DocumentSymbolProviderRegistry.all(model).map(support => {
return Promise.resolve(support.provideDocumentSymbols(model, token)).then(result => {
if (Array.isArray(result)) {
roots.push(...result);
}
}, err => {
onUnexpectedExternalError(err);
});
});
return Promise.all(promises).then(() => {
let flatEntries: DocumentSymbol[] = [];
if (token.isCancellationRequested) {
return flatEntries;
}
if (flat) {
flatten(flatEntries, roots, '');
} else {
flatEntries = roots;
}
flatEntries.sort(compareEntriesUsingStart);
return flatEntries;
});
}
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,
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);
}
}
}
registerLanguageCommand('_executeDocumentSymbolProvider', function (accessor, args) {
const { resource } = args;
if (!(resource instanceof URI)) {
throw illegalArgument('resource');
}
const model = accessor.get(IModelService).getModel(resource);
if (!model) {
throw illegalArgument('resource');
}
return getDocumentSymbols(model, false, CancellationToken.None);
});