codelens.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*---------------------------------------------------------------------------------------------
  2. * Copyright (c) Microsoft Corporation. All rights reserved.
  3. * Licensed under the MIT License. See License.txt in the project root for license information.
  4. *--------------------------------------------------------------------------------------------*/
  5. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  6. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  7. return new (P || (P = Promise))(function (resolve, reject) {
  8. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  9. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  10. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  11. step((generator = generator.apply(thisArg, _arguments || [])).next());
  12. });
  13. };
  14. import { CancellationToken } from '../../../base/common/cancellation.js';
  15. import { illegalArgument, onUnexpectedExternalError } from '../../../base/common/errors.js';
  16. import { DisposableStore } from '../../../base/common/lifecycle.js';
  17. import { assertType } from '../../../base/common/types.js';
  18. import { URI } from '../../../base/common/uri.js';
  19. import { CodeLensProviderRegistry } from '../../common/modes.js';
  20. import { IModelService } from '../../common/services/modelService.js';
  21. import { CommandsRegistry } from '../../../platform/commands/common/commands.js';
  22. export class CodeLensModel {
  23. constructor() {
  24. this.lenses = [];
  25. this._disposables = new DisposableStore();
  26. }
  27. dispose() {
  28. this._disposables.dispose();
  29. }
  30. add(list, provider) {
  31. this._disposables.add(list);
  32. for (const symbol of list.lenses) {
  33. this.lenses.push({ symbol, provider });
  34. }
  35. }
  36. }
  37. export function getCodeLensModel(model, token) {
  38. return __awaiter(this, void 0, void 0, function* () {
  39. const provider = CodeLensProviderRegistry.ordered(model);
  40. const providerRanks = new Map();
  41. const result = new CodeLensModel();
  42. const promises = provider.map((provider, i) => __awaiter(this, void 0, void 0, function* () {
  43. providerRanks.set(provider, i);
  44. try {
  45. const list = yield Promise.resolve(provider.provideCodeLenses(model, token));
  46. if (list) {
  47. result.add(list, provider);
  48. }
  49. }
  50. catch (err) {
  51. onUnexpectedExternalError(err);
  52. }
  53. }));
  54. yield Promise.all(promises);
  55. result.lenses = result.lenses.sort((a, b) => {
  56. // sort by lineNumber, provider-rank, and column
  57. if (a.symbol.range.startLineNumber < b.symbol.range.startLineNumber) {
  58. return -1;
  59. }
  60. else if (a.symbol.range.startLineNumber > b.symbol.range.startLineNumber) {
  61. return 1;
  62. }
  63. else if ((providerRanks.get(a.provider)) < (providerRanks.get(b.provider))) {
  64. return -1;
  65. }
  66. else if ((providerRanks.get(a.provider)) > (providerRanks.get(b.provider))) {
  67. return 1;
  68. }
  69. else if (a.symbol.range.startColumn < b.symbol.range.startColumn) {
  70. return -1;
  71. }
  72. else if (a.symbol.range.startColumn > b.symbol.range.startColumn) {
  73. return 1;
  74. }
  75. else {
  76. return 0;
  77. }
  78. });
  79. return result;
  80. });
  81. }
  82. CommandsRegistry.registerCommand('_executeCodeLensProvider', function (accessor, ...args) {
  83. let [uri, itemResolveCount] = args;
  84. assertType(URI.isUri(uri));
  85. assertType(typeof itemResolveCount === 'number' || !itemResolveCount);
  86. const model = accessor.get(IModelService).getModel(uri);
  87. if (!model) {
  88. throw illegalArgument();
  89. }
  90. const result = [];
  91. const disposables = new DisposableStore();
  92. return getCodeLensModel(model, CancellationToken.None).then(value => {
  93. disposables.add(value);
  94. let resolve = [];
  95. for (const item of value.lenses) {
  96. if (itemResolveCount === undefined || itemResolveCount === null || Boolean(item.symbol.command)) {
  97. result.push(item.symbol);
  98. }
  99. else if (itemResolveCount-- > 0 && item.provider.resolveCodeLens) {
  100. resolve.push(Promise.resolve(item.provider.resolveCodeLens(model, item.symbol, CancellationToken.None)).then(symbol => result.push(symbol || item.symbol)));
  101. }
  102. }
  103. return Promise.all(resolve);
  104. }).then(() => {
  105. return result;
  106. }).finally(() => {
  107. // make sure to return results, then (on next tick)
  108. // dispose the results
  109. setTimeout(() => disposables.dispose(), 100);
  110. });
  111. });