Path: blob/main/src/vs/editor/contrib/comment/test/browser/lineCommentCommand.test.ts
3296 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import assert from 'assert';6import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';7import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';8import { Selection } from '../../../../common/core/selection.js';9import { ICommand } from '../../../../common/editorCommon.js';10import { ColorId, MetadataConsts } from '../../../../common/encodedTokenAttributes.js';11import { EncodedTokenizationResult, IState, TokenizationRegistry } from '../../../../common/languages.js';12import { ILanguageService } from '../../../../common/languages/language.js';13import { CommentRule } from '../../../../common/languages/languageConfiguration.js';14import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js';15import { NullState } from '../../../../common/languages/nullTokenize.js';16import { ILinePreflightData, IPreflightData, ISimpleModel, LineCommentCommand, Type } from '../../browser/lineCommentCommand.js';17import { testCommand } from '../../../../test/browser/testCommand.js';18import { TestLanguageConfigurationService } from '../../../../test/common/modes/testLanguageConfigurationService.js';19import { IInstantiationService, ServicesAccessor } from '../../../../../platform/instantiation/common/instantiation.js';2021function createTestCommandHelper(commentsConfig: CommentRule, commandFactory: (accessor: ServicesAccessor, selection: Selection) => ICommand): (lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection) => void {22return (lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection) => {23const languageId = 'commentMode';24const prepare = (accessor: ServicesAccessor, disposables: DisposableStore) => {25const languageConfigurationService = accessor.get(ILanguageConfigurationService);26const languageService = accessor.get(ILanguageService);27disposables.add(languageService.registerLanguage({ id: languageId }));28disposables.add(languageConfigurationService.register(languageId, {29comments: commentsConfig30}));31};32testCommand(lines, languageId, selection, commandFactory, expectedLines, expectedSelection, false, prepare);33};34}3536suite('Editor Contrib - Line Comment Command', () => {3738ensureNoDisposablesAreLeakedInTestSuite();3940const testLineCommentCommand = createTestCommandHelper(41{ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] },42(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)43);4445const testAddLineCommentCommand = createTestCommandHelper(46{ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] },47(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.ForceAdd, true, true)48);4950const testLineCommentCommandTokenFirstColumn = createTestCommandHelper(51{ lineComment: { comment: '!@#', noIndent: true }, blockComment: ['<!@#', '#@!>'] },52(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)53);5455test('comment single line', function () {56testLineCommentCommand(57[58'some text',59'\tsome more text'60],61new Selection(1, 1, 1, 1),62[63'!@# some text',64'\tsome more text'65],66new Selection(1, 5, 1, 5)67);68});6970test('case insensitive', function () {71const testLineCommentCommand = createTestCommandHelper(72{ lineComment: 'rem' },73(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)74);7576testLineCommentCommand(77[78'REM some text'79],80new Selection(1, 1, 1, 1),81[82'some text'83],84new Selection(1, 1, 1, 1)85);86});8788test('comment with token column fixed', function () {89testLineCommentCommandTokenFirstColumn(90[91'some text',92'\tsome more text'93],94new Selection(2, 1, 2, 1),95[96'some text',97'!@# \tsome more text'98],99new Selection(2, 5, 2, 5)100);101});102103function createSimpleModel(lines: string[]): ISimpleModel {104return {105getLineContent: (lineNumber: number) => {106return lines[lineNumber - 1];107}108};109}110111function createBasicLinePreflightData(commentTokens: string[]): ILinePreflightData[] {112return commentTokens.map((commentString) => {113const r: ILinePreflightData = {114ignore: false,115commentStr: commentString,116commentStrOffset: 0,117commentStrLength: commentString.length118};119return r;120});121}122123test('_analyzeLines', () => {124const disposable = new DisposableStore();125let r: IPreflightData;126127r = LineCommentCommand._analyzeLines(Type.Toggle, true, createSimpleModel([128'\t\t',129' ',130' c',131'\t\td'132]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1, true, false, disposable.add(new TestLanguageConfigurationService()), 'plaintext');133if (!r.supported) {134throw new Error(`unexpected`);135}136137assert.strictEqual(r.shouldRemoveComments, false);138139// Does not change `commentStr`140assert.strictEqual(r.lines[0].commentStr, '//');141assert.strictEqual(r.lines[1].commentStr, 'rem');142assert.strictEqual(r.lines[2].commentStr, '!@#');143assert.strictEqual(r.lines[3].commentStr, '!@#');144145// Fills in `isWhitespace`146assert.strictEqual(r.lines[0].ignore, true);147assert.strictEqual(r.lines[1].ignore, true);148assert.strictEqual(r.lines[2].ignore, false);149assert.strictEqual(r.lines[3].ignore, false);150151// Fills in `commentStrOffset`152assert.strictEqual(r.lines[0].commentStrOffset, 2);153assert.strictEqual(r.lines[1].commentStrOffset, 4);154assert.strictEqual(r.lines[2].commentStrOffset, 4);155assert.strictEqual(r.lines[3].commentStrOffset, 2);156157158r = LineCommentCommand._analyzeLines(Type.Toggle, true, createSimpleModel([159'\t\t',160' rem ',161' !@# c',162'\t\t!@#d'163]), createBasicLinePreflightData(['//', 'rem', '!@#', '!@#']), 1, true, false, disposable.add(new TestLanguageConfigurationService()), 'plaintext');164if (!r.supported) {165throw new Error(`unexpected`);166}167168assert.strictEqual(r.shouldRemoveComments, true);169170// Does not change `commentStr`171assert.strictEqual(r.lines[0].commentStr, '//');172assert.strictEqual(r.lines[1].commentStr, 'rem');173assert.strictEqual(r.lines[2].commentStr, '!@#');174assert.strictEqual(r.lines[3].commentStr, '!@#');175176// Fills in `isWhitespace`177assert.strictEqual(r.lines[0].ignore, true);178assert.strictEqual(r.lines[1].ignore, false);179assert.strictEqual(r.lines[2].ignore, false);180assert.strictEqual(r.lines[3].ignore, false);181182// Fills in `commentStrOffset`183assert.strictEqual(r.lines[0].commentStrOffset, 2);184assert.strictEqual(r.lines[1].commentStrOffset, 4);185assert.strictEqual(r.lines[2].commentStrOffset, 4);186assert.strictEqual(r.lines[3].commentStrOffset, 2);187188// Fills in `commentStrLength`189assert.strictEqual(r.lines[0].commentStrLength, 2);190assert.strictEqual(r.lines[1].commentStrLength, 4);191assert.strictEqual(r.lines[2].commentStrLength, 4);192assert.strictEqual(r.lines[3].commentStrLength, 3);193194disposable.dispose();195});196197test('_normalizeInsertionPoint', () => {198199const runTest = (mixedArr: any[], tabSize: number, expected: number[], testName: string) => {200const model = createSimpleModel(mixedArr.filter((item, idx) => idx % 2 === 0));201const offsets = mixedArr.filter((item, idx) => idx % 2 === 1).map(offset => {202return {203commentStrOffset: offset,204ignore: false205};206});207LineCommentCommand._normalizeInsertionPoint(model, offsets, 1, tabSize);208const actual = offsets.map(item => item.commentStrOffset);209assert.deepStrictEqual(actual, expected, testName);210};211212// Bug 16696:[comment] comments not aligned in this case213runTest([214' XX', 2,215' YY', 4216], 4, [0, 0], 'Bug 16696');217218runTest([219'\t\t\tXX', 3,220' \tYY', 5,221' ZZ', 8,222'\t\tTT', 2223], 4, [2, 5, 8, 2], 'Test1');224225runTest([226'\t\t\t XX', 6,227' \t\t\t\tYY', 8,228' ZZ', 8,229'\t\t TT', 6230], 4, [2, 5, 8, 2], 'Test2');231232runTest([233'\t\t', 2,234'\t\t\t', 3,235'\t\t\t\t', 4,236'\t\t\t', 3237], 4, [2, 2, 2, 2], 'Test3');238239runTest([240'\t\t', 2,241'\t\t\t', 3,242'\t\t\t\t', 4,243'\t\t\t', 3,244' ', 4245], 2, [2, 2, 2, 2, 4], 'Test4');246247runTest([248'\t\t', 2,249'\t\t\t', 3,250'\t\t\t\t', 4,251'\t\t\t', 3,252' ', 4253], 4, [1, 1, 1, 1, 4], 'Test5');254255runTest([256' \t', 2,257' \t', 3,258' \t', 4,259' ', 4,260'\t', 1261], 4, [2, 3, 4, 4, 1], 'Test6');262263runTest([264' \t\t', 3,265' \t\t', 4,266' \t\t', 5,267' \t', 5,268'\t', 1269], 4, [2, 3, 4, 4, 1], 'Test7');270271runTest([272'\t', 1,273' ', 4274], 4, [1, 4], 'Test8:4');275runTest([276'\t', 1,277' ', 3278], 4, [0, 0], 'Test8:3');279runTest([280'\t', 1,281' ', 2282], 4, [0, 0], 'Test8:2');283runTest([284'\t', 1,285' ', 1286], 4, [0, 0], 'Test8:1');287runTest([288'\t', 1,289'', 0290], 4, [0, 0], 'Test8:0');291});292293test('detects indentation', function () {294testLineCommentCommand(295[296'\tsome text',297'\tsome more text'298],299new Selection(2, 2, 1, 1),300[301'\t!@# some text',302'\t!@# some more text'303],304new Selection(2, 2, 1, 1)305);306});307308test('detects mixed indentation', function () {309testLineCommentCommand(310[311'\tsome text',312' some more text'313],314new Selection(2, 2, 1, 1),315[316'\t!@# some text',317' !@# some more text'318],319new Selection(2, 2, 1, 1)320);321});322323test('ignores whitespace lines', function () {324testLineCommentCommand(325[326'\tsome text',327'\t ',328'',329'\tsome more text'330],331new Selection(4, 2, 1, 1),332[333'\t!@# some text',334'\t ',335'',336'\t!@# some more text'337],338new Selection(4, 2, 1, 1)339);340});341342test('removes its own', function () {343testLineCommentCommand(344[345'\t!@# some text',346'\t ',347'\t\t!@# some more text'348],349new Selection(3, 2, 1, 1),350[351'\tsome text',352'\t ',353'\t\tsome more text'354],355new Selection(3, 2, 1, 1)356);357});358359test('works in only whitespace', function () {360testLineCommentCommand(361[362'\t ',363'\t',364'\t\tsome more text'365],366new Selection(3, 1, 1, 1),367[368'\t!@# ',369'\t!@# ',370'\t\tsome more text'371],372new Selection(3, 1, 1, 1)373);374});375376test('bug 9697 - whitespace before comment token', function () {377testLineCommentCommand(378[379'\t !@#first',380'\tsecond line'381],382new Selection(1, 1, 1, 1),383[384'\t first',385'\tsecond line'386],387new Selection(1, 1, 1, 1)388);389});390391test('bug 10162 - line comment before caret', function () {392testLineCommentCommand(393[394'first!@#',395'\tsecond line'396],397new Selection(1, 1, 1, 1),398[399'!@# first!@#',400'\tsecond line'401],402new Selection(1, 5, 1, 5)403);404});405406test('comment single line - leading whitespace', function () {407testLineCommentCommand(408[409'first!@#',410'\tsecond line'411],412new Selection(2, 3, 2, 1),413[414'first!@#',415'\t!@# second line'416],417new Selection(2, 7, 2, 1)418);419});420421test('ignores invisible selection', function () {422testLineCommentCommand(423[424'first',425'\tsecond line',426'third line',427'fourth line',428'fifth'429],430new Selection(2, 1, 1, 1),431[432'!@# first',433'\tsecond line',434'third line',435'fourth line',436'fifth'437],438new Selection(2, 1, 1, 5)439);440});441442test('multiple lines', function () {443testLineCommentCommand(444[445'first',446'\tsecond line',447'third line',448'fourth line',449'fifth'450],451new Selection(2, 4, 1, 1),452[453'!@# first',454'!@# \tsecond line',455'third line',456'fourth line',457'fifth'458],459new Selection(2, 8, 1, 5)460);461});462463test('multiple modes on multiple lines', function () {464testLineCommentCommand(465[466'first',467'\tsecond line',468'third line',469'fourth line',470'fifth'471],472new Selection(4, 4, 3, 1),473[474'first',475'\tsecond line',476'!@# third line',477'!@# fourth line',478'fifth'479],480new Selection(4, 8, 3, 5)481);482});483484test('toggle single line', function () {485testLineCommentCommand(486[487'first',488'\tsecond line',489'third line',490'fourth line',491'fifth'492],493new Selection(1, 1, 1, 1),494[495'!@# first',496'\tsecond line',497'third line',498'fourth line',499'fifth'500],501new Selection(1, 5, 1, 5)502);503504testLineCommentCommand(505[506'!@# first',507'\tsecond line',508'third line',509'fourth line',510'fifth'511],512new Selection(1, 4, 1, 4),513[514'first',515'\tsecond line',516'third line',517'fourth line',518'fifth'519],520new Selection(1, 1, 1, 1)521);522});523524test('toggle multiple lines', function () {525testLineCommentCommand(526[527'first',528'\tsecond line',529'third line',530'fourth line',531'fifth'532],533new Selection(2, 4, 1, 1),534[535'!@# first',536'!@# \tsecond line',537'third line',538'fourth line',539'fifth'540],541new Selection(2, 8, 1, 5)542);543544testLineCommentCommand(545[546'!@# first',547'!@# \tsecond line',548'third line',549'fourth line',550'fifth'551],552new Selection(2, 7, 1, 4),553[554'first',555'\tsecond line',556'third line',557'fourth line',558'fifth'559],560new Selection(2, 3, 1, 1)561);562});563564test('issue #5964: Ctrl+/ to create comment when cursor is at the beginning of the line puts the cursor in a strange position', () => {565testLineCommentCommand(566[567'first',568'\tsecond line',569'third line',570'fourth line',571'fifth'572],573new Selection(1, 1, 1, 1),574[575'!@# first',576'\tsecond line',577'third line',578'fourth line',579'fifth'580],581new Selection(1, 5, 1, 5)582);583});584585test('issue #35673: Comment hotkeys throws the cursor before the comment', () => {586testLineCommentCommand(587[588'first',589'',590'\tsecond line',591'third line',592'fourth line',593'fifth'594],595new Selection(2, 1, 2, 1),596[597'first',598'!@# ',599'\tsecond line',600'third line',601'fourth line',602'fifth'603],604new Selection(2, 5, 2, 5)605);606607testLineCommentCommand(608[609'first',610'\t',611'\tsecond line',612'third line',613'fourth line',614'fifth'615],616new Selection(2, 2, 2, 2),617[618'first',619'\t!@# ',620'\tsecond line',621'third line',622'fourth line',623'fifth'624],625new Selection(2, 6, 2, 6)626);627});628629test('issue #2837 "Add Line Comment" fault when blank lines involved', function () {630testAddLineCommentCommand(631[632' if displayName == "":',633' displayName = groupName',634' description = getAttr(attributes, "description")',635' mailAddress = getAttr(attributes, "mail")',636'',637' print "||Group name|%s|" % displayName',638' print "||Description|%s|" % description',639' print "||Email address|[mailto:%s]|" % mailAddress`',640],641new Selection(1, 1, 8, 56),642[643' !@# if displayName == "":',644' !@# displayName = groupName',645' !@# description = getAttr(attributes, "description")',646' !@# mailAddress = getAttr(attributes, "mail")',647'',648' !@# print "||Group name|%s|" % displayName',649' !@# print "||Description|%s|" % description',650' !@# print "||Email address|[mailto:%s]|" % mailAddress`',651],652new Selection(1, 1, 8, 60)653);654});655656test('issue #47004: Toggle comments shouldn\'t move cursor', () => {657testAddLineCommentCommand(658[659' A line',660' Another line'661],662new Selection(2, 7, 1, 1),663[664' !@# A line',665' !@# Another line'666],667new Selection(2, 11, 1, 1)668);669});670671test('insertSpace false', () => {672const testLineCommentCommand = createTestCommandHelper(673{ lineComment: '!@#' },674(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, false, true)675);676677testLineCommentCommand(678[679'some text'680],681new Selection(1, 1, 1, 1),682[683'!@#some text'684],685new Selection(1, 4, 1, 4)686);687});688689test('insertSpace false does not remove space', () => {690const testLineCommentCommand = createTestCommandHelper(691{ lineComment: '!@#' },692(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, false, true)693);694695testLineCommentCommand(696[697'!@# some text'698],699new Selection(1, 1, 1, 1),700[701' some text'702],703new Selection(1, 1, 1, 1)704);705});706});707708suite('ignoreEmptyLines false', () => {709710ensureNoDisposablesAreLeakedInTestSuite();711712const testLineCommentCommand = createTestCommandHelper(713{ lineComment: '!@#', blockComment: ['<!@#', '#@!>'] },714(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, false)715);716717test('does not ignore whitespace lines', () => {718testLineCommentCommand(719[720'\tsome text',721'\t ',722'',723'\tsome more text'724],725new Selection(4, 2, 1, 1),726[727'!@# \tsome text',728'!@# \t ',729'!@# ',730'!@# \tsome more text'731],732new Selection(4, 6, 1, 5)733);734});735736test('removes its own', function () {737testLineCommentCommand(738[739'\t!@# some text',740'\t ',741'\t\t!@# some more text'742],743new Selection(3, 2, 1, 1),744[745'\tsome text',746'\t ',747'\t\tsome more text'748],749new Selection(3, 2, 1, 1)750);751});752753test('works in only whitespace', function () {754testLineCommentCommand(755[756'\t ',757'\t',758'\t\tsome more text'759],760new Selection(3, 1, 1, 1),761[762'\t!@# ',763'\t!@# ',764'\t\tsome more text'765],766new Selection(3, 1, 1, 1)767);768});769770test('comments single line', function () {771testLineCommentCommand(772[773'some text',774'\tsome more text'775],776new Selection(1, 1, 1, 1),777[778'!@# some text',779'\tsome more text'780],781new Selection(1, 5, 1, 5)782);783});784785test('detects indentation', function () {786testLineCommentCommand(787[788'\tsome text',789'\tsome more text'790],791new Selection(2, 2, 1, 1),792[793'\t!@# some text',794'\t!@# some more text'795],796new Selection(2, 2, 1, 1)797);798});799});800801suite('Editor Contrib - Line Comment As Block Comment', () => {802803ensureNoDisposablesAreLeakedInTestSuite();804805const testLineCommentCommand = createTestCommandHelper(806{ lineComment: '', blockComment: ['(', ')'] },807(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)808);809810test('fall back to block comment command', function () {811testLineCommentCommand(812[813'first',814'\tsecond line',815'third line',816'fourth line',817'fifth'818],819new Selection(1, 1, 1, 1),820[821'( first )',822'\tsecond line',823'third line',824'fourth line',825'fifth'826],827new Selection(1, 3, 1, 3)828);829});830831test('fall back to block comment command - toggle', function () {832testLineCommentCommand(833[834'(first)',835'\tsecond line',836'third line',837'fourth line',838'fifth'839],840new Selection(1, 7, 1, 2),841[842'first',843'\tsecond line',844'third line',845'fourth line',846'fifth'847],848new Selection(1, 6, 1, 1)849);850});851852test('bug 9513 - expand single line to uncomment auto block', function () {853testLineCommentCommand(854[855'first',856'\tsecond line',857'third line',858'fourth line',859'fifth'860],861new Selection(1, 1, 1, 1),862[863'( first )',864'\tsecond line',865'third line',866'fourth line',867'fifth'868],869new Selection(1, 3, 1, 3)870);871});872873test('bug 9691 - always expand selection to line boundaries', function () {874testLineCommentCommand(875[876'first',877'\tsecond line',878'third line',879'fourth line',880'fifth'881],882new Selection(3, 2, 1, 3),883[884'( first',885'\tsecond line',886'third line )',887'fourth line',888'fifth'889],890new Selection(3, 2, 1, 5)891);892893testLineCommentCommand(894[895'(first',896'\tsecond line',897'third line)',898'fourth line',899'fifth'900],901new Selection(3, 11, 1, 2),902[903'first',904'\tsecond line',905'third line',906'fourth line',907'fifth'908],909new Selection(3, 11, 1, 1)910);911});912});913914suite('Editor Contrib - Line Comment As Block Comment 2', () => {915916ensureNoDisposablesAreLeakedInTestSuite();917918const testLineCommentCommand = createTestCommandHelper(919{ lineComment: null, blockComment: ['<!@#', '#@!>'] },920(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true)921);922923test('no selection => uses indentation', function () {924testLineCommentCommand(925[926'\t\tfirst\t ',927'\t\tsecond line',928'\tthird line',929'fourth line',930'\t\t<!@#fifth#@!>\t\t'931],932new Selection(1, 1, 1, 1),933[934'\t\t<!@# first\t #@!>',935'\t\tsecond line',936'\tthird line',937'fourth line',938'\t\t<!@#fifth#@!>\t\t'939],940new Selection(1, 1, 1, 1)941);942943testLineCommentCommand(944[945'\t\t<!@#first\t #@!>',946'\t\tsecond line',947'\tthird line',948'fourth line',949'\t\t<!@#fifth#@!>\t\t'950],951new Selection(1, 1, 1, 1),952[953'\t\tfirst\t ',954'\t\tsecond line',955'\tthird line',956'fourth line',957'\t\t<!@#fifth#@!>\t\t'958],959new Selection(1, 1, 1, 1)960);961});962963test('can remove', function () {964testLineCommentCommand(965[966'\t\tfirst\t ',967'\t\tsecond line',968'\tthird line',969'fourth line',970'\t\t<!@#fifth#@!>\t\t'971],972new Selection(5, 1, 5, 1),973[974'\t\tfirst\t ',975'\t\tsecond line',976'\tthird line',977'fourth line',978'\t\tfifth\t\t'979],980new Selection(5, 1, 5, 1)981);982983testLineCommentCommand(984[985'\t\tfirst\t ',986'\t\tsecond line',987'\tthird line',988'fourth line',989'\t\t<!@#fifth#@!>\t\t'990],991new Selection(5, 3, 5, 3),992[993'\t\tfirst\t ',994'\t\tsecond line',995'\tthird line',996'fourth line',997'\t\tfifth\t\t'998],999new Selection(5, 3, 5, 3)1000);10011002testLineCommentCommand(1003[1004'\t\tfirst\t ',1005'\t\tsecond line',1006'\tthird line',1007'fourth line',1008'\t\t<!@#fifth#@!>\t\t'1009],1010new Selection(5, 4, 5, 4),1011[1012'\t\tfirst\t ',1013'\t\tsecond line',1014'\tthird line',1015'fourth line',1016'\t\tfifth\t\t'1017],1018new Selection(5, 3, 5, 3)1019);10201021testLineCommentCommand(1022[1023'\t\tfirst\t ',1024'\t\tsecond line',1025'\tthird line',1026'fourth line',1027'\t\t<!@#fifth#@!>\t\t'1028],1029new Selection(5, 16, 5, 3),1030[1031'\t\tfirst\t ',1032'\t\tsecond line',1033'\tthird line',1034'fourth line',1035'\t\tfifth\t\t'1036],1037new Selection(5, 8, 5, 3)1038);10391040testLineCommentCommand(1041[1042'\t\tfirst\t ',1043'\t\tsecond line',1044'\tthird line',1045'fourth line',1046'\t\t<!@#fifth#@!>\t\t'1047],1048new Selection(5, 12, 5, 7),1049[1050'\t\tfirst\t ',1051'\t\tsecond line',1052'\tthird line',1053'fourth line',1054'\t\tfifth\t\t'1055],1056new Selection(5, 8, 5, 3)1057);10581059testLineCommentCommand(1060[1061'\t\tfirst\t ',1062'\t\tsecond line',1063'\tthird line',1064'fourth line',1065'\t\t<!@#fifth#@!>\t\t'1066],1067new Selection(5, 18, 5, 18),1068[1069'\t\tfirst\t ',1070'\t\tsecond line',1071'\tthird line',1072'fourth line',1073'\t\tfifth\t\t'1074],1075new Selection(5, 10, 5, 10)1076);1077});10781079test('issue #993: Remove comment does not work consistently in HTML', () => {1080testLineCommentCommand(1081[1082' asd qwe',1083' asd qwe',1084''1085],1086new Selection(1, 1, 3, 1),1087[1088' <!@# asd qwe',1089' asd qwe #@!>',1090''1091],1092new Selection(1, 1, 3, 1)1093);10941095testLineCommentCommand(1096[1097' <!@#asd qwe',1098' asd qwe#@!>',1099''1100],1101new Selection(1, 1, 3, 1),1102[1103' asd qwe',1104' asd qwe',1105''1106],1107new Selection(1, 1, 3, 1)1108);1109});1110});11111112suite('Editor Contrib - Line Comment in mixed modes', () => {11131114ensureNoDisposablesAreLeakedInTestSuite();11151116const OUTER_LANGUAGE_ID = 'outerMode';1117const INNER_LANGUAGE_ID = 'innerMode';11181119class OuterMode extends Disposable {1120private readonly languageId = OUTER_LANGUAGE_ID;1121constructor(1122commentsConfig: CommentRule,1123@ILanguageService languageService: ILanguageService,1124@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService1125) {1126super();1127this._register(languageService.registerLanguage({ id: this.languageId }));1128this._register(languageConfigurationService.register(this.languageId, {1129comments: commentsConfig1130}));11311132this._register(TokenizationRegistry.register(this.languageId, {1133getInitialState: (): IState => NullState,1134tokenize: () => {1135throw new Error('not implemented');1136},1137tokenizeEncoded: (line: string, hasEOL: boolean, state: IState): EncodedTokenizationResult => {1138const languageId = (/^ /.test(line) ? INNER_LANGUAGE_ID : OUTER_LANGUAGE_ID);1139const encodedLanguageId = languageService.languageIdCodec.encodeLanguageId(languageId);11401141const tokens = new Uint32Array(1 << 1);1142tokens[(0 << 1)] = 0;1143tokens[(0 << 1) + 1] = (1144(ColorId.DefaultForeground << MetadataConsts.FOREGROUND_OFFSET)1145| (encodedLanguageId << MetadataConsts.LANGUAGEID_OFFSET)1146);1147return new EncodedTokenizationResult(tokens, state);1148}1149}));1150}1151}11521153class InnerMode extends Disposable {1154private readonly languageId = INNER_LANGUAGE_ID;1155constructor(1156commentsConfig: CommentRule,1157@ILanguageService languageService: ILanguageService,1158@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService1159) {1160super();1161this._register(languageService.registerLanguage({ id: this.languageId }));1162this._register(languageConfigurationService.register(this.languageId, {1163comments: commentsConfig1164}));1165}1166}11671168function testLineCommentCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection): void {11691170const setup = (accessor: ServicesAccessor, disposables: DisposableStore) => {1171const instantiationService = accessor.get(IInstantiationService);1172disposables.add(instantiationService.createInstance(OuterMode, { lineComment: '//', blockComment: ['/*', '*/'] }));1173disposables.add(instantiationService.createInstance(InnerMode, { lineComment: null, blockComment: ['{/*', '*/}'] }));1174};11751176testCommand(1177lines,1178OUTER_LANGUAGE_ID,1179selection,1180(accessor, sel) => new LineCommentCommand(accessor.get(ILanguageConfigurationService), sel, 4, Type.Toggle, true, true),1181expectedLines,1182expectedSelection,1183true,1184setup1185);1186}11871188test('issue #24047 (part 1): Commenting code in JSX files', () => {1189testLineCommentCommand(1190[1191'import React from \'react\';',1192'const Loader = () => (',1193' <div>',1194' Loading...',1195' </div>',1196');',1197'export default Loader;'1198],1199new Selection(1, 1, 7, 22),1200[1201'// import React from \'react\';',1202'// const Loader = () => (',1203'// <div>',1204'// Loading...',1205'// </div>',1206'// );',1207'// export default Loader;'1208],1209new Selection(1, 4, 7, 25),1210);1211});12121213test('issue #24047 (part 2): Commenting code in JSX files', () => {1214testLineCommentCommand(1215[1216'import React from \'react\';',1217'const Loader = () => (',1218' <div>',1219' Loading...',1220' </div>',1221');',1222'export default Loader;'1223],1224new Selection(3, 4, 3, 4),1225[1226'import React from \'react\';',1227'const Loader = () => (',1228' {/* <div> */}',1229' Loading...',1230' </div>',1231');',1232'export default Loader;'1233],1234new Selection(3, 8, 3, 8),1235);1236});12371238test('issue #36173: Commenting code in JSX tag body', () => {1239testLineCommentCommand(1240[1241'<div>',1242' {123}',1243'</div>',1244],1245new Selection(2, 4, 2, 4),1246[1247'<div>',1248' {/* {123} */}',1249'</div>',1250],1251new Selection(2, 8, 2, 8),1252);1253});1254});125512561257