| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /*---------------------------------------------------------------------------------------------
- * 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 { CancellationError, onUnexpectedExternalError } from '../../../../base/common/errors.js';
- import { DisposableStore } from '../../../../base/common/lifecycle.js';
- import { Position } from '../../../common/core/position.js';
- import { Range } from '../../../common/core/range.js';
- import { Schemas } from '../../../../base/common/network.js';
- import { URI } from '../../../../base/common/uri.js';
- export class InlayHintAnchor {
- constructor(range, direction) {
- this.range = range;
- this.direction = direction;
- }
- }
- export class InlayHintItem {
- constructor(hint, anchor, provider) {
- this.hint = hint;
- this.anchor = anchor;
- this.provider = provider;
- this._isResolved = false;
- }
- with(delta) {
- const result = new InlayHintItem(this.hint, delta.anchor, this.provider);
- result._isResolved = this._isResolved;
- result._currentResolve = this._currentResolve;
- return result;
- }
- resolve(token) {
- return __awaiter(this, void 0, void 0, function* () {
- if (typeof this.provider.resolveInlayHint !== 'function') {
- return;
- }
- if (this._currentResolve) {
- // wait for an active resolve operation and try again
- // when that's done.
- yield this._currentResolve;
- if (token.isCancellationRequested) {
- return;
- }
- return this.resolve(token);
- }
- if (!this._isResolved) {
- this._currentResolve = this._doResolve(token)
- .finally(() => this._currentResolve = undefined);
- }
- yield this._currentResolve;
- });
- }
- _doResolve(token) {
- var _a, _b;
- return __awaiter(this, void 0, void 0, function* () {
- try {
- const newHint = yield Promise.resolve(this.provider.resolveInlayHint(this.hint, token));
- this.hint.tooltip = (_a = newHint === null || newHint === void 0 ? void 0 : newHint.tooltip) !== null && _a !== void 0 ? _a : this.hint.tooltip;
- this.hint.label = (_b = newHint === null || newHint === void 0 ? void 0 : newHint.label) !== null && _b !== void 0 ? _b : this.hint.label;
- this._isResolved = true;
- }
- catch (err) {
- onUnexpectedExternalError(err);
- this._isResolved = false;
- }
- });
- }
- }
- export class InlayHintsFragments {
- constructor(ranges, data, model) {
- this._disposables = new DisposableStore();
- this.ranges = ranges;
- this.provider = new Set();
- const items = [];
- for (const [list, provider] of data) {
- this._disposables.add(list);
- this.provider.add(provider);
- for (const hint of list.hints) {
- // compute the range to which the item should be attached to
- const position = model.validatePosition(hint.position);
- let direction = 'before';
- const wordRange = InlayHintsFragments._getRangeAtPosition(model, position);
- let range;
- if (wordRange.getStartPosition().isBefore(position)) {
- range = Range.fromPositions(wordRange.getStartPosition(), position);
- direction = 'after';
- }
- else {
- range = Range.fromPositions(position, wordRange.getEndPosition());
- direction = 'before';
- }
- items.push(new InlayHintItem(hint, new InlayHintAnchor(range, direction), provider));
- }
- }
- this.items = items.sort((a, b) => Position.compare(a.hint.position, b.hint.position));
- }
- static create(registry, model, ranges, token) {
- return __awaiter(this, void 0, void 0, function* () {
- const data = [];
- const promises = registry.ordered(model).reverse().map(provider => ranges.map((range) => __awaiter(this, void 0, void 0, function* () {
- try {
- const result = yield provider.provideInlayHints(model, range, token);
- if (result === null || result === void 0 ? void 0 : result.hints.length) {
- data.push([result, provider]);
- }
- }
- catch (err) {
- onUnexpectedExternalError(err);
- }
- })));
- yield Promise.all(promises.flat());
- if (token.isCancellationRequested || model.isDisposed()) {
- throw new CancellationError();
- }
- return new InlayHintsFragments(ranges, data, model);
- });
- }
- dispose() {
- this._disposables.dispose();
- }
- static _getRangeAtPosition(model, position) {
- const line = position.lineNumber;
- const word = model.getWordAtPosition(position);
- if (word) {
- // always prefer the word range
- return new Range(line, word.startColumn, line, word.endColumn);
- }
- model.tokenization.tokenizeIfCheap(line);
- const tokens = model.tokenization.getLineTokens(line);
- const offset = position.column - 1;
- const idx = tokens.findTokenIndexAtOffset(offset);
- let start = tokens.getStartOffset(idx);
- let end = tokens.getEndOffset(idx);
- if (end - start === 1) {
- // single character token, when at its end try leading/trailing token instead
- if (start === offset && idx > 1) {
- // leading token
- start = tokens.getStartOffset(idx - 1);
- end = tokens.getEndOffset(idx - 1);
- }
- else if (end === offset && idx < tokens.getCount() - 1) {
- // trailing token
- start = tokens.getStartOffset(idx + 1);
- end = tokens.getEndOffset(idx + 1);
- }
- }
- return new Range(line, start + 1, line, end + 1);
- }
- }
- export function asCommandLink(command) {
- return URI.from({
- scheme: Schemas.command,
- path: command.id,
- query: command.arguments && encodeURIComponent(JSON.stringify(command.arguments))
- }).toString();
- }
|