ghostTextModel.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  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 __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  6. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  7. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  8. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  9. return c > 3 && r && Object.defineProperty(target, key, r), r;
  10. };
  11. var __param = (this && this.__param) || function (paramIndex, decorator) {
  12. return function (target, key) { decorator(target, key, paramIndex); }
  13. };
  14. var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
  15. function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
  16. return new (P || (P = Promise))(function (resolve, reject) {
  17. function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
  18. function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
  19. function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
  20. step((generator = generator.apply(thisArg, _arguments || [])).next());
  21. });
  22. };
  23. import { Emitter } from '../../../base/common/event.js';
  24. import { Disposable, MutableDisposable } from '../../../base/common/lifecycle.js';
  25. import { Position } from '../../common/core/position.js';
  26. import { InlineCompletionTriggerKind } from '../../common/modes.js';
  27. import { InlineCompletionsModel, SynchronizedInlineCompletionsCache } from './inlineCompletionsModel.js';
  28. import { SuggestWidgetPreviewModel } from './suggestWidgetPreviewModel.js';
  29. import { createDisposableRef } from './utils.js';
  30. import { ICommandService } from '../../../platform/commands/common/commands.js';
  31. export class DelegatingModel extends Disposable {
  32. constructor() {
  33. super(...arguments);
  34. this.onDidChangeEmitter = new Emitter();
  35. this.onDidChange = this.onDidChangeEmitter.event;
  36. this.hasCachedGhostText = false;
  37. this.currentModelRef = this._register(new MutableDisposable());
  38. }
  39. get targetModel() {
  40. var _a;
  41. return (_a = this.currentModelRef.value) === null || _a === void 0 ? void 0 : _a.object;
  42. }
  43. setTargetModel(model) {
  44. var _a;
  45. if (((_a = this.currentModelRef.value) === null || _a === void 0 ? void 0 : _a.object) === model) {
  46. return;
  47. }
  48. this.currentModelRef.clear();
  49. this.currentModelRef.value = model ? createDisposableRef(model, model.onDidChange(() => {
  50. this.hasCachedGhostText = false;
  51. this.onDidChangeEmitter.fire();
  52. })) : undefined;
  53. this.hasCachedGhostText = false;
  54. this.onDidChangeEmitter.fire();
  55. }
  56. get ghostText() {
  57. var _a, _b;
  58. if (!this.hasCachedGhostText) {
  59. this.cachedGhostText = (_b = (_a = this.currentModelRef.value) === null || _a === void 0 ? void 0 : _a.object) === null || _b === void 0 ? void 0 : _b.ghostText;
  60. this.hasCachedGhostText = true;
  61. }
  62. return this.cachedGhostText;
  63. }
  64. setExpanded(expanded) {
  65. var _a;
  66. (_a = this.targetModel) === null || _a === void 0 ? void 0 : _a.setExpanded(expanded);
  67. }
  68. get minReservedLineCount() {
  69. return this.targetModel ? this.targetModel.minReservedLineCount : 0;
  70. }
  71. }
  72. /**
  73. * A ghost text model that is both driven by inline completions and the suggest widget.
  74. */
  75. let GhostTextModel = class GhostTextModel extends DelegatingModel {
  76. constructor(editor, commandService) {
  77. super();
  78. this.editor = editor;
  79. this.commandService = commandService;
  80. this.sharedCache = this._register(new SharedInlineCompletionCache());
  81. this.suggestWidgetAdapterModel = this._register(new SuggestWidgetPreviewModel(this.editor, this.sharedCache));
  82. this.inlineCompletionsModel = this._register(new InlineCompletionsModel(this.editor, this.sharedCache, this.commandService));
  83. this._register(this.suggestWidgetAdapterModel.onDidChange(() => {
  84. this.updateModel();
  85. }));
  86. this.updateModel();
  87. }
  88. get activeInlineCompletionsModel() {
  89. if (this.targetModel === this.inlineCompletionsModel) {
  90. return this.inlineCompletionsModel;
  91. }
  92. return undefined;
  93. }
  94. updateModel() {
  95. this.setTargetModel(this.suggestWidgetAdapterModel.isActive
  96. ? this.suggestWidgetAdapterModel
  97. : this.inlineCompletionsModel);
  98. this.inlineCompletionsModel.setActive(this.targetModel === this.inlineCompletionsModel);
  99. }
  100. shouldShowHoverAt(hoverRange) {
  101. var _a;
  102. const ghostText = (_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.ghostText;
  103. if (ghostText) {
  104. return ghostText.parts.some(p => hoverRange.containsPosition(new Position(ghostText.lineNumber, p.column)));
  105. }
  106. return false;
  107. }
  108. triggerInlineCompletion() {
  109. var _a;
  110. (_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.trigger(InlineCompletionTriggerKind.Explicit);
  111. }
  112. commitInlineCompletion() {
  113. var _a;
  114. (_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.commitCurrentSuggestion();
  115. }
  116. hideInlineCompletion() {
  117. var _a;
  118. (_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.hide();
  119. }
  120. showNextInlineCompletion() {
  121. var _a;
  122. (_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.showNext();
  123. }
  124. showPreviousInlineCompletion() {
  125. var _a;
  126. (_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.showPrevious();
  127. }
  128. hasMultipleInlineCompletions() {
  129. var _a;
  130. return __awaiter(this, void 0, void 0, function* () {
  131. const result = yield ((_a = this.activeInlineCompletionsModel) === null || _a === void 0 ? void 0 : _a.hasMultipleInlineCompletions());
  132. return result !== undefined ? result : false;
  133. });
  134. }
  135. };
  136. GhostTextModel = __decorate([
  137. __param(1, ICommandService)
  138. ], GhostTextModel);
  139. export { GhostTextModel };
  140. export class SharedInlineCompletionCache extends Disposable {
  141. constructor() {
  142. super(...arguments);
  143. this.onDidChangeEmitter = new Emitter();
  144. this.onDidChange = this.onDidChangeEmitter.event;
  145. this.cache = this._register(new MutableDisposable());
  146. }
  147. get value() {
  148. return this.cache.value;
  149. }
  150. setValue(editor, completionsSource, triggerKind) {
  151. this.cache.value = new SynchronizedInlineCompletionsCache(editor, completionsSource, () => this.onDidChangeEmitter.fire(), triggerKind);
  152. }
  153. clearAndLeak() {
  154. return this.cache.clearAndLeak();
  155. }
  156. clear() {
  157. this.cache.clear();
  158. }
  159. }