@opensumi/ide-comments 3.0.5-next-1717466130.0 → 3.0.5-next-1717473339.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CommentsService = void 0;
4
4
  const tslib_1 = require("tslib");
5
- const debounce_1 = tslib_1.__importDefault(require("lodash/debounce"));
6
5
  const flattenDeep_1 = tslib_1.__importDefault(require("lodash/flattenDeep"));
7
6
  const groupBy_1 = tslib_1.__importDefault(require("lodash/groupBy"));
8
7
  const di_1 = require("@opensumi/di");
@@ -10,6 +9,7 @@ const ide_core_browser_1 = require("@opensumi/ide-core-browser");
10
9
  const browser_1 = require("@opensumi/ide-editor/lib/browser");
11
10
  const ide_main_layout_1 = require("@opensumi/ide-main-layout");
12
11
  const ide_monaco_1 = require("@opensumi/ide-monaco");
12
+ const monaco = tslib_1.__importStar(require("@opensumi/ide-monaco"));
13
13
  const browser_2 = require("@opensumi/ide-monaco/lib/browser");
14
14
  const ide_theme_1 = require("@opensumi/ide-theme");
15
15
  const textModel = tslib_1.__importStar(require("@opensumi/monaco-editor-core/esm/vs/editor/common/model/textModel"));
@@ -24,13 +24,20 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
24
24
  this.threads = new Map();
25
25
  this.threadsChangeEmitter = new ide_core_browser_1.Emitter();
26
26
  this.threadsCommentChangeEmitter = new ide_core_browser_1.Emitter();
27
+ this.commentRangeProviderChangeEmitter = new ide_core_browser_1.Emitter();
28
+ this.onDidChangeCurrentCommentThreadEmitter = new ide_core_browser_1.Emitter();
27
29
  this.threadsCreatedEmitter = new ide_core_browser_1.Emitter();
28
30
  this.rangeProviderMap = new Map();
29
31
  this.rangeOwner = new Map();
30
32
  this.providerDecorationCache = new ide_core_browser_1.LRUCache(10000);
33
+ this.commentRangeDecorationMap = new Map();
31
34
  // 默认在 file 协议和 git 协议中显示评论数据
32
- this.shouldShowCommentsSchemes = new Set(['file', 'git']);
35
+ this.shouldShowCommentsSchemes = new Set(['file', 'git', 'diff']);
33
36
  this.decorationProviderDisposer = ide_core_browser_1.Disposable.NULL;
37
+ this.activeThreadDecorationIds = [];
38
+ this.allEditors = [];
39
+ this.editorCommentingRangeSpaceReservedMap = new Map();
40
+ this.editorLineDecorationsWidthMap = new Map();
34
41
  }
35
42
  get commentsThreads() {
36
43
  return [...this.threads.values()];
@@ -56,6 +63,15 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
56
63
  get onThreadsCreated() {
57
64
  return this.threadsCreatedEmitter.event;
58
65
  }
66
+ get onCommentRangeProviderChange() {
67
+ return this.commentRangeProviderChangeEmitter.event;
68
+ }
69
+ get onDidChangeCurrentCommentThread() {
70
+ return this.onDidChangeCurrentCommentThreadEmitter.event;
71
+ }
72
+ setCurrentCommentThread(thread) {
73
+ this.onDidChangeCurrentCommentThreadEmitter.fire(thread);
74
+ }
59
75
  /**
60
76
  * -------------------------------- IMPORTANT --------------------------------
61
77
  * 需要注意区分 model.IModelDecorationOptions 与 monaco.editor.IModelDecorationOptions 两个类型
@@ -70,19 +86,78 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
70
86
  // 对于新增的空的 thread,默认显示当前用户的头像,否则使用第一个用户的头像
71
87
  const avatar = thread.comments.length === 0 ? this.currentAuthorAvatar : (_a = thread.comments[0].author.iconPath) === null || _a === void 0 ? void 0 : _a.toString();
72
88
  const icon = avatar
73
- ? this.iconService.fromIcon('', avatar, ide_theme_1.IconType.Background)
74
- : this.iconService.fromString('$(comment-unresolved)');
89
+ ? `${this.iconService.fromIcon('', avatar, ide_theme_1.IconType.Background)} avatar-icon`
90
+ : this.iconService.fromString('$(comment)');
75
91
  const decorationOptions = {
76
92
  description: 'comments-thread-decoration',
77
- // 创建评论显示在 glyph margin 处
78
- glyphMarginClassName: ['comments-decoration', 'comments-thread', icon].join(' '),
93
+ glyphMarginClassName: avatar
94
+ ? ['comment-thread', icon].join(' ')
95
+ : ['comment-range', 'comment-thread', icon].join(' '),
96
+ };
97
+ return textModel.ModelDecorationOptions.createDynamic(decorationOptions);
98
+ }
99
+ updateActiveThreadDecoration(thread) {
100
+ var _a;
101
+ const editor = this.getCurrentEditor(thread === null || thread === void 0 ? void 0 : thread.uri);
102
+ if (!editor) {
103
+ return;
104
+ }
105
+ (_a = this.currentThreadCollapseStateListener) === null || _a === void 0 ? void 0 : _a.dispose();
106
+ const newDecoration = [];
107
+ if (thread) {
108
+ const range = thread.range;
109
+ if (!thread.isCollapsed) {
110
+ this.currentThreadCollapseStateListener = thread.onDidChangeCollapsibleState((state) => {
111
+ if (state === common_1.CommentThreadCollapsibleState.Collapsed) {
112
+ this.updateActiveThreadDecoration(undefined);
113
+ }
114
+ });
115
+ newDecoration.push({
116
+ range,
117
+ options: this.createThreadRangeActiveDecoration(),
118
+ });
119
+ }
120
+ }
121
+ this.activeThreadDecorationIds = editor.monacoEditor.deltaDecorations(this.activeThreadDecorationIds, newDecoration);
122
+ }
123
+ createDottedRangeDecoration() {
124
+ const decorationOptions = {
125
+ description: 'comments-multiline-hover-decoration',
126
+ linesDecorationsClassName: ['comment-range', 'multiline-add'].join(' '),
79
127
  };
80
128
  return textModel.ModelDecorationOptions.createDynamic(decorationOptions);
81
129
  }
82
130
  createHoverDecoration() {
83
131
  const decorationOptions = {
84
132
  description: 'comments-hover-decoration',
85
- linesDecorationsClassName: ['comments-decoration', 'comments-add', (0, ide_core_browser_1.getIcon)('add-comments')].join(' '),
133
+ linesDecorationsClassName: ['comment-range', 'line-hover', 'comment-add'].join(' '),
134
+ };
135
+ return textModel.ModelDecorationOptions.createDynamic(decorationOptions);
136
+ }
137
+ createThreadRangeActiveDecoration() {
138
+ const activeDecorationOptions = {
139
+ description: 'comments-thread-range-active-decoration',
140
+ isWholeLine: false,
141
+ zIndex: 20,
142
+ className: 'comment-thread-range-current',
143
+ shouldFillLineOnLineBreak: true,
144
+ };
145
+ return textModel.ModelDecorationOptions.createDynamic(activeDecorationOptions);
146
+ }
147
+ createThreadRangeDecoration() {
148
+ const activeDecorationOptions = {
149
+ description: 'comments-thread-range-decoration',
150
+ isWholeLine: false,
151
+ zIndex: 20,
152
+ className: 'comment-thread-range',
153
+ shouldFillLineOnLineBreak: true,
154
+ };
155
+ return textModel.ModelDecorationOptions.createDynamic(activeDecorationOptions);
156
+ }
157
+ createCommentRangeDecoration() {
158
+ const decorationOptions = {
159
+ description: 'comments-range-decoration',
160
+ linesDecorationsClassName: ['comment-range', 'comment-diff-added'].join(' '),
86
161
  };
87
162
  return textModel.ModelDecorationOptions.createDynamic(decorationOptions);
88
163
  }
@@ -107,34 +182,43 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
107
182
  }));
108
183
  this.registerDecorationProvider();
109
184
  }
185
+ getCurrentEditor(uri) {
186
+ var _a;
187
+ if (uri) {
188
+ for (const editor of this.allEditors) {
189
+ if ((_a = editor.currentUri) === null || _a === void 0 ? void 0 : _a.isEqual(uri)) {
190
+ this.editor = editor;
191
+ return editor;
192
+ }
193
+ }
194
+ }
195
+ return this.editor;
196
+ }
110
197
  handleOnCreateEditor(editor) {
198
+ this.allEditors.push(editor);
199
+ this.editor = editor;
111
200
  const disposer = new ide_core_browser_1.Disposable();
201
+ let commentRangeDecorationIds = [];
202
+ let hasHiddenArea = false;
112
203
  disposer.addDispose(editor.monacoEditor.onMouseDown((event) => {
113
204
  if (event.target.type === browser_2.monacoBrowser.editor.MouseTargetType.GUTTER_LINE_DECORATIONS &&
114
205
  event.target.element &&
115
- event.target.element.className.indexOf('comments-add') > -1) {
206
+ event.target.element.className.indexOf('comment-add') > -1) {
116
207
  const { target } = event;
117
208
  if (target && target.range) {
118
209
  const { range } = target;
119
- // 如果已经存在一个待输入的评论组件,则不创建新的
120
- if (!this.commentsThreads.some((thread) => thread.comments.length === 0 &&
121
- thread.uri.isEqual(editor.currentUri) &&
122
- thread.range.startLineNumber === range.startLineNumber)) {
123
- const thread = this.createThread(editor.currentUri, range);
124
- thread.show(editor);
125
- }
210
+ this.startCommentRange = range;
126
211
  event.event.stopPropagation();
127
212
  }
128
213
  }
129
214
  else if (event.target.type === browser_2.monacoBrowser.editor.MouseTargetType.GUTTER_GLYPH_MARGIN &&
130
215
  event.target.element &&
131
- event.target.element.className.indexOf('comments-thread') > -1) {
216
+ event.target.element.className.indexOf('comment-thread') > -1) {
132
217
  const { target } = event;
133
218
  if (target && target.range) {
134
219
  const { range } = target;
135
- const threads = this.commentsThreads.filter((thread) => thread.uri.isEqual(editor.currentUri) && thread.range.startLineNumber === range.startLineNumber);
220
+ const threads = this.commentsThreads.filter((thread) => thread.uri.isEqual(editor.currentUri) && thread.range.endLineNumber === range.endLineNumber);
136
221
  if (threads.length) {
137
- // 判断当前 widget 是否是显示的
138
222
  const isShowWidget = threads.some((thread) => thread.isShowWidget(editor));
139
223
  if (isShowWidget) {
140
224
  threads.forEach((thread) => thread.hide(editor));
@@ -147,45 +231,412 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
147
231
  event.event.stopPropagation();
148
232
  }
149
233
  }));
150
- let oldDecorations = [];
151
- disposer.addDispose(editor.monacoEditor.onMouseMove((0, debounce_1.default)(async (event) => {
234
+ disposer.addDispose(editor.monacoEditor.onMouseUp(async (event) => {
235
+ if (this.startCommentRange) {
236
+ if (hasHiddenArea) {
237
+ this.renderCommentRange(editor);
238
+ hasHiddenArea = false;
239
+ this.startCommentRange = null;
240
+ this.endCommentRange = null;
241
+ return;
242
+ }
243
+ let range = this.startCommentRange;
244
+ if (this.endCommentRange) {
245
+ if (this.endCommentRange.startLineNumber < this.startCommentRange.startLineNumber) {
246
+ range.startColumn = this.endCommentRange.startColumn;
247
+ range.startLineNumber = this.endCommentRange.startLineNumber;
248
+ }
249
+ else {
250
+ range.endColumn = this.endCommentRange.endColumn;
251
+ range.endLineNumber = this.endCommentRange.endLineNumber;
252
+ }
253
+ }
254
+ if (editor.currentUri) {
255
+ range = await this.getValidRange(range, editor.currentUri);
256
+ }
257
+ if (range) {
258
+ if (!this.commentsThreads.some((thread) => thread.comments.length === 0 &&
259
+ thread.uri.isEqual(editor.currentUri) &&
260
+ thread.range.startLineNumber === range.startLineNumber &&
261
+ thread.range.endLineNumber === range.endLineNumber)) {
262
+ const thread = this.createThread(editor.currentUri, range);
263
+ thread.show(editor);
264
+ }
265
+ event.event.stopPropagation();
266
+ }
267
+ }
268
+ else if (event.target.type === browser_2.monacoBrowser.editor.MouseTargetType.GUTTER_LINE_DECORATIONS &&
269
+ event.target.element &&
270
+ event.target.element.className.indexOf('comment-range') > -1 &&
271
+ event.target.element.className.indexOf('comment-thread') < 0) {
272
+ const { target } = event;
273
+ const range = target.range;
274
+ if (range) {
275
+ if (!this.commentsThreads.some((thread) => thread.comments.length === 0 &&
276
+ thread.uri.isEqual(editor.currentUri) &&
277
+ thread.range.startLineNumber === range.startLineNumber &&
278
+ thread.range.endLineNumber === range.endLineNumber)) {
279
+ const thread = this.createThread(editor.currentUri, range);
280
+ thread.show(editor);
281
+ }
282
+ event.event.stopPropagation();
283
+ }
284
+ }
285
+ this.startCommentRange = null;
286
+ this.endCommentRange = null;
287
+ }));
288
+ disposer.addDispose(editor.monacoEditor.onMouseMove(async (event) => {
289
+ var _a, _b, _c;
152
290
  const uri = editor.currentUri;
153
291
  const range = event.target.range;
154
- if (uri && range && (await this.shouldShowHoverDecoration(uri, range))) {
155
- oldDecorations = editor.monacoEditor.deltaDecorations(oldDecorations, [
156
- {
157
- range: (0, ide_monaco_1.positionToRange)(range.startLineNumber),
158
- options: this.createHoverDecoration(),
159
- },
160
- ]);
292
+ // 多行评论
293
+ if (this.startCommentRange) {
294
+ if (!((_a = event.target.element) === null || _a === void 0 ? void 0 : _a.className)) {
295
+ if ((_c = (_b = event.target.element) === null || _b === void 0 ? void 0 : _b.offsetParent) === null || _c === void 0 ? void 0 : _c.className.includes('diff-hidden-lines')) {
296
+ // 当多行评论跨过折叠代码时,不创建评论
297
+ hasHiddenArea = true;
298
+ }
299
+ }
300
+ if (uri && range) {
301
+ let selection = {
302
+ startLineNumber: this.startCommentRange.startLineNumber,
303
+ endLineNumber: range.endLineNumber,
304
+ startColumn: this.startCommentRange.startColumn,
305
+ endColumn: range.endColumn,
306
+ };
307
+ if (this.startCommentRange.startLineNumber > range.startLineNumber) {
308
+ selection = {
309
+ startLineNumber: range.startLineNumber,
310
+ endLineNumber: this.startCommentRange.endLineNumber,
311
+ startColumn: range.startColumn,
312
+ endColumn: this.startCommentRange.endColumn,
313
+ };
314
+ }
315
+ this.renderCommentRange(editor, selection);
316
+ this.endCommentRange = range;
317
+ }
161
318
  }
162
319
  else {
163
- oldDecorations = editor.monacoEditor.deltaDecorations(oldDecorations, []);
320
+ if (uri && range && (await this.shouldShowHoverDecoration(uri, range))) {
321
+ const newDecorations = [
322
+ {
323
+ range: (0, ide_monaco_1.positionToRange)(range.startLineNumber),
324
+ options: this.createHoverDecoration(),
325
+ },
326
+ ];
327
+ commentRangeDecorationIds = editor.monacoEditor.deltaDecorations(commentRangeDecorationIds, newDecorations);
328
+ }
329
+ }
330
+ }));
331
+ disposer.addDispose(editor.monacoEditor.onMouseLeave(async (event) => {
332
+ var _a;
333
+ const range = (_a = event.target) === null || _a === void 0 ? void 0 : _a.range;
334
+ const newDecorations = [];
335
+ if (!this.startCommentRange && range) {
336
+ newDecorations.push({
337
+ range: (0, ide_monaco_1.positionToRange)(range.startLineNumber),
338
+ options: this.createCommentRangeDecoration(),
339
+ });
340
+ }
341
+ commentRangeDecorationIds = editor.monacoEditor.deltaDecorations(commentRangeDecorationIds, newDecorations);
342
+ }));
343
+ disposer.addDispose(this.onCommentRangeProviderChange(() => {
344
+ this.renderCommentRange(editor);
345
+ }));
346
+ disposer.addDispose(ide_core_browser_1.Event.any(this.onThreadsChanged, this.onThreadsCommentChange, this.onThreadsCreated)((thread) => {
347
+ const editor = this.getCurrentEditor(thread.uri);
348
+ if (editor) {
349
+ this.renderCommentRange(editor);
164
350
  }
165
- }, 10)));
166
- disposer.addDispose(editor.monacoEditor.onMouseLeave((0, debounce_1.default)(() => {
167
- oldDecorations = editor.monacoEditor.deltaDecorations(oldDecorations, []);
168
- }, 10)));
351
+ this.updateActiveThreadDecoration(undefined);
352
+ }));
353
+ disposer.addDispose(this.onDidChangeCurrentCommentThread((thread) => {
354
+ this.updateActiveThreadDecoration(thread);
355
+ }));
356
+ this.tryUpdateReservedSpace(editor);
357
+ disposer.addDispose(editor.monacoEditor.onDidChangeModel(() => {
358
+ this.renderCommentRange(editor);
359
+ this.tryUpdateReservedSpace(editor);
360
+ }));
169
361
  return disposer;
170
362
  }
363
+ async getValidRange(range, uri) {
364
+ if (!uri) {
365
+ return range;
366
+ }
367
+ const contributionRanges = await this.getContributionRanges(uri);
368
+ if (contributionRanges.length === 0) {
369
+ return range;
370
+ }
371
+ const validRange = contributionRanges.find((contributionRange) => {
372
+ if (range.startLineNumber >= contributionRange.startLineNumber &&
373
+ range.startLineNumber <= contributionRange.endLineNumber) {
374
+ return true;
375
+ }
376
+ });
377
+ if (validRange) {
378
+ if (validRange.endLineNumber < range.endLineNumber) {
379
+ return {
380
+ startLineNumber: range.startLineNumber,
381
+ startColumn: range.startColumn,
382
+ endLineNumber: validRange.endLineNumber,
383
+ endColumn: validRange.endColumn,
384
+ };
385
+ }
386
+ else {
387
+ return range;
388
+ }
389
+ }
390
+ else {
391
+ return range;
392
+ }
393
+ }
394
+ ensureCommentingRangeReservedAmount(editor) {
395
+ const existing = this.getExistingCommentEditorOptions(editor);
396
+ const lineDecorationsWidth = this.editorLineDecorationsWidthMap.get(editor.getId());
397
+ if (existing.lineDecorationsWidth !== lineDecorationsWidth) {
398
+ editor.updateOptions({
399
+ lineDecorationsWidth: this.getWithCommentsLineDecorationWidth(editor, existing.lineDecorationsWidth),
400
+ });
401
+ }
402
+ }
403
+ async tryUpdateReservedSpace(editor) {
404
+ if (!editor) {
405
+ return;
406
+ }
407
+ let commentingRangeSpaceReserved = this.editorCommentingRangeSpaceReservedMap.get(editor.getId()) || false;
408
+ const shouldShowComments = editor.currentUri ? this.shouldShowCommentsSchemes.has(editor.currentUri.scheme) : false;
409
+ const hasComments = this.commentsThreads.some((thread) => thread.uri.isEqual(editor.currentUri) && thread.comments.length > 0);
410
+ const hasCommentsOrRanges = shouldShowComments || hasComments;
411
+ if (hasCommentsOrRanges) {
412
+ if (!commentingRangeSpaceReserved) {
413
+ commentingRangeSpaceReserved = true;
414
+ const { lineDecorationsWidth, extraEditorClassName } = this.getExistingCommentEditorOptions(editor);
415
+ const newOptions = this.getWithCommentsEditorOptions(editor, extraEditorClassName, lineDecorationsWidth);
416
+ this.updateEditorLayoutOptions(editor, newOptions.extraEditorClassName, newOptions.lineDecorationsWidth);
417
+ }
418
+ else {
419
+ this.ensureCommentingRangeReservedAmount(editor);
420
+ }
421
+ }
422
+ else if (!hasCommentsOrRanges && commentingRangeSpaceReserved) {
423
+ commentingRangeSpaceReserved = false;
424
+ const { lineDecorationsWidth, extraEditorClassName } = this.getExistingCommentEditorOptions(editor);
425
+ const newOptions = this.getWithoutCommentsEditorOptions(editor, extraEditorClassName, lineDecorationsWidth);
426
+ this.updateEditorLayoutOptions(editor, newOptions.extraEditorClassName, newOptions.lineDecorationsWidth);
427
+ }
428
+ this.editorCommentingRangeSpaceReservedMap.set(editor.getId(), commentingRangeSpaceReserved);
429
+ }
430
+ getExistingCommentEditorOptions(editor) {
431
+ const lineDecorationsWidth = editor.monacoEditor.getOption(monaco.EditorOption.lineDecorationsWidth);
432
+ let extraEditorClassName = [];
433
+ const configuredExtraClassName = editor.monacoEditor.getRawOptions().extraEditorClassName;
434
+ if (configuredExtraClassName) {
435
+ extraEditorClassName = configuredExtraClassName.split(' ');
436
+ }
437
+ return { lineDecorationsWidth, extraEditorClassName };
438
+ }
439
+ getWithoutCommentsEditorOptions(editor, extraEditorClassName, startingLineDecorationsWidth) {
440
+ let lineDecorationsWidth = startingLineDecorationsWidth;
441
+ const inlineCommentPos = extraEditorClassName.findIndex((name) => name === 'inline-comment');
442
+ if (inlineCommentPos >= 0) {
443
+ extraEditorClassName.splice(inlineCommentPos, 1);
444
+ }
445
+ const options = editor.monacoEditor.getOptions();
446
+ if (options.get(monaco.EditorOption.folding) && options.get(monaco.EditorOption.showFoldingControls) !== 'never') {
447
+ lineDecorationsWidth += 11; // 11 comes from https://github.com/microsoft/vscode/blob/94ee5f58619d59170983f453fe78f156c0cc73a3/src/vs/workbench/contrib/comments/browser/media/review.css#L485
448
+ }
449
+ lineDecorationsWidth -= 24;
450
+ return { extraEditorClassName, lineDecorationsWidth };
451
+ }
452
+ updateEditorLayoutOptions(editor, extraEditorClassName, lineDecorationsWidth) {
453
+ editor.updateOptions({
454
+ extraEditorClassName: extraEditorClassName.join(' '),
455
+ lineDecorationsWidth,
456
+ });
457
+ }
458
+ getWithCommentsEditorOptions(editor, extraEditorClassName, startingLineDecorationsWidth) {
459
+ extraEditorClassName.push('inline-comment');
460
+ return {
461
+ lineDecorationsWidth: this.getWithCommentsLineDecorationWidth(editor, startingLineDecorationsWidth),
462
+ extraEditorClassName,
463
+ };
464
+ }
465
+ getWithCommentsLineDecorationWidth(editor, startingLineDecorationsWidth) {
466
+ let lineDecorationsWidth = startingLineDecorationsWidth;
467
+ const options = editor.monacoEditor.getOptions();
468
+ if (options.get(monaco.EditorOption.folding) && options.get(monaco.EditorOption.showFoldingControls) !== 'never') {
469
+ lineDecorationsWidth -= 11;
470
+ }
471
+ lineDecorationsWidth += 24;
472
+ this.editorLineDecorationsWidthMap.set(editor.getId(), lineDecorationsWidth);
473
+ return lineDecorationsWidth;
474
+ }
475
+ async renderCommentRange(editor, selection = {
476
+ startLineNumber: 0,
477
+ endLineNumber: 0,
478
+ startColumn: 0,
479
+ endColumn: 0,
480
+ }) {
481
+ if (!editor.currentUri) {
482
+ return;
483
+ }
484
+ const contributionRanges = await this.getContributionRanges(editor.currentUri);
485
+ if (contributionRanges.length > 0) {
486
+ const newDecorations = [];
487
+ contributionRanges.map((contributionRange) => {
488
+ if (selection.startLineNumber === 0 && selection.endLineNumber === 0) {
489
+ newDecorations.push({
490
+ range: contributionRange,
491
+ options: this.createCommentRangeDecoration(),
492
+ });
493
+ }
494
+ else if (selection.startLineNumber <= contributionRange.startLineNumber &&
495
+ selection.endLineNumber >= contributionRange.endLineNumber) {
496
+ newDecorations.push(...[
497
+ {
498
+ range: contributionRange,
499
+ options: this.createDottedRangeDecoration(),
500
+ },
501
+ {
502
+ range: contributionRange,
503
+ options: this.createThreadRangeDecoration(),
504
+ },
505
+ ]);
506
+ }
507
+ else if (selection.endLineNumber >= contributionRange.endLineNumber) {
508
+ if (selection.startLineNumber <= contributionRange.endLineNumber) {
509
+ // 存在交集
510
+ const selectionRange = {
511
+ startLineNumber: selection.startLineNumber,
512
+ endLineNumber: contributionRange.endLineNumber,
513
+ startColumn: selection.startColumn,
514
+ endColumn: contributionRange.endColumn,
515
+ };
516
+ const topCommentRange = {
517
+ startLineNumber: contributionRange.startLineNumber,
518
+ endLineNumber: selectionRange.startLineNumber - 1,
519
+ startColumn: contributionRange.startColumn,
520
+ endColumn: selectionRange.endColumn,
521
+ };
522
+ newDecorations.push(...[
523
+ {
524
+ range: topCommentRange,
525
+ options: this.createCommentRangeDecoration(),
526
+ },
527
+ {
528
+ range: selectionRange,
529
+ options: this.createDottedRangeDecoration(),
530
+ },
531
+ {
532
+ range: selectionRange,
533
+ options: this.createThreadRangeDecoration(),
534
+ },
535
+ ]);
536
+ }
537
+ else {
538
+ newDecorations.push({
539
+ range: contributionRange,
540
+ options: this.createCommentRangeDecoration(),
541
+ });
542
+ }
543
+ }
544
+ else if (selection.endLineNumber < contributionRange.endLineNumber) {
545
+ if (selection.endLineNumber >= contributionRange.startLineNumber) {
546
+ // 存在交集
547
+ if (selection.startLineNumber >= contributionRange.startLineNumber) {
548
+ const topCommentRange = {
549
+ startLineNumber: contributionRange.startLineNumber,
550
+ startColumn: contributionRange.startColumn,
551
+ endLineNumber: selection.startLineNumber - 1,
552
+ endColumn: selection.startColumn,
553
+ };
554
+ const bottomCommentRange = {
555
+ startLineNumber: selection.endLineNumber + 1,
556
+ startColumn: selection.endColumn,
557
+ endLineNumber: contributionRange.endLineNumber,
558
+ endColumn: contributionRange.endColumn,
559
+ };
560
+ const decorations = selection.startLineNumber !== contributionRange.startLineNumber
561
+ ? [
562
+ {
563
+ range: topCommentRange,
564
+ options: this.createCommentRangeDecoration(),
565
+ },
566
+ ]
567
+ : [];
568
+ decorations.push({
569
+ range: selection,
570
+ options: this.createDottedRangeDecoration(),
571
+ });
572
+ decorations.push({
573
+ range: selection,
574
+ options: this.createThreadRangeDecoration(),
575
+ });
576
+ decorations.push({
577
+ range: bottomCommentRange,
578
+ options: this.createCommentRangeDecoration(),
579
+ });
580
+ newDecorations.push(...decorations);
581
+ }
582
+ else {
583
+ const selectionRange = {
584
+ startLineNumber: contributionRange.startLineNumber,
585
+ startColumn: contributionRange.startColumn,
586
+ endLineNumber: selection.endLineNumber,
587
+ endColumn: selection.endColumn,
588
+ };
589
+ const bottomCommentRange = {
590
+ startLineNumber: selectionRange.endLineNumber + 1,
591
+ startColumn: selectionRange.endColumn,
592
+ endLineNumber: contributionRange.endLineNumber,
593
+ endColumn: contributionRange.endColumn,
594
+ };
595
+ newDecorations.push(...[
596
+ {
597
+ range: selectionRange,
598
+ options: this.createDottedRangeDecoration(),
599
+ },
600
+ {
601
+ range: selectionRange,
602
+ options: this.createThreadRangeDecoration(),
603
+ },
604
+ {
605
+ range: bottomCommentRange,
606
+ options: this.createCommentRangeDecoration(),
607
+ },
608
+ ]);
609
+ }
610
+ }
611
+ else {
612
+ newDecorations.push({
613
+ range: contributionRange,
614
+ options: this.createCommentRangeDecoration(),
615
+ });
616
+ }
617
+ }
618
+ });
619
+ const commentRangeDecorationIds = this.commentRangeDecorationMap.get(editor.currentUri.toString()) || [];
620
+ this.commentRangeDecorationMap.set(editor.currentUri.toString(), editor.monacoEditor.deltaDecorations(commentRangeDecorationIds, newDecorations));
621
+ }
622
+ else {
623
+ this.commentRangeDecorationMap.set(editor.currentUri.toString(), []);
624
+ }
625
+ }
171
626
  async shouldShowHoverDecoration(uri, range) {
172
627
  if (!this.shouldShowCommentsSchemes.has(uri.scheme)) {
173
628
  return false;
174
629
  }
175
630
  const contributionRanges = await this.getContributionRanges(uri);
176
- const isProviderRanges = contributionRanges.some((contributionRange) => range.startLineNumber >= contributionRange.startLineNumber &&
177
- range.startLineNumber <= contributionRange.endLineNumber);
178
- // 如果不支持对同一行进行多个评论,那么过滤掉当前有 thread 行号的 decoration
179
- const isShowHoverToSingleLine = this.isMultiCommentsForSingleLine ||
180
- !this.commentsThreads.some((thread) => thread.uri.isEqual(uri) && thread.range.startLineNumber === range.startLineNumber);
181
- return isProviderRanges && isShowHoverToSingleLine;
631
+ const isProviderRanges = contributionRanges.some((contributionRange) => range.startLineNumber <= contributionRange.endLineNumber);
632
+ return isProviderRanges;
182
633
  }
183
634
  createThread(uri, range, options = {
184
635
  comments: [],
185
636
  readOnly: false,
186
637
  }) {
187
638
  // 获取当前 range 的 providerId,用于 commentController contextKey 的生成
188
- const providerId = this.getProviderIdsByLine(range.startLineNumber)[0];
639
+ const providerId = this.getProviderIdsByLine(range.endLineNumber)[0];
189
640
  const thread = this.injector.get(comments_thread_1.CommentsThread, [uri, range, providerId, options]);
190
641
  thread.onDispose(() => {
191
642
  this.threads.delete(thread.id);
@@ -226,11 +677,16 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
226
677
  return childs;
227
678
  }
228
679
  handleCommentContentNode(parent) {
680
+ var _a;
229
681
  const childs = [];
230
682
  for (const thread of parent.threads) {
231
683
  const [first] = thread.comments;
232
684
  const comment = typeof first.body === 'string' ? first.body : first.body.value;
233
- childs.push(new tree_node_defined_1.CommentContentNode(this, thread, comment, `[Ln ${thread.range.startLineNumber}]`, first.author.iconPath
685
+ let description = `[Ln ${thread.range.startLineNumber}]`;
686
+ if (thread.range.startLineNumber !== thread.range.endLineNumber) {
687
+ description = `[Ln ${thread.range.startLineNumber}-${thread.range.endLineNumber}]`;
688
+ }
689
+ childs.push(new tree_node_defined_1.CommentContentNode(this, thread, comment, description, first.author.iconPath && ((_a = first.author.iconPath) === null || _a === void 0 ? void 0 : _a.authority)
234
690
  ? this.iconService.fromIcon('', first.author.iconPath.toString(), ide_theme_1.IconType.Background)
235
691
  : (0, ide_core_browser_1.getIcon)('message'), first.author, parent.resource, parent));
236
692
  }
@@ -278,12 +734,15 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
278
734
  if (cache) {
279
735
  return await cache.promise;
280
736
  }
281
- const model = this.documentService.getModelReference(uri, 'get-contribution-rages');
737
+ const model = this.documentService.getModelReference(uri, 'Get Comment Range');
282
738
  const rangePromise = [];
283
739
  for (const rangeProvider of this.rangeProviderMap) {
284
740
  const [id, provider] = rangeProvider;
285
741
  rangePromise.push((async () => {
286
- const ranges = await provider.getCommentingRanges(model === null || model === void 0 ? void 0 : model.instance);
742
+ if (!(model === null || model === void 0 ? void 0 : model.instance)) {
743
+ return;
744
+ }
745
+ const ranges = await provider.getCommentingRanges(model.instance);
287
746
  if (ranges && ranges.length) {
288
747
  // FIXME: ranges 会被 Diff uri 的两个 range 互相覆盖,导致可能根据行查不到 provider
289
748
  this.rangeOwner.set(id, ranges);
@@ -333,7 +792,12 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
333
792
  return isCurrentThread;
334
793
  })
335
794
  .map((thread) => ({
336
- range: thread.range,
795
+ range: {
796
+ startLineNumber: thread.range.endLineNumber,
797
+ endLineNumber: thread.range.endLineNumber,
798
+ startColumn: thread.range.endColumn,
799
+ endColumn: thread.range.endColumn,
800
+ },
337
801
  options: this.createThreadDecoration(thread),
338
802
  })),
339
803
  });
@@ -359,6 +823,7 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
359
823
  this.rangeProviderMap.set(id, provider);
360
824
  // 注册一个新的 range provider 后清理掉之前的缓存
361
825
  this.providerDecorationCache.clear();
826
+ this.commentRangeProviderChangeEmitter.fire();
362
827
  return ide_core_browser_1.Disposable.create(() => {
363
828
  this.rangeProviderMap.delete(id);
364
829
  this.rangeOwner.delete(id);
@@ -378,7 +843,6 @@ let CommentsService = class CommentsService extends ide_core_browser_1.Disposabl
378
843
  getProviderIdsByLine(line) {
379
844
  const result = [];
380
845
  if (this.rangeOwner.size === 1) {
381
- // 只有一个provider,直接返回
382
846
  return [this.rangeOwner.keys().next().value];
383
847
  }
384
848
  for (const rangeOwner of this.rangeOwner) {