Path: blob/main/src/vs/editor/contrib/bracketMatching/test/browser/bracketMatching.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 assert from 'assert';5import { Position } from '../../../../common/core/position.js';6import { Selection } from '../../../../common/core/selection.js';7import { ILanguageConfigurationService } from '../../../../common/languages/languageConfigurationRegistry.js';8import { BracketMatchingController } from '../../browser/bracketMatching.js';9import { createCodeEditorServices, instantiateTestCodeEditor } from '../../../../test/browser/testCodeEditor.js';10import { instantiateTextModel } from '../../../../test/common/testTextModel.js';11import { DisposableStore } from '../../../../../base/common/lifecycle.js';12import { TestInstantiationService } from '../../../../../platform/instantiation/test/common/instantiationServiceMock.js';13import { ILanguageService } from '../../../../common/languages/language.js';14import { ensureNoDisposablesAreLeakedInTestSuite } from '../../../../../base/test/common/utils.js';1516suite('bracket matching', () => {17let disposables: DisposableStore;18let instantiationService: TestInstantiationService;19let languageConfigurationService: ILanguageConfigurationService;20let languageService: ILanguageService;2122setup(() => {23disposables = new DisposableStore();24instantiationService = createCodeEditorServices(disposables);25languageConfigurationService = instantiationService.get(ILanguageConfigurationService);26languageService = instantiationService.get(ILanguageService);27});2829teardown(() => {30disposables.dispose();31});3233ensureNoDisposablesAreLeakedInTestSuite();3435function createTextModelWithBrackets(text: string) {36const languageId = 'bracketMode';37disposables.add(languageService.registerLanguage({ id: languageId }));38disposables.add(languageConfigurationService.register(languageId, {39brackets: [40['{', '}'],41['[', ']'],42['(', ')'],43]44}));45return disposables.add(instantiateTextModel(instantiationService, text, languageId));46}4748function createCodeEditorWithBrackets(text: string) {49return disposables.add(instantiateTestCodeEditor(instantiationService, createTextModelWithBrackets(text)));50}5152test('issue #183: jump to matching bracket position', () => {53const editor = createCodeEditorWithBrackets('var x = (3 + (5-7)) + ((5+3)+5);');54const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));5556// start on closing bracket57editor.setPosition(new Position(1, 20));58bracketMatchingController.jumpToBracket();59assert.deepStrictEqual(editor.getPosition(), new Position(1, 9));60bracketMatchingController.jumpToBracket();61assert.deepStrictEqual(editor.getPosition(), new Position(1, 19));62bracketMatchingController.jumpToBracket();63assert.deepStrictEqual(editor.getPosition(), new Position(1, 9));6465// start on opening bracket66editor.setPosition(new Position(1, 23));67bracketMatchingController.jumpToBracket();68assert.deepStrictEqual(editor.getPosition(), new Position(1, 31));69bracketMatchingController.jumpToBracket();70assert.deepStrictEqual(editor.getPosition(), new Position(1, 23));71bracketMatchingController.jumpToBracket();72assert.deepStrictEqual(editor.getPosition(), new Position(1, 31));73});7475test('Jump to next bracket', () => {76const editor = createCodeEditorWithBrackets('var x = (3 + (5-7)); y();');77const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));7879// start position between brackets80editor.setPosition(new Position(1, 16));81bracketMatchingController.jumpToBracket();82assert.deepStrictEqual(editor.getPosition(), new Position(1, 18));83bracketMatchingController.jumpToBracket();84assert.deepStrictEqual(editor.getPosition(), new Position(1, 14));85bracketMatchingController.jumpToBracket();86assert.deepStrictEqual(editor.getPosition(), new Position(1, 18));8788// skip brackets in comments89editor.setPosition(new Position(1, 21));90bracketMatchingController.jumpToBracket();91assert.deepStrictEqual(editor.getPosition(), new Position(1, 23));92bracketMatchingController.jumpToBracket();93assert.deepStrictEqual(editor.getPosition(), new Position(1, 24));94bracketMatchingController.jumpToBracket();95assert.deepStrictEqual(editor.getPosition(), new Position(1, 23));9697// do not break if no brackets are available98editor.setPosition(new Position(1, 26));99bracketMatchingController.jumpToBracket();100assert.deepStrictEqual(editor.getPosition(), new Position(1, 26));101});102103test('Select to next bracket', () => {104const editor = createCodeEditorWithBrackets('var x = (3 + (5-7)); y();');105const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));106107// start position in open brackets108editor.setPosition(new Position(1, 9));109bracketMatchingController.selectToBracket(true);110assert.deepStrictEqual(editor.getPosition(), new Position(1, 20));111assert.deepStrictEqual(editor.getSelection(), new Selection(1, 9, 1, 20));112113// start position in close brackets (should select backwards)114editor.setPosition(new Position(1, 20));115bracketMatchingController.selectToBracket(true);116assert.deepStrictEqual(editor.getPosition(), new Position(1, 9));117assert.deepStrictEqual(editor.getSelection(), new Selection(1, 20, 1, 9));118119// start position between brackets120editor.setPosition(new Position(1, 16));121bracketMatchingController.selectToBracket(true);122assert.deepStrictEqual(editor.getPosition(), new Position(1, 19));123assert.deepStrictEqual(editor.getSelection(), new Selection(1, 14, 1, 19));124125// start position outside brackets126editor.setPosition(new Position(1, 21));127bracketMatchingController.selectToBracket(true);128assert.deepStrictEqual(editor.getPosition(), new Position(1, 25));129assert.deepStrictEqual(editor.getSelection(), new Selection(1, 23, 1, 25));130131// do not break if no brackets are available132editor.setPosition(new Position(1, 26));133bracketMatchingController.selectToBracket(true);134assert.deepStrictEqual(editor.getPosition(), new Position(1, 26));135assert.deepStrictEqual(editor.getSelection(), new Selection(1, 26, 1, 26));136});137138test('issue #1772: jump to enclosing brackets', () => {139const text = [140'const x = {',141' something: [0, 1, 2],',142' another: true,',143' somethingmore: [0, 2, 4]',144'};',145].join('\n');146const editor = createCodeEditorWithBrackets(text);147const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));148149editor.setPosition(new Position(3, 5));150bracketMatchingController.jumpToBracket();151assert.deepStrictEqual(editor.getSelection(), new Selection(5, 1, 5, 1));152});153154test('issue #43371: argument to not select brackets', () => {155const text = [156'const x = {',157' something: [0, 1, 2],',158' another: true,',159' somethingmore: [0, 2, 4]',160'};',161].join('\n');162const editor = createCodeEditorWithBrackets(text);163const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));164165editor.setPosition(new Position(3, 5));166bracketMatchingController.selectToBracket(false);167assert.deepStrictEqual(editor.getSelection(), new Selection(1, 12, 5, 1));168});169170test('issue #45369: Select to Bracket with multicursor', () => {171const editor = createCodeEditorWithBrackets('{ } { } { }');172const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));173174// cursors inside brackets become selections of the entire bracket contents175editor.setSelections([176new Selection(1, 3, 1, 3),177new Selection(1, 10, 1, 10),178new Selection(1, 17, 1, 17)179]);180bracketMatchingController.selectToBracket(true);181assert.deepStrictEqual(editor.getSelections(), [182new Selection(1, 1, 1, 5),183new Selection(1, 8, 1, 13),184new Selection(1, 16, 1, 19)185]);186187// cursors to the left of bracket pairs become selections of the entire pair188editor.setSelections([189new Selection(1, 1, 1, 1),190new Selection(1, 6, 1, 6),191new Selection(1, 14, 1, 14)192]);193bracketMatchingController.selectToBracket(true);194assert.deepStrictEqual(editor.getSelections(), [195new Selection(1, 1, 1, 5),196new Selection(1, 8, 1, 13),197new Selection(1, 16, 1, 19)198]);199200// cursors just right of a bracket pair become selections of the entire pair201editor.setSelections([202new Selection(1, 5, 1, 5),203new Selection(1, 13, 1, 13),204new Selection(1, 19, 1, 19)205]);206bracketMatchingController.selectToBracket(true);207assert.deepStrictEqual(editor.getSelections(), [208new Selection(1, 5, 1, 1),209new Selection(1, 13, 1, 8),210new Selection(1, 19, 1, 16)211]);212});213214test('Removes brackets', () => {215const editor = createCodeEditorWithBrackets('var x = (3 + (5-7)); y();');216const bracketMatchingController = disposables.add(editor.registerAndInstantiateContribution(BracketMatchingController.ID, BracketMatchingController));217function removeBrackets() {218bracketMatchingController.removeBrackets();219}220221// position before the bracket222editor.setPosition(new Position(1, 9));223removeBrackets();224assert.deepStrictEqual(editor.getModel().getValue(), 'var x = 3 + (5-7); y();');225editor.getModel().setValue('var x = (3 + (5-7)); y();');226227// position between brackets228editor.setPosition(new Position(1, 16));229removeBrackets();230assert.deepStrictEqual(editor.getModel().getValue(), 'var x = (3 + 5-7); y();');231removeBrackets();232assert.deepStrictEqual(editor.getModel().getValue(), 'var x = 3 + 5-7; y();');233removeBrackets();234assert.deepStrictEqual(editor.getModel().getValue(), 'var x = 3 + 5-7; y();');235});236});237238239