import * as assert from 'assert' ; import { before } from 'mocha' ; import * as vscode from 'vscode' ; import { PddlOnTypeFormatter } from '../../formatting/PddlOnTypeFormatter' ; import { assertStrictEqualDecorated } from './testUtils' ; let formatProvider ; suite ( 'PDDL on-type formatter Test Suite' , ( ) => { before ( async ( ) => { vscode . window . showInformationMessage ( 'Start all tests.' ) ; formatProvider = new PddlOnTypeFormatter ( undefined , true ) ; } ) ; test ( 'should indent nested text on new-line char' , async ( ) => { const inputTextHead = '(define ' ; const ch = '\n' ; const inputTextTail = ')' ; const expectedText = inputTextHead + ch + '\t\n' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent nested text on new-line char in already indented line' , async ( ) => { const inputTextHead = '\t(define ' ; const ch = '\n' ; const inputTextTail = ')' ; const expectedText = inputTextHead + ch + '\t\t\n\t' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent nested text on new-line char, inside 2nd level' , async ( ) => { const inputTextHead = '(define \n' + '\t(:requirements' ; const ch = '\n' ; const inputTextTail = ')\n)' ; const expectedText = inputTextHead + ch + '\t\t\n\t' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should honor wrong indentation on new-line char, inside unindented 1st level' , async ( ) => { const inputTextHead = '(define \n' + '(:requirements' ; const ch = '\n' ; const inputTextTail = ')\n)' ; const expectedText = inputTextHead + ch + '\t\n' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should honor wrong indentation on additional new-line insertion, inside unindented 1st level' , async ( ) => { const previousIndent = '  ' ; const inputTextHead = '(define \n' + previousIndent + '(:requirements )\n\n' ; const ch = '\n' ; const inputTextTail = '\n)' ; const expectedText = inputTextHead + ch + previousIndent + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent nested text on new-line char, inside action precondition' , async ( ) => { const inputTextHead = '(:action a \n' + '\t:precondition (and' ; const ch = '\n' ; const inputTextTail = ')\n)' ; const expectedText = inputTextHead + ch + '\t\t\n\t' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent when adding an empty line' , async ( ) => { const inputTextHead = '(define \n' ; const ch = '\n' ; const inputTextTail = `)` ; const expectedText = inputTextHead + ch + '\t\n' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent when adding an empty line after 1-indented' , async ( ) => { const inputTextHead = '(define \n\t' ; const ch = '\n' ; const inputTextTail = `)` ; const expectedText = inputTextHead + ch + '\t\n' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent when adding an empty line after 2x 1-indented' , async ( ) => { const inputTextHead = '(define \n\t\n\t' ; const ch = '\n' ; const inputTextTail = `)` ; const expectedText = inputTextHead + ch + '\t\n' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test ( 'should indent following text when enter is pressed mid-text' , async ( ) => { const inputTextHead = '(define ' ; const ch = '\n' ; const inputTextTail = `(following-text)\n)` ; const expectedText = inputTextHead + ch + '\t' + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; test . skip ( 'should indent nested open bracket - disabled to preserve auto-completion' , async ( ) => { const inputTextHead = '(define \n' ; const ch = '(' ; const inputTextTail = '\n)' ; const expectedText = inputTextHead + '\t' + ch + inputTextTail ; await testFormatter ( inputTextHead , ch , inputTextTail , expectedText , { insertSpaces : false , tabSize : 4 } ) ; } ) ; } ) ; async function testFormatter ( inputTextHead , ch , inputTextTail , expectedText , options ) { const initialText = inputTextHead + ch + inputTextTail ; const doc = await vscode . workspace . openTextDocument ( { language : 'pddl-do-not-load-extension' , content : initialText } ) ; const editor = await vscode . window . showTextDocument ( doc ) ; const position = doc . positionAt ( ( inputTextHead + ch ) . length ) ; editor . selection = new vscode . Selection ( position , position ) ; const startSelectionBefore = editor . selection . start ; const edits = await formatProvider . provideOnTypeFormattingEdits ( doc , position , ch , options , new vscode . CancellationTokenSource ( ) . token ) ; if ( edits ) { await editor . edit ( builder => reBuild ( builder , edits ) ) ; } else { assert . fail ( 'no edits returned' ) ; } const startSelectionAfter = editor . selection . start ; const textAfter = doc . getText ( ) ; assertStrictEqualDecorated ( textAfter , expectedText , "document text should be formatted" ) ; assert . deepStrictEqual ( startSelectionAfter , startSelectionBefore , "cursor position should be the same" ) ; } function reBuild ( builder , edits ) { edits . forEach ( edit => builder . replace ( edit . range , edit . newText ) ) ; }