/*--------------------------------------------------------------------------------------------- * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; import { CancellationToken } from '../../../base/common/cancellation.js'; import { illegalArgument, onUnexpectedExternalError } from '../../../base/common/errors.js'; import { DisposableStore } from '../../../base/common/lifecycle.js'; import { assertType } from '../../../base/common/types.js'; import { URI } from '../../../base/common/uri.js'; import { CodeLensProviderRegistry } from '../../common/modes.js'; import { IModelService } from '../../common/services/modelService.js'; import { CommandsRegistry } from '../../../platform/commands/common/commands.js'; export class CodeLensModel { constructor() { this.lenses = []; this._disposables = new DisposableStore(); } dispose() { this._disposables.dispose(); } add(list, provider) { this._disposables.add(list); for (const symbol of list.lenses) { this.lenses.push({ symbol, provider }); } } } export function getCodeLensModel(model, token) { return __awaiter(this, void 0, void 0, function* () { const provider = CodeLensProviderRegistry.ordered(model); const providerRanks = new Map(); const result = new CodeLensModel(); const promises = provider.map((provider, i) => __awaiter(this, void 0, void 0, function* () { providerRanks.set(provider, i); try { const list = yield Promise.resolve(provider.provideCodeLenses(model, token)); if (list) { result.add(list, provider); } } catch (err) { onUnexpectedExternalError(err); } })); yield Promise.all(promises); result.lenses = result.lenses.sort((a, b) => { // sort by lineNumber, provider-rank, and column if (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) { return -1; } else if (a.symbol.range.startLineNumber > b.symbol.range.startLineNumber) { return 1; } else if ((providerRanks.get(a.provider)) < (providerRanks.get(b.provider))) { return -1; } else if ((providerRanks.get(a.provider)) > (providerRanks.get(b.provider))) { return 1; } else if (a.symbol.range.startColumn < b.symbol.range.startColumn) { return -1; } else if (a.symbol.range.startColumn > b.symbol.range.startColumn) { return 1; } else { return 0; } }); return result; }); } CommandsRegistry.registerCommand('_executeCodeLensProvider', function (accessor, ...args) { let [uri, itemResolveCount] = args; assertType(URI.isUri(uri)); assertType(typeof itemResolveCount === 'number' || !itemResolveCount); const model = accessor.get(IModelService).getModel(uri); if (!model) { throw illegalArgument(); } const result = []; const disposables = new DisposableStore(); return getCodeLensModel(model, CancellationToken.None).then(value => { disposables.add(value); let resolve = []; for (const item of value.lenses) { if (itemResolveCount === undefined || itemResolveCount === null || Boolean(item.symbol.command)) { result.push(item.symbol); } else if (itemResolveCount-- > 0 && item.provider.resolveCodeLens) { resolve.push(Promise.resolve(item.provider.resolveCodeLens(model, item.symbol, CancellationToken.None)).then(symbol => result.push(symbol || item.symbol))); } } return Promise.all(resolve); }).then(() => { return result; }).finally(() => { // make sure to return results, then (on next tick) // dispose the results setTimeout(() => disposables.dispose(), 100); }); });