Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/comment/test/browser/lineCommentCommand.test.ts
3296 views
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
6
import assert from 'assert';
7
import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
8
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
9
import { Selection } from '../../../../common/core/selection.js';
10
import { ICommand } from '../../../../common/editorCommon.js';
11
import { ColorId, MetadataConsts } from '../../../../common/encodedTokenAttributes.js';
12
import { EncodedTokenizationResult, IState, TokenizationRegistry } from '../../../../common/languages.js';
13
import { ILanguageService } from '../../../../common/languages/language.js';
14
import { CommentRule } from '../../../../common/languages/languageConfiguration.js';
15
import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js';
16
import { NullState } from '../../../../common/languages/nullTokenize.js';
17
import { ILinePreflightData, IPreflightData, ISimpleModel, LineCommentCommand, Type } from '../../browser/lineCommentCommand.js';
18
import { testCommand } from '../../../../test/browser/testCommand.js';
19
import { TestLanguageConfigurationService } from '../../../../test/common/modes/testLanguageConfigurationService.js';
20
import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';
21
22
function createTestCommandHelper(commentsConfig: CommentRule, commandFactory: (accessor: ServicesAccessor, selection: Selection) => ICommand): (lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection) => void {
23
return (lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection) => {
24
const languageId = 'commentMode';
25
const prepare = (accessor: ServicesAccessor, disposables: DisposableStore) => {
26
const languageConfigurationService = accessor.get(ILanguageConfigurationService);
27
const languageService = accessor.get(ILanguageService);
28
disposables.add(languageService.registerLanguage({ id: languageId }));
29
disposables.add(languageConfigurationService.register(languageId, {
30
comments: commentsConfig
31
}));
32
};
33
testCommand(lines, languageId, selection, commandFactory, expectedLines, expectedSelection, false, prepare);
34
};
35
}
36
37
suite('Editor Contrib - Line Comment Command', () => {
38
39
ensureNoDisposablesAreLeakedInTestSuite();
40
41
const testLineCommentCommand = createTestCommandHelper(
42
{ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] },
43
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)
44
);
45
46
const testAddLineCommentCommand = createTestCommandHelper(
47
{ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] },
48
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.ForceAdd, true, true)
49
);
50
51
const testLineCommentCommandTokenFirstColumn = createTestCommandHelper(
52
{ lineComment: { comment: '!@#', noIndent: true }, blockComment: ['<!@#', '#@!>'] },
53
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)
54
);
55
56
test('comment single line', function () {
57
testLineCommentCommand(
58
[
59
'some text',
60
'\tsome more text'
61
],
62
new Selection(1, 1, 1, 1),
63
[
64
'!@# some text',
65
'\tsome more text'
66
],
67
new Selection(1, 5, 1, 5)
68
);
69
});
70
71
test('case insensitive', function () {
72
const testLineCommentCommand = createTestCommandHelper(
73
{ lineComment: 'rem' },
74
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)
75
);
76
77
testLineCommentCommand(
78
[
79
'REM some text'
80
],
81
new Selection(1, 1, 1, 1),
82
[
83
'some text'
84
],
85
new Selection(1, 1, 1, 1)
86
);
87
});
88
89
test('comment with token column fixed', function () {
90
testLineCommentCommandTokenFirstColumn(
91
[
92
'some text',
93
'\tsome more text'
94
],
95
new Selection(2, 1, 2, 1),
96
[
97
'some text',
98
'!@# \tsome more text'
99
],
100
new Selection(2, 5, 2, 5)
101
);
102
});
103
104
function createSimpleModel(lines: string[]): ISimpleModel {
105
return {
106
getLineContent: (lineNumber: number) => {
107
return lines[lineNumber - 1];
108
}
109
};
110
}
111
112
function createBasicLinePreflightData(commentTokens: string[]): ILinePreflightData[] {
113
return commentTokens.map((commentString) => {
114
const r: ILinePreflightData = {
115
ignore: false,
116
commentStr: commentString,
117
commentStrOffset: 0,
118
commentStrLength: commentString.length
119
};
120
return r;
121
});
122
}
123
124
test('_analyzeLines', () => {
125
const disposable = new DisposableStore();
126
let r: IPreflightData;
127
128
r = LineCommentCommand._analyzeLines(Type.Toggle, true, createSimpleModel([
129
'\t\t',
130
' ',
131
' c',
132
'\t\td'
133
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1, true, false, disposable.add(new TestLanguageConfigurationService()), 'plaintext');
134
if (!r.supported) {
135
throw new Error(`unexpected`);
136
}
137
138
assert.strictEqual(r.shouldRemoveComments, false);
139
140
// Does not change `commentStr`
141
assert.strictEqual(r.lines[0].commentStr, '//');
142
assert.strictEqual(r.lines[1].commentStr, 'rem');
143
assert.strictEqual(r.lines[2].commentStr, '!@#');
144
assert.strictEqual(r.lines[3].commentStr, '!@#');
145
146
// Fills in `isWhitespace`
147
assert.strictEqual(r.lines[0].ignore, true);
148
assert.strictEqual(r.lines[1].ignore, true);
149
assert.strictEqual(r.lines[2].ignore, false);
150
assert.strictEqual(r.lines[3].ignore, false);
151
152
// Fills in `commentStrOffset`
153
assert.strictEqual(r.lines[0].commentStrOffset, 2);
154
assert.strictEqual(r.lines[1].commentStrOffset, 4);
155
assert.strictEqual(r.lines[2].commentStrOffset, 4);
156
assert.strictEqual(r.lines[3].commentStrOffset, 2);
157
158
159
r = LineCommentCommand._analyzeLines(Type.Toggle, true, createSimpleModel([
160
'\t\t',
161
' rem ',
162
' !@# c',
163
'\t\t!@#d'
164
]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1, true, false, disposable.add(new TestLanguageConfigurationService()), 'plaintext');
165
if (!r.supported) {
166
throw new Error(`unexpected`);
167
}
168
169
assert.strictEqual(r.shouldRemoveComments, true);
170
171
// Does not change `commentStr`
172
assert.strictEqual(r.lines[0].commentStr, '//');
173
assert.strictEqual(r.lines[1].commentStr, 'rem');
174
assert.strictEqual(r.lines[2].commentStr, '!@#');
175
assert.strictEqual(r.lines[3].commentStr, '!@#');
176
177
// Fills in `isWhitespace`
178
assert.strictEqual(r.lines[0].ignore, true);
179
assert.strictEqual(r.lines[1].ignore, false);
180
assert.strictEqual(r.lines[2].ignore, false);
181
assert.strictEqual(r.lines[3].ignore, false);
182
183
// Fills in `commentStrOffset`
184
assert.strictEqual(r.lines[0].commentStrOffset, 2);
185
assert.strictEqual(r.lines[1].commentStrOffset, 4);
186
assert.strictEqual(r.lines[2].commentStrOffset, 4);
187
assert.strictEqual(r.lines[3].commentStrOffset, 2);
188
189
// Fills in `commentStrLength`
190
assert.strictEqual(r.lines[0].commentStrLength, 2);
191
assert.strictEqual(r.lines[1].commentStrLength, 4);
192
assert.strictEqual(r.lines[2].commentStrLength, 4);
193
assert.strictEqual(r.lines[3].commentStrLength, 3);
194
195
disposable.dispose();
196
});
197
198
test('_normalizeInsertionPoint', () => {
199
200
const runTest = (mixedArr: any[], tabSize: number, expected: number[], testName: string) => {
201
const model = createSimpleModel(mixedArr.filter((item, idx) => idx % 2 === 0));
202
const offsets = mixedArr.filter((item, idx) => idx % 2 === 1).map(offset => {
203
return {
204
commentStrOffset: offset,
205
ignore: false
206
};
207
});
208
LineCommentCommand._normalizeInsertionPoint(model, offsets, 1, tabSize);
209
const actual = offsets.map(item => item.commentStrOffset);
210
assert.deepStrictEqual(actual, expected, testName);
211
};
212
213
// Bug 16696:[comment] comments not aligned in this case
214
runTest([
215
' XX', 2,
216
' YY', 4
217
], 4, [0, 0], 'Bug 16696');
218
219
runTest([
220
'\t\t\tXX', 3,
221
' \tYY', 5,
222
' ZZ', 8,
223
'\t\tTT', 2
224
], 4, [2, 5, 8, 2], 'Test1');
225
226
runTest([
227
'\t\t\t XX', 6,
228
' \t\t\t\tYY', 8,
229
' ZZ', 8,
230
'\t\t TT', 6
231
], 4, [2, 5, 8, 2], 'Test2');
232
233
runTest([
234
'\t\t', 2,
235
'\t\t\t', 3,
236
'\t\t\t\t', 4,
237
'\t\t\t', 3
238
], 4, [2, 2, 2, 2], 'Test3');
239
240
runTest([
241
'\t\t', 2,
242
'\t\t\t', 3,
243
'\t\t\t\t', 4,
244
'\t\t\t', 3,
245
' ', 4
246
], 2, [2, 2, 2, 2, 4], 'Test4');
247
248
runTest([
249
'\t\t', 2,
250
'\t\t\t', 3,
251
'\t\t\t\t', 4,
252
'\t\t\t', 3,
253
' ', 4
254
], 4, [1, 1, 1, 1, 4], 'Test5');
255
256
runTest([
257
' \t', 2,
258
' \t', 3,
259
' \t', 4,
260
' ', 4,
261
'\t', 1
262
], 4, [2, 3, 4, 4, 1], 'Test6');
263
264
runTest([
265
' \t\t', 3,
266
' \t\t', 4,
267
' \t\t', 5,
268
' \t', 5,
269
'\t', 1
270
], 4, [2, 3, 4, 4, 1], 'Test7');
271
272
runTest([
273
'\t', 1,
274
' ', 4
275
], 4, [1, 4], 'Test8:4');
276
runTest([
277
'\t', 1,
278
' ', 3
279
], 4, [0, 0], 'Test8:3');
280
runTest([
281
'\t', 1,
282
' ', 2
283
], 4, [0, 0], 'Test8:2');
284
runTest([
285
'\t', 1,
286
' ', 1
287
], 4, [0, 0], 'Test8:1');
288
runTest([
289
'\t', 1,
290
'', 0
291
], 4, [0, 0], 'Test8:0');
292
});
293
294
test('detects indentation', function () {
295
testLineCommentCommand(
296
[
297
'\tsome text',
298
'\tsome more text'
299
],
300
new Selection(2, 2, 1, 1),
301
[
302
'\t!@# some text',
303
'\t!@# some more text'
304
],
305
new Selection(2, 2, 1, 1)
306
);
307
});
308
309
test('detects mixed indentation', function () {
310
testLineCommentCommand(
311
[
312
'\tsome text',
313
' some more text'
314
],
315
new Selection(2, 2, 1, 1),
316
[
317
'\t!@# some text',
318
' !@# some more text'
319
],
320
new Selection(2, 2, 1, 1)
321
);
322
});
323
324
test('ignores whitespace lines', function () {
325
testLineCommentCommand(
326
[
327
'\tsome text',
328
'\t ',
329
'',
330
'\tsome more text'
331
],
332
new Selection(4, 2, 1, 1),
333
[
334
'\t!@# some text',
335
'\t ',
336
'',
337
'\t!@# some more text'
338
],
339
new Selection(4, 2, 1, 1)
340
);
341
});
342
343
test('removes its own', function () {
344
testLineCommentCommand(
345
[
346
'\t!@# some text',
347
'\t ',
348
'\t\t!@# some more text'
349
],
350
new Selection(3, 2, 1, 1),
351
[
352
'\tsome text',
353
'\t ',
354
'\t\tsome more text'
355
],
356
new Selection(3, 2, 1, 1)
357
);
358
});
359
360
test('works in only whitespace', function () {
361
testLineCommentCommand(
362
[
363
'\t ',
364
'\t',
365
'\t\tsome more text'
366
],
367
new Selection(3, 1, 1, 1),
368
[
369
'\t!@# ',
370
'\t!@# ',
371
'\t\tsome more text'
372
],
373
new Selection(3, 1, 1, 1)
374
);
375
});
376
377
test('bug 9697 - whitespace before comment token', function () {
378
testLineCommentCommand(
379
[
380
'\t !@#first',
381
'\tsecond line'
382
],
383
new Selection(1, 1, 1, 1),
384
[
385
'\t first',
386
'\tsecond line'
387
],
388
new Selection(1, 1, 1, 1)
389
);
390
});
391
392
test('bug 10162 - line comment before caret', function () {
393
testLineCommentCommand(
394
[
395
'first!@#',
396
'\tsecond line'
397
],
398
new Selection(1, 1, 1, 1),
399
[
400
'!@# first!@#',
401
'\tsecond line'
402
],
403
new Selection(1, 5, 1, 5)
404
);
405
});
406
407
test('comment single line - leading whitespace', function () {
408
testLineCommentCommand(
409
[
410
'first!@#',
411
'\tsecond line'
412
],
413
new Selection(2, 3, 2, 1),
414
[
415
'first!@#',
416
'\t!@# second line'
417
],
418
new Selection(2, 7, 2, 1)
419
);
420
});
421
422
test('ignores invisible selection', function () {
423
testLineCommentCommand(
424
[
425
'first',
426
'\tsecond line',
427
'third line',
428
'fourth line',
429
'fifth'
430
],
431
new Selection(2, 1, 1, 1),
432
[
433
'!@# first',
434
'\tsecond line',
435
'third line',
436
'fourth line',
437
'fifth'
438
],
439
new Selection(2, 1, 1, 5)
440
);
441
});
442
443
test('multiple lines', function () {
444
testLineCommentCommand(
445
[
446
'first',
447
'\tsecond line',
448
'third line',
449
'fourth line',
450
'fifth'
451
],
452
new Selection(2, 4, 1, 1),
453
[
454
'!@# first',
455
'!@# \tsecond line',
456
'third line',
457
'fourth line',
458
'fifth'
459
],
460
new Selection(2, 8, 1, 5)
461
);
462
});
463
464
test('multiple modes on multiple lines', function () {
465
testLineCommentCommand(
466
[
467
'first',
468
'\tsecond line',
469
'third line',
470
'fourth line',
471
'fifth'
472
],
473
new Selection(4, 4, 3, 1),
474
[
475
'first',
476
'\tsecond line',
477
'!@# third line',
478
'!@# fourth line',
479
'fifth'
480
],
481
new Selection(4, 8, 3, 5)
482
);
483
});
484
485
test('toggle single line', function () {
486
testLineCommentCommand(
487
[
488
'first',
489
'\tsecond line',
490
'third line',
491
'fourth line',
492
'fifth'
493
],
494
new Selection(1, 1, 1, 1),
495
[
496
'!@# first',
497
'\tsecond line',
498
'third line',
499
'fourth line',
500
'fifth'
501
],
502
new Selection(1, 5, 1, 5)
503
);
504
505
testLineCommentCommand(
506
[
507
'!@# first',
508
'\tsecond line',
509
'third line',
510
'fourth line',
511
'fifth'
512
],
513
new Selection(1, 4, 1, 4),
514
[
515
'first',
516
'\tsecond line',
517
'third line',
518
'fourth line',
519
'fifth'
520
],
521
new Selection(1, 1, 1, 1)
522
);
523
});
524
525
test('toggle multiple lines', function () {
526
testLineCommentCommand(
527
[
528
'first',
529
'\tsecond line',
530
'third line',
531
'fourth line',
532
'fifth'
533
],
534
new Selection(2, 4, 1, 1),
535
[
536
'!@# first',
537
'!@# \tsecond line',
538
'third line',
539
'fourth line',
540
'fifth'
541
],
542
new Selection(2, 8, 1, 5)
543
);
544
545
testLineCommentCommand(
546
[
547
'!@# first',
548
'!@# \tsecond line',
549
'third line',
550
'fourth line',
551
'fifth'
552
],
553
new Selection(2, 7, 1, 4),
554
[
555
'first',
556
'\tsecond line',
557
'third line',
558
'fourth line',
559
'fifth'
560
],
561
new Selection(2, 3, 1, 1)
562
);
563
});
564
565
test('issue #5964: Ctrl+/ to create comment when cursor is at the beginning of the line puts the cursor in a strange position', () => {
566
testLineCommentCommand(
567
[
568
'first',
569
'\tsecond line',
570
'third line',
571
'fourth line',
572
'fifth'
573
],
574
new Selection(1, 1, 1, 1),
575
[
576
'!@# first',
577
'\tsecond line',
578
'third line',
579
'fourth line',
580
'fifth'
581
],
582
new Selection(1, 5, 1, 5)
583
);
584
});
585
586
test('issue #35673: Comment hotkeys throws the cursor before the comment', () => {
587
testLineCommentCommand(
588
[
589
'first',
590
'',
591
'\tsecond line',
592
'third line',
593
'fourth line',
594
'fifth'
595
],
596
new Selection(2, 1, 2, 1),
597
[
598
'first',
599
'!@# ',
600
'\tsecond line',
601
'third line',
602
'fourth line',
603
'fifth'
604
],
605
new Selection(2, 5, 2, 5)
606
);
607
608
testLineCommentCommand(
609
[
610
'first',
611
'\t',
612
'\tsecond line',
613
'third line',
614
'fourth line',
615
'fifth'
616
],
617
new Selection(2, 2, 2, 2),
618
[
619
'first',
620
'\t!@# ',
621
'\tsecond line',
622
'third line',
623
'fourth line',
624
'fifth'
625
],
626
new Selection(2, 6, 2, 6)
627
);
628
});
629
630
test('issue #2837 "Add Line Comment" fault when blank lines involved', function () {
631
testAddLineCommentCommand(
632
[
633
' if displayName == "":',
634
' displayName = groupName',
635
' description = getAttr(attributes, "description")',
636
' mailAddress = getAttr(attributes, "mail")',
637
'',
638
' print "||Group name|%s|" % displayName',
639
' print "||Description|%s|" % description',
640
' print "||Email address|[mailto:%s]|" % mailAddress`',
641
],
642
new Selection(1, 1, 8, 56),
643
[
644
' !@# if displayName == "":',
645
' !@# displayName = groupName',
646
' !@# description = getAttr(attributes, "description")',
647
' !@# mailAddress = getAttr(attributes, "mail")',
648
'',
649
' !@# print "||Group name|%s|" % displayName',
650
' !@# print "||Description|%s|" % description',
651
' !@# print "||Email address|[mailto:%s]|" % mailAddress`',
652
],
653
new Selection(1, 1, 8, 60)
654
);
655
});
656
657
test('issue #47004: Toggle comments shouldn\'t move cursor', () => {
658
testAddLineCommentCommand(
659
[
660
' A line',
661
' Another line'
662
],
663
new Selection(2, 7, 1, 1),
664
[
665
' !@# A line',
666
' !@# Another line'
667
],
668
new Selection(2, 11, 1, 1)
669
);
670
});
671
672
test('insertSpace false', () => {
673
const testLineCommentCommand = createTestCommandHelper(
674
{ lineComment: '!@#' },
675
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, false, true)
676
);
677
678
testLineCommentCommand(
679
[
680
'some text'
681
],
682
new Selection(1, 1, 1, 1),
683
[
684
'!@#some text'
685
],
686
new Selection(1, 4, 1, 4)
687
);
688
});
689
690
test('insertSpace false does not remove space', () => {
691
const testLineCommentCommand = createTestCommandHelper(
692
{ lineComment: '!@#' },
693
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, false, true)
694
);
695
696
testLineCommentCommand(
697
[
698
'!@# some text'
699
],
700
new Selection(1, 1, 1, 1),
701
[
702
' some text'
703
],
704
new Selection(1, 1, 1, 1)
705
);
706
});
707
});
708
709
suite('ignoreEmptyLines false', () => {
710
711
ensureNoDisposablesAreLeakedInTestSuite();
712
713
const testLineCommentCommand = createTestCommandHelper(
714
{ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] },
715
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, false)
716
);
717
718
test('does not ignore whitespace lines', () => {
719
testLineCommentCommand(
720
[
721
'\tsome text',
722
'\t ',
723
'',
724
'\tsome more text'
725
],
726
new Selection(4, 2, 1, 1),
727
[
728
'!@# \tsome text',
729
'!@# \t ',
730
'!@# ',
731
'!@# \tsome more text'
732
],
733
new Selection(4, 6, 1, 5)
734
);
735
});
736
737
test('removes its own', function () {
738
testLineCommentCommand(
739
[
740
'\t!@# some text',
741
'\t ',
742
'\t\t!@# some more text'
743
],
744
new Selection(3, 2, 1, 1),
745
[
746
'\tsome text',
747
'\t ',
748
'\t\tsome more text'
749
],
750
new Selection(3, 2, 1, 1)
751
);
752
});
753
754
test('works in only whitespace', function () {
755
testLineCommentCommand(
756
[
757
'\t ',
758
'\t',
759
'\t\tsome more text'
760
],
761
new Selection(3, 1, 1, 1),
762
[
763
'\t!@# ',
764
'\t!@# ',
765
'\t\tsome more text'
766
],
767
new Selection(3, 1, 1, 1)
768
);
769
});
770
771
test('comments single line', function () {
772
testLineCommentCommand(
773
[
774
'some text',
775
'\tsome more text'
776
],
777
new Selection(1, 1, 1, 1),
778
[
779
'!@# some text',
780
'\tsome more text'
781
],
782
new Selection(1, 5, 1, 5)
783
);
784
});
785
786
test('detects indentation', function () {
787
testLineCommentCommand(
788
[
789
'\tsome text',
790
'\tsome more text'
791
],
792
new Selection(2, 2, 1, 1),
793
[
794
'\t!@# some text',
795
'\t!@# some more text'
796
],
797
new Selection(2, 2, 1, 1)
798
);
799
});
800
});
801
802
suite('Editor Contrib - Line Comment As Block Comment', () => {
803
804
ensureNoDisposablesAreLeakedInTestSuite();
805
806
const testLineCommentCommand = createTestCommandHelper(
807
{ lineComment: '', blockComment: ['(', ')'] },
808
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)
809
);
810
811
test('fall back to block comment command', function () {
812
testLineCommentCommand(
813
[
814
'first',
815
'\tsecond line',
816
'third line',
817
'fourth line',
818
'fifth'
819
],
820
new Selection(1, 1, 1, 1),
821
[
822
'( first )',
823
'\tsecond line',
824
'third line',
825
'fourth line',
826
'fifth'
827
],
828
new Selection(1, 3, 1, 3)
829
);
830
});
831
832
test('fall back to block comment command - toggle', function () {
833
testLineCommentCommand(
834
[
835
'(first)',
836
'\tsecond line',
837
'third line',
838
'fourth line',
839
'fifth'
840
],
841
new Selection(1, 7, 1, 2),
842
[
843
'first',
844
'\tsecond line',
845
'third line',
846
'fourth line',
847
'fifth'
848
],
849
new Selection(1, 6, 1, 1)
850
);
851
});
852
853
test('bug 9513 - expand single line to uncomment auto block', function () {
854
testLineCommentCommand(
855
[
856
'first',
857
'\tsecond line',
858
'third line',
859
'fourth line',
860
'fifth'
861
],
862
new Selection(1, 1, 1, 1),
863
[
864
'( first )',
865
'\tsecond line',
866
'third line',
867
'fourth line',
868
'fifth'
869
],
870
new Selection(1, 3, 1, 3)
871
);
872
});
873
874
test('bug 9691 - always expand selection to line boundaries', function () {
875
testLineCommentCommand(
876
[
877
'first',
878
'\tsecond line',
879
'third line',
880
'fourth line',
881
'fifth'
882
],
883
new Selection(3, 2, 1, 3),
884
[
885
'( first',
886
'\tsecond line',
887
'third line )',
888
'fourth line',
889
'fifth'
890
],
891
new Selection(3, 2, 1, 5)
892
);
893
894
testLineCommentCommand(
895
[
896
'(first',
897
'\tsecond line',
898
'third line)',
899
'fourth line',
900
'fifth'
901
],
902
new Selection(3, 11, 1, 2),
903
[
904
'first',
905
'\tsecond line',
906
'third line',
907
'fourth line',
908
'fifth'
909
],
910
new Selection(3, 11, 1, 1)
911
);
912
});
913
});
914
915
suite('Editor Contrib - Line Comment As Block Comment 2', () => {
916
917
ensureNoDisposablesAreLeakedInTestSuite();
918
919
const testLineCommentCommand = createTestCommandHelper(
920
{ lineComment: null, blockComment: ['<!@#', '#@!>'] },
921
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)
922
);
923
924
test('no selection => uses indentation', function () {
925
testLineCommentCommand(
926
[
927
'\t\tfirst\t ',
928
'\t\tsecond line',
929
'\tthird line',
930
'fourth line',
931
'\t\t<!@#fifth#@!>\t\t'
932
],
933
new Selection(1, 1, 1, 1),
934
[
935
'\t\t<!@# first\t #@!>',
936
'\t\tsecond line',
937
'\tthird line',
938
'fourth line',
939
'\t\t<!@#fifth#@!>\t\t'
940
],
941
new Selection(1, 1, 1, 1)
942
);
943
944
testLineCommentCommand(
945
[
946
'\t\t<!@#first\t #@!>',
947
'\t\tsecond line',
948
'\tthird line',
949
'fourth line',
950
'\t\t<!@#fifth#@!>\t\t'
951
],
952
new Selection(1, 1, 1, 1),
953
[
954
'\t\tfirst\t ',
955
'\t\tsecond line',
956
'\tthird line',
957
'fourth line',
958
'\t\t<!@#fifth#@!>\t\t'
959
],
960
new Selection(1, 1, 1, 1)
961
);
962
});
963
964
test('can remove', function () {
965
testLineCommentCommand(
966
[
967
'\t\tfirst\t ',
968
'\t\tsecond line',
969
'\tthird line',
970
'fourth line',
971
'\t\t<!@#fifth#@!>\t\t'
972
],
973
new Selection(5, 1, 5, 1),
974
[
975
'\t\tfirst\t ',
976
'\t\tsecond line',
977
'\tthird line',
978
'fourth line',
979
'\t\tfifth\t\t'
980
],
981
new Selection(5, 1, 5, 1)
982
);
983
984
testLineCommentCommand(
985
[
986
'\t\tfirst\t ',
987
'\t\tsecond line',
988
'\tthird line',
989
'fourth line',
990
'\t\t<!@#fifth#@!>\t\t'
991
],
992
new Selection(5, 3, 5, 3),
993
[
994
'\t\tfirst\t ',
995
'\t\tsecond line',
996
'\tthird line',
997
'fourth line',
998
'\t\tfifth\t\t'
999
],
1000
new Selection(5, 3, 5, 3)
1001
);
1002
1003
testLineCommentCommand(
1004
[
1005
'\t\tfirst\t ',
1006
'\t\tsecond line',
1007
'\tthird line',
1008
'fourth line',
1009
'\t\t<!@#fifth#@!>\t\t'
1010
],
1011
new Selection(5, 4, 5, 4),
1012
[
1013
'\t\tfirst\t ',
1014
'\t\tsecond line',
1015
'\tthird line',
1016
'fourth line',
1017
'\t\tfifth\t\t'
1018
],
1019
new Selection(5, 3, 5, 3)
1020
);
1021
1022
testLineCommentCommand(
1023
[
1024
'\t\tfirst\t ',
1025
'\t\tsecond line',
1026
'\tthird line',
1027
'fourth line',
1028
'\t\t<!@#fifth#@!>\t\t'
1029
],
1030
new Selection(5, 16, 5, 3),
1031
[
1032
'\t\tfirst\t ',
1033
'\t\tsecond line',
1034
'\tthird line',
1035
'fourth line',
1036
'\t\tfifth\t\t'
1037
],
1038
new Selection(5, 8, 5, 3)
1039
);
1040
1041
testLineCommentCommand(
1042
[
1043
'\t\tfirst\t ',
1044
'\t\tsecond line',
1045
'\tthird line',
1046
'fourth line',
1047
'\t\t<!@#fifth#@!>\t\t'
1048
],
1049
new Selection(5, 12, 5, 7),
1050
[
1051
'\t\tfirst\t ',
1052
'\t\tsecond line',
1053
'\tthird line',
1054
'fourth line',
1055
'\t\tfifth\t\t'
1056
],
1057
new Selection(5, 8, 5, 3)
1058
);
1059
1060
testLineCommentCommand(
1061
[
1062
'\t\tfirst\t ',
1063
'\t\tsecond line',
1064
'\tthird line',
1065
'fourth line',
1066
'\t\t<!@#fifth#@!>\t\t'
1067
],
1068
new Selection(5, 18, 5, 18),
1069
[
1070
'\t\tfirst\t ',
1071
'\t\tsecond line',
1072
'\tthird line',
1073
'fourth line',
1074
'\t\tfifth\t\t'
1075
],
1076
new Selection(5, 10, 5, 10)
1077
);
1078
});
1079
1080
test('issue #993: Remove comment does not work consistently in HTML', () => {
1081
testLineCommentCommand(
1082
[
1083
' asd qwe',
1084
' asd qwe',
1085
''
1086
],
1087
new Selection(1, 1, 3, 1),
1088
[
1089
' <!@# asd qwe',
1090
' asd qwe #@!>',
1091
''
1092
],
1093
new Selection(1, 1, 3, 1)
1094
);
1095
1096
testLineCommentCommand(
1097
[
1098
' <!@#asd qwe',
1099
' asd qwe#@!>',
1100
''
1101
],
1102
new Selection(1, 1, 3, 1),
1103
[
1104
' asd qwe',
1105
' asd qwe',
1106
''
1107
],
1108
new Selection(1, 1, 3, 1)
1109
);
1110
});
1111
});
1112
1113
suite('Editor Contrib - Line Comment in mixed modes', () => {
1114
1115
ensureNoDisposablesAreLeakedInTestSuite();
1116
1117
const OUTER_LANGUAGE_ID = 'outerMode';
1118
const INNER_LANGUAGE_ID = 'innerMode';
1119
1120
class OuterMode extends Disposable {
1121
private readonly languageId = OUTER_LANGUAGE_ID;
1122
constructor(
1123
commentsConfig: CommentRule,
1124
@ILanguageService languageService: ILanguageService,
1125
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
1126
) {
1127
super();
1128
this._register(languageService.registerLanguage({ id: this.languageId }));
1129
this._register(languageConfigurationService.register(this.languageId, {
1130
comments: commentsConfig
1131
}));
1132
1133
this._register(TokenizationRegistry.register(this.languageId, {
1134
getInitialState: (): IState => NullState,
1135
tokenize: () => {
1136
throw new Error('not implemented');
1137
},
1138
tokenizeEncoded: (line: string, hasEOL: boolean, state: IState): EncodedTokenizationResult => {
1139
const languageId = (/^ /.test(line) ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID);
1140
const encodedLanguageId = languageService.languageIdCodec.encodeLanguageId(languageId);
1141
1142
const tokens = new Uint32Array(1 << 1);
1143
tokens[(0 << 1)] = 0;
1144
tokens[(0 << 1) + 1] = (
1145
(ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)
1146
| (encodedLanguageId << MetadataConsts.LANGUAGEID_OFFSET)
1147
);
1148
return new EncodedTokenizationResult(tokens, state);
1149
}
1150
}));
1151
}
1152
}
1153
1154
class InnerMode extends Disposable {
1155
private readonly languageId = INNER_LANGUAGE_ID;
1156
constructor(
1157
commentsConfig: CommentRule,
1158
@ILanguageService languageService: ILanguageService,
1159
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
1160
) {
1161
super();
1162
this._register(languageService.registerLanguage({ id: this.languageId }));
1163
this._register(languageConfigurationService.register(this.languageId, {
1164
comments: commentsConfig
1165
}));
1166
}
1167
}
1168
1169
function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {
1170
1171
const setup = (accessor: ServicesAccessor, disposables: DisposableStore) => {
1172
const instantiationService = accessor.get(IInstantiationService);
1173
disposables.add(instantiationService.createInstance(OuterMode, { lineComment: '//', blockComment: ['/*', '*/'] }));
1174
disposables.add(instantiationService.createInstance(InnerMode, { lineComment: null, blockComment: ['{/*', '*/}'] }));
1175
};
1176
1177
testCommand(
1178
lines,
1179
OUTER_LANGUAGE_ID,
1180
selection,
1181
(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true),
1182
expectedLines,
1183
expectedSelection,
1184
true,
1185
setup
1186
);
1187
}
1188
1189
test('issue #24047 (part 1): Commenting code in JSX files', () => {
1190
testLineCommentCommand(
1191
[
1192
'import React from \'react\';',
1193
'const Loader = () => (',
1194
' <div>',
1195
' Loading...',
1196
' </div>',
1197
');',
1198
'export default Loader;'
1199
],
1200
new Selection(1, 1, 7, 22),
1201
[
1202
'// import React from \'react\';',
1203
'// const Loader = () => (',
1204
'// <div>',
1205
'// Loading...',
1206
'// </div>',
1207
'// );',
1208
'// export default Loader;'
1209
],
1210
new Selection(1, 4, 7, 25),
1211
);
1212
});
1213
1214
test('issue #24047 (part 2): Commenting code in JSX files', () => {
1215
testLineCommentCommand(
1216
[
1217
'import React from \'react\';',
1218
'const Loader = () => (',
1219
' <div>',
1220
' Loading...',
1221
' </div>',
1222
');',
1223
'export default Loader;'
1224
],
1225
new Selection(3, 4, 3, 4),
1226
[
1227
'import React from \'react\';',
1228
'const Loader = () => (',
1229
' {/* <div> */}',
1230
' Loading...',
1231
' </div>',
1232
');',
1233
'export default Loader;'
1234
],
1235
new Selection(3, 8, 3, 8),
1236
);
1237
});
1238
1239
test('issue #36173: Commenting code in JSX tag body', () => {
1240
testLineCommentCommand(
1241
[
1242
'<div>',
1243
' {123}',
1244
'</div>',
1245
],
1246
new Selection(2, 4, 2, 4),
1247
[
1248
'<div>',
1249
' {/* {123} */}',
1250
'</div>',
1251
],
1252
new Selection(2, 8, 2, 8),
1253
);
1254
});
1255
});
1256
1257