Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/editor/contrib/linesOperations/test/browser/moveLinesCommand.test.ts
4780 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
import { Disposable, DisposableStore } from '../../../../../base/common/lifecycle.js';
6
import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';
7
import { EditorAutoIndentStrategy } from '../../../../common/config/editorOptions.js';
8
import { Selection } from '../../../../common/core/selection.js';
9
import { ILanguageService } from '../../../../common/languages/language.js';
10
import { IndentationRule } from '../../../../common/languages/languageConfiguration.js';
11
import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js';
12
import { LanguageService } from '../../../../common/services/languageService.js';
13
import { MoveLinesCommand } from '../../browser/moveLinesCommand.js';
14
import { testCommand } from '../../../../test/browser/testCommand.js';
15
import { TestLanguageConfigurationService } from '../../../../test/common/modes/testLanguageConfigurationService.js';
16
17
const enum MoveLinesDirection {
18
Up,
19
Down
20
}
21
22
function testMoveLinesDownCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {
23
testMoveLinesUpOrDownCommand(MoveLinesDirection.Down, lines, selection, expectedLines, expectedSelection, languageConfigurationService);
24
}
25
26
function testMoveLinesUpCommand(lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {
27
testMoveLinesUpOrDownCommand(MoveLinesDirection.Up, lines, selection, expectedLines, expectedSelection, languageConfigurationService);
28
}
29
30
function testMoveLinesDownWithIndentCommand(languageId: string, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {
31
testMoveLinesUpOrDownWithIndentCommand(MoveLinesDirection.Down, languageId, lines, selection, expectedLines, expectedSelection, languageConfigurationService);
32
}
33
34
function testMoveLinesUpWithIndentCommand(languageId: string, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService): void {
35
testMoveLinesUpOrDownWithIndentCommand(MoveLinesDirection.Up, languageId, lines, selection, expectedLines, expectedSelection, languageConfigurationService);
36
}
37
38
function testMoveLinesUpOrDownCommand(direction: MoveLinesDirection, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService) {
39
const disposables = new DisposableStore();
40
if (!languageConfigurationService) {
41
languageConfigurationService = disposables.add(new TestLanguageConfigurationService());
42
}
43
testCommand(lines, null, selection, (accessor, sel) => new MoveLinesCommand(sel, direction === MoveLinesDirection.Up ? false : true, EditorAutoIndentStrategy.Advanced, languageConfigurationService), expectedLines, expectedSelection);
44
disposables.dispose();
45
}
46
47
function testMoveLinesUpOrDownWithIndentCommand(direction: MoveLinesDirection, languageId: string, lines: string[], selection: Selection, expectedLines: string[], expectedSelection: Selection, languageConfigurationService?: ILanguageConfigurationService) {
48
const disposables = new DisposableStore();
49
if (!languageConfigurationService) {
50
languageConfigurationService = disposables.add(new TestLanguageConfigurationService());
51
}
52
testCommand(lines, languageId, selection, (accessor, sel) => new MoveLinesCommand(sel, direction === MoveLinesDirection.Up ? false : true, EditorAutoIndentStrategy.Full, languageConfigurationService), expectedLines, expectedSelection);
53
disposables.dispose();
54
}
55
56
suite('Editor Contrib - Move Lines Command', () => {
57
58
ensureNoDisposablesAreLeakedInTestSuite();
59
60
test('move first up / last down disabled', function () {
61
testMoveLinesUpCommand(
62
[
63
'first',
64
'second line',
65
'third line',
66
'fourth line',
67
'fifth'
68
],
69
new Selection(1, 1, 1, 1),
70
[
71
'first',
72
'second line',
73
'third line',
74
'fourth line',
75
'fifth'
76
],
77
new Selection(1, 1, 1, 1)
78
);
79
80
testMoveLinesDownCommand(
81
[
82
'first',
83
'second line',
84
'third line',
85
'fourth line',
86
'fifth'
87
],
88
new Selection(5, 1, 5, 1),
89
[
90
'first',
91
'second line',
92
'third line',
93
'fourth line',
94
'fifth'
95
],
96
new Selection(5, 1, 5, 1)
97
);
98
});
99
100
test('move first line down', function () {
101
testMoveLinesDownCommand(
102
[
103
'first',
104
'second line',
105
'third line',
106
'fourth line',
107
'fifth'
108
],
109
new Selection(1, 4, 1, 1),
110
[
111
'second line',
112
'first',
113
'third line',
114
'fourth line',
115
'fifth'
116
],
117
new Selection(2, 4, 2, 1)
118
);
119
});
120
121
test('move 2nd line up', function () {
122
testMoveLinesUpCommand(
123
[
124
'first',
125
'second line',
126
'third line',
127
'fourth line',
128
'fifth'
129
],
130
new Selection(2, 1, 2, 1),
131
[
132
'second line',
133
'first',
134
'third line',
135
'fourth line',
136
'fifth'
137
],
138
new Selection(1, 1, 1, 1)
139
);
140
});
141
142
test('issue #1322a: move 2nd line up', function () {
143
testMoveLinesUpCommand(
144
[
145
'first',
146
'second line',
147
'third line',
148
'fourth line',
149
'fifth'
150
],
151
new Selection(2, 12, 2, 12),
152
[
153
'second line',
154
'first',
155
'third line',
156
'fourth line',
157
'fifth'
158
],
159
new Selection(1, 12, 1, 12)
160
);
161
});
162
163
test('issue #1322b: move last line up', function () {
164
testMoveLinesUpCommand(
165
[
166
'first',
167
'second line',
168
'third line',
169
'fourth line',
170
'fifth'
171
],
172
new Selection(5, 6, 5, 6),
173
[
174
'first',
175
'second line',
176
'third line',
177
'fifth',
178
'fourth line'
179
],
180
new Selection(4, 6, 4, 6)
181
);
182
});
183
184
test('issue #1322c: move last line selected up', function () {
185
testMoveLinesUpCommand(
186
[
187
'first',
188
'second line',
189
'third line',
190
'fourth line',
191
'fifth'
192
],
193
new Selection(5, 6, 5, 1),
194
[
195
'first',
196
'second line',
197
'third line',
198
'fifth',
199
'fourth line'
200
],
201
new Selection(4, 6, 4, 1)
202
);
203
});
204
205
test('move last line up', function () {
206
testMoveLinesUpCommand(
207
[
208
'first',
209
'second line',
210
'third line',
211
'fourth line',
212
'fifth'
213
],
214
new Selection(5, 1, 5, 1),
215
[
216
'first',
217
'second line',
218
'third line',
219
'fifth',
220
'fourth line'
221
],
222
new Selection(4, 1, 4, 1)
223
);
224
});
225
226
test('move 4th line down', function () {
227
testMoveLinesDownCommand(
228
[
229
'first',
230
'second line',
231
'third line',
232
'fourth line',
233
'fifth'
234
],
235
new Selection(4, 1, 4, 1),
236
[
237
'first',
238
'second line',
239
'third line',
240
'fifth',
241
'fourth line'
242
],
243
new Selection(5, 1, 5, 1)
244
);
245
});
246
247
test('move multiple lines down', function () {
248
testMoveLinesDownCommand(
249
[
250
'first',
251
'second line',
252
'third line',
253
'fourth line',
254
'fifth'
255
],
256
new Selection(4, 4, 2, 2),
257
[
258
'first',
259
'fifth',
260
'second line',
261
'third line',
262
'fourth line'
263
],
264
new Selection(5, 4, 3, 2)
265
);
266
});
267
268
test('invisible selection is ignored', function () {
269
testMoveLinesDownCommand(
270
[
271
'first',
272
'second line',
273
'third line',
274
'fourth line',
275
'fifth'
276
],
277
new Selection(2, 1, 1, 1),
278
[
279
'second line',
280
'first',
281
'third line',
282
'fourth line',
283
'fifth'
284
],
285
new Selection(3, 1, 2, 1)
286
);
287
});
288
});
289
290
class IndentRulesMode extends Disposable {
291
public readonly languageId = 'moveLinesIndentMode';
292
constructor(
293
indentationRules: IndentationRule,
294
@ILanguageService languageService: ILanguageService,
295
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
296
) {
297
super();
298
this._register(languageService.registerLanguage({ id: this.languageId }));
299
this._register(languageConfigurationService.register(this.languageId, {
300
indentationRules: indentationRules
301
}));
302
}
303
}
304
305
suite('Editor contrib - Move Lines Command honors Indentation Rules', () => {
306
307
ensureNoDisposablesAreLeakedInTestSuite();
308
309
const indentRules = {
310
decreaseIndentPattern: /^\s*((?!\S.*\/[*]).*[*]\/\s*)?[})\]]|^\s*(case\b.*|default):\s*(\/\/.*|\/[*].*[*]\/\s*)?$/,
311
increaseIndentPattern: /(\{[^}"'`]*|\([^)"']*|\[[^\]"']*|^\s*(\{\}|\(\)|\[\]|(case\b.*|default):))\s*(\/\/.*|\/[*].*[*]\/\s*)?$/,
312
indentNextLinePattern: /^\s*(for|while|if|else)\b(?!.*[;{}]\s*(\/\/.*|\/[*].*[*]\/\s*)?$)/,
313
unIndentedLinePattern: /^(?!.*([;{}]|\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*)?$))/
314
};
315
316
// https://github.com/microsoft/vscode/issues/28552#issuecomment-307862797
317
test('first line indentation adjust to 0', () => {
318
const languageService = new LanguageService();
319
const languageConfigurationService = new TestLanguageConfigurationService();
320
const mode = new IndentRulesMode(indentRules, languageService, languageConfigurationService);
321
322
testMoveLinesUpWithIndentCommand(
323
mode.languageId,
324
[
325
'class X {',
326
'\tz = 2',
327
'}'
328
],
329
new Selection(2, 1, 2, 1),
330
[
331
'z = 2',
332
'class X {',
333
'}'
334
],
335
new Selection(1, 1, 1, 1),
336
languageConfigurationService
337
);
338
339
mode.dispose();
340
languageService.dispose();
341
languageConfigurationService.dispose();
342
});
343
344
// https://github.com/microsoft/vscode/issues/28552#issuecomment-307867717
345
test('move lines across block', () => {
346
const languageService = new LanguageService();
347
const languageConfigurationService = new TestLanguageConfigurationService();
348
const mode = new IndentRulesMode(indentRules, languageService, languageConfigurationService);
349
350
testMoveLinesDownWithIndentCommand(
351
mode.languageId,
352
[
353
'const value = 2;',
354
'const standardLanguageDescriptions = [',
355
' {',
356
' diagnosticSource: \'js\',',
357
' }',
358
'];'
359
],
360
new Selection(1, 1, 1, 1),
361
[
362
'const standardLanguageDescriptions = [',
363
' const value = 2;',
364
' {',
365
' diagnosticSource: \'js\',',
366
' }',
367
'];'
368
],
369
new Selection(2, 5, 2, 5),
370
languageConfigurationService
371
);
372
373
mode.dispose();
374
languageService.dispose();
375
languageConfigurationService.dispose();
376
});
377
378
379
test('move line should still work as before if there is no indentation rules', () => {
380
testMoveLinesUpWithIndentCommand(
381
null!,
382
[
383
'if (true) {',
384
' var task = new Task(() => {',
385
' var work = 1234;',
386
' });',
387
'}'
388
],
389
new Selection(3, 1, 3, 1),
390
[
391
'if (true) {',
392
' var work = 1234;',
393
' var task = new Task(() => {',
394
' });',
395
'}'
396
],
397
new Selection(2, 1, 2, 1)
398
);
399
});
400
});
401
402
class EnterRulesMode extends Disposable {
403
public readonly languageId = 'moveLinesEnterMode';
404
constructor(
405
@ILanguageService languageService: ILanguageService,
406
@ILanguageConfigurationService languageConfigurationService: ILanguageConfigurationService
407
) {
408
super();
409
this._register(languageService.registerLanguage({ id: this.languageId }));
410
this._register(languageConfigurationService.register(this.languageId, {
411
indentationRules: {
412
decreaseIndentPattern: /^\s*\[$/,
413
increaseIndentPattern: /^\s*\]$/,
414
},
415
brackets: [
416
['{', '}']
417
]
418
}));
419
}
420
}
421
422
suite('Editor - contrib - Move Lines Command honors onEnter Rules', () => {
423
424
ensureNoDisposablesAreLeakedInTestSuite();
425
426
test('issue #54829. move block across block', () => {
427
const languageService = new LanguageService();
428
const languageConfigurationService = new TestLanguageConfigurationService();
429
const mode = new EnterRulesMode(languageService, languageConfigurationService);
430
431
testMoveLinesDownWithIndentCommand(
432
mode.languageId,
433
434
[
435
'if (true) {',
436
' if (false) {',
437
' if (1) {',
438
' console.log(\'b\');',
439
' }',
440
' console.log(\'a\');',
441
' }',
442
'}'
443
],
444
new Selection(3, 9, 5, 10),
445
[
446
'if (true) {',
447
' if (false) {',
448
' console.log(\'a\');',
449
' if (1) {',
450
' console.log(\'b\');',
451
' }',
452
' }',
453
'}'
454
],
455
new Selection(4, 9, 6, 10),
456
languageConfigurationService
457
);
458
459
mode.dispose();
460
languageService.dispose();
461
languageConfigurationService.dispose();
462
});
463
});
464
465