Path: blob/main/src/vs/editor/contrib/linesOperations/test/browser/moveLinesCommand.test.ts
4780 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*--------------------------------------------------------------------------------------------*/4import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';5import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';6import { EditorAutoIndentStrategy } from '../../../../common/config/editorOptions.js';7import { Selection } from '../../../../common/core/selection.js';8import { ILanguageService } from '../../../../common/languages/language.js';9import { IndentationRule } from '../../../../common/languages/languageConfiguration.js';10import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js';11import { LanguageService } from '../../../../common/services/languageService.js';12import { MoveLinesCommand } from '../../browser/moveLinesCommand.js';13import { testCommand } from '../../../../test/browser/testCommand.js';14import { TestLanguageConfigurationService } from '../../../../test/common/modes/testLanguageConfigurationService.js';1516const enum MoveLinesDirection {17Up,18Down19}2021function testMoveLinesDownCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {22testMoveLinesUpOrDownCommand(MoveLinesDirection.Down, lines, selection, expectedLines, expectedSelection, languageConfigurationService);23}2425function testMoveLinesUpCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {26testMoveLinesUpOrDownCommand(MoveLinesDirection.Up, lines, selection, expectedLines, expectedSelection, languageConfigurationService);27}2829function testMoveLinesDownWithIndentCommand(languageId: string, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {30testMoveLinesUpOrDownWithIndentCommand(MoveLinesDirection.Down, languageId, lines, selection, expectedLines, expectedSelection, languageConfigurationService);31}3233function testMoveLinesUpWithIndentCommand(languageId: string, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {34testMoveLinesUpOrDownWithIndentCommand(MoveLinesDirection.Up, languageId, lines, selection, expectedLines, expectedSelection, languageConfigurationService);35}3637function testMoveLinesUpOrDownCommand(direction: MoveLinesDirection, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService) {38const disposables = new DisposableStore();39if (!languageConfigurationService) {40languageConfigurationService = disposables.add(new TestLanguageConfigurationService());41}42testCommand(lines, null, selection, (accessor, sel) => new MoveLinesCommand(sel, direction === MoveLinesDirection.Up ? false : true, EditorAutoIndentStrategy.Advanced, languageConfigurationService), expectedLines, expectedSelection);43disposables.dispose();44}4546function testMoveLinesUpOrDownWithIndentCommand(direction: MoveLinesDirection, languageId: string, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService) {47const disposables = new DisposableStore();48if (!languageConfigurationService) {49languageConfigurationService = disposables.add(new TestLanguageConfigurationService());50}51testCommand(lines, languageId, selection, (accessor, sel) => new MoveLinesCommand(sel, direction === MoveLinesDirection.Up ? false : true, EditorAutoIndentStrategy.Full, languageConfigurationService), expectedLines, expectedSelection);52disposables.dispose();53}5455suite('Editor Contrib - Move Lines Command', () => {5657ensureNoDisposablesAreLeakedInTestSuite();5859test('move first up / last down disabled', function () {60testMoveLinesUpCommand(61[62'first',63'second line',64'third line',65'fourth line',66'fifth'67],68new Selection(1, 1, 1, 1),69[70'first',71'second line',72'third line',73'fourth line',74'fifth'75],76new Selection(1, 1, 1, 1)77);7879testMoveLinesDownCommand(80[81'first',82'second line',83'third line',84'fourth line',85'fifth'86],87new Selection(5, 1, 5, 1),88[89'first',90'second line',91'third line',92'fourth line',93'fifth'94],95new Selection(5, 1, 5, 1)96);97});9899test('move first line down', function () {100testMoveLinesDownCommand(101[102'first',103'second line',104'third line',105'fourth line',106'fifth'107],108new Selection(1, 4, 1, 1),109[110'second line',111'first',112'third line',113'fourth line',114'fifth'115],116new Selection(2, 4, 2, 1)117);118});119120test('move 2nd line up', function () {121testMoveLinesUpCommand(122[123'first',124'second line',125'third line',126'fourth line',127'fifth'128],129new Selection(2, 1, 2, 1),130[131'second line',132'first',133'third line',134'fourth line',135'fifth'136],137new Selection(1, 1, 1, 1)138);139});140141test('issue #1322a: move 2nd line up', function () {142testMoveLinesUpCommand(143[144'first',145'second line',146'third line',147'fourth line',148'fifth'149],150new Selection(2, 12, 2, 12),151[152'second line',153'first',154'third line',155'fourth line',156'fifth'157],158new Selection(1, 12, 1, 12)159);160});161162test('issue #1322b: move last line up', function () {163testMoveLinesUpCommand(164[165'first',166'second line',167'third line',168'fourth line',169'fifth'170],171new Selection(5, 6, 5, 6),172[173'first',174'second line',175'third line',176'fifth',177'fourth line'178],179new Selection(4, 6, 4, 6)180);181});182183test('issue #1322c: move last line selected up', function () {184testMoveLinesUpCommand(185[186'first',187'second line',188'third line',189'fourth line',190'fifth'191],192new Selection(5, 6, 5, 1),193[194'first',195'second line',196'third line',197'fifth',198'fourth line'199],200new Selection(4, 6, 4, 1)201);202});203204test('move last line up', function () {205testMoveLinesUpCommand(206[207'first',208'second line',209'third line',210'fourth line',211'fifth'212],213new Selection(5, 1, 5, 1),214[215'first',216'second line',217'third line',218'fifth',219'fourth line'220],221new Selection(4, 1, 4, 1)222);223});224225test('move 4th line down', function () {226testMoveLinesDownCommand(227[228'first',229'second line',230'third line',231'fourth line',232'fifth'233],234new Selection(4, 1, 4, 1),235[236'first',237'second line',238'third line',239'fifth',240'fourth line'241],242new Selection(5, 1, 5, 1)243);244});245246test('move multiple lines down', function () {247testMoveLinesDownCommand(248[249'first',250'second line',251'third line',252'fourth line',253'fifth'254],255new Selection(4, 4, 2, 2),256[257'first',258'fifth',259'second line',260'third line',261'fourth line'262],263new Selection(5, 4, 3, 2)264);265});266267test('invisible selection is ignored', function () {268testMoveLinesDownCommand(269[270'first',271'second line',272'third line',273'fourth line',274'fifth'275],276new Selection(2, 1, 1, 1),277[278'second line',279'first',280'third line',281'fourth line',282'fifth'283],284new Selection(3, 1, 2, 1)285);286});287});288289class IndentRulesMode extends Disposable {290public readonly languageId = 'moveLinesIndentMode';291constructor(292indentationRules: IndentationRule,293@ILanguageService languageService: ILanguageService,294@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService295) {296super();297this._register(languageService.registerLanguage({ id: this.languageId }));298this._register(languageConfigurationService.register(this.languageId, {299indentationRules: indentationRules300}));301}302}303304suite('Editor contrib - Move Lines Command honors Indentation Rules', () => {305306ensureNoDisposablesAreLeakedInTestSuite();307308const indentRules = {309decreaseIndentPattern: /^\s*((?!\S.*\/[*]).*[*]\/\s*)?[})\]]|^\s*(case\b.*|default):\s*(\/\/.*|\/[*].*[*]\/\s*)?$/,310increaseIndentPattern: /(\{[^}"'`]*|\([^)"']*|\[[^\]"']*|^\s*(\{\}|\(\)|\[\]|(case\b.*|default):))\s*(\/\/.*|\/[*].*[*]\/\s*)?$/,311indentNextLinePattern: /^\s*(for|while|if|else)\b(?!.*[;{}]\s*(\/\/.*|\/[*].*[*]\/\s*)?$)/,312unIndentedLinePattern: /^(?!.*([;{}]|\S:)\s*(\/\/.*|\/[*].*[*]\/\s*)?$)(?!.*(\{[^}"']*|\([^)"']*|\[[^\]"']*|^\s*(\{\}|\(\)|\[\]|(case\b.*|default):))\s*(\/\/.*|\/[*].*[*]\/\s*)?$)(?!^\s*((?!\S.*\/[*]).*[*]\/\s*)?[})\]]|^\s*(case\b.*|default):\s*(\/\/.*|\/[*].*[*]\/\s*)?$)(?!^\s*(for|while|if|else)\b(?!.*[;{}]\s*(\/\/.*|\/[*].*[*]\/\s*)?$))/313};314315// https://github.com/microsoft/vscode/issues/28552#issuecomment-307862797316test('first line indentation adjust to 0', () => {317const languageService = new LanguageService();318const languageConfigurationService = new TestLanguageConfigurationService();319const mode = new IndentRulesMode(indentRules, languageService, languageConfigurationService);320321testMoveLinesUpWithIndentCommand(322mode.languageId,323[324'class X {',325'\tz = 2',326'}'327],328new Selection(2, 1, 2, 1),329[330'z = 2',331'class X {',332'}'333],334new Selection(1, 1, 1, 1),335languageConfigurationService336);337338mode.dispose();339languageService.dispose();340languageConfigurationService.dispose();341});342343// https://github.com/microsoft/vscode/issues/28552#issuecomment-307867717344test('move lines across block', () => {345const languageService = new LanguageService();346const languageConfigurationService = new TestLanguageConfigurationService();347const mode = new IndentRulesMode(indentRules, languageService, languageConfigurationService);348349testMoveLinesDownWithIndentCommand(350mode.languageId,351[352'const value = 2;',353'const standardLanguageDescriptions = [',354' {',355' diagnosticSource: \'js\',',356' }',357'];'358],359new Selection(1, 1, 1, 1),360[361'const standardLanguageDescriptions = [',362' const value = 2;',363' {',364' diagnosticSource: \'js\',',365' }',366'];'367],368new Selection(2, 5, 2, 5),369languageConfigurationService370);371372mode.dispose();373languageService.dispose();374languageConfigurationService.dispose();375});376377378test('move line should still work as before if there is no indentation rules', () => {379testMoveLinesUpWithIndentCommand(380null!,381[382'if (true) {',383' var task = new Task(() => {',384' var work = 1234;',385' });',386'}'387],388new Selection(3, 1, 3, 1),389[390'if (true) {',391' var work = 1234;',392' var task = new Task(() => {',393' });',394'}'395],396new Selection(2, 1, 2, 1)397);398});399});400401class EnterRulesMode extends Disposable {402public readonly languageId = 'moveLinesEnterMode';403constructor(404@ILanguageService languageService: ILanguageService,405@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService406) {407super();408this._register(languageService.registerLanguage({ id: this.languageId }));409this._register(languageConfigurationService.register(this.languageId, {410indentationRules: {411decreaseIndentPattern: /^\s*\[$/,412increaseIndentPattern: /^\s*\]$/,413},414brackets: [415['{', '}']416]417}));418}419}420421suite('Editor - contrib - Move Lines Command honors onEnter Rules', () => {422423ensureNoDisposablesAreLeakedInTestSuite();424425test('issue #54829. move block across block', () => {426const languageService = new LanguageService();427const languageConfigurationService = new TestLanguageConfigurationService();428const mode = new EnterRulesMode(languageService, languageConfigurationService);429430testMoveLinesDownWithIndentCommand(431mode.languageId,432433[434'if (true) {',435' if (false) {',436' if (1) {',437' console.log(\'b\');',438' }',439' console.log(\'a\');',440' }',441'}'442],443new Selection(3, 9, 5, 10),444[445'if (true) {',446' if (false) {',447' console.log(\'a\');',448' if (1) {',449' console.log(\'b\');',450' }',451' }',452'}'453],454new Selection(4, 9, 6, 10),455languageConfigurationService456);457458mode.dispose();459languageService.dispose();460languageConfigurationService.dispose();461});462});463464465