diff --git a/package.json b/package.json index 3958d73d..4f4a4630 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,7 @@ "test:sanity": "npm run test:wtest -- --root language/test/sanity", "test:validations": "mocha --parallel -r ts-node/register/transpile-only test/validator.test.ts", "test:wtest": "mocha --delay -t 10000 -r ts-node/register/transpile-only test/wtest.ts", - "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer.test.ts", + "test:printer": "mocha --parallel -r ts-node/register/transpile-only test/printer-tests/*.test.ts", "prepublishOnly": "npm run build && npm test", "postpublish": "git tag v$npm_package_version && git push --tags", "prepack": "npm run build" diff --git a/src/constants.ts b/src/constants.ts index cef10db1..c47eddd7 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -54,5 +54,4 @@ export const KEYWORDS = { FIXTURE: 'fixture', PROGRAM: 'program', PACKAGE: 'package', - } as const \ No newline at end of file diff --git a/src/printer/print.ts b/src/printer/print.ts index 0c944e22..b92cea7a 100644 --- a/src/printer/print.ts +++ b/src/printer/print.ts @@ -1,7 +1,7 @@ import { IDoc, append, braces, choice, enclose, hang as nativeHang, intersperse, lineBreak, lineBreaks, indent as nativeIndent, nest as nativeNest, parens, render, softBreak, softLine, align } from 'prettier-printer' -import { KEYWORDS, LIST_MODULE, SET_MODULE } from '../constants' +import { KEYWORDS, LIST_MODULE, PREFIX_OPERATORS, SET_MODULE } from '../constants' import { List, match, when, notEmpty, isEmpty } from '../extensions' -import { Assignment, Body, Class, Describe, Expression, Field, If, Import, Literal, Method, Mixin, NamedArgument, New, Node, Package, Parameter, ParameterizedType, Program, Reference, Return, Self, Send, Sentence, Singleton, Super, Test, Variable } from '../model' +import { Assignment, Body, Class, Describe, Expression, Field, If, Import, Literal, Method, Mixin, Name, NamedArgument, New, Node, Package, Parameter, ParameterizedType, Program, Reference, Return, Self, Send, Sentence, Singleton, Super, Test, Variable } from '../model' import { DocTransformer, WS, body, enclosedList, infixOperators, listEnclosers, listed, setEnclosers, stringify } from './utils' type PrintSettings = { @@ -74,7 +74,7 @@ const format: FormatterWithContext = context => node => { } const formatPackage: FormatterWithContext = context => node => { - return [node.imports.length > 0 ? [intersperse(lineBreak, node.imports.map(format(context))), lineBreaks] : [], intersperse( + return [notEmpty(node.imports) ? [intersperse(lineBreak, node.imports.map(format(context))), lineBreaks] : [], intersperse( lineBreaks, node.members.map(format(context)) )] @@ -268,7 +268,7 @@ const formatMixin: FormatterWithContext =context => node => { KEYWORDS.MIXIN, WS, node.name, - node.supertypes.length > 0 ? [WS, KEYWORDS.INHERITS, WS, intersperse([WS, KEYWORDS.MIXED_AND, WS], node.supertypes.map(format(context)))] : [], + notEmpty(node.supertypes) ? [WS, KEYWORDS.INHERITS, WS, intersperse([WS, KEYWORDS.MIXED_AND, WS], node.supertypes.map(format(context)))] : [], ] return [declaration, WS, formatModuleMembers(context)(node.members)] @@ -277,7 +277,7 @@ const formatMixin: FormatterWithContext =context => node => { const formatParameterizedType: FormatterWithContext = context => node => [ node.reference.name, - node.args.length > 0 ? + notEmpty(node.args) ? [WS, enclosedList(context.nest)(parens, node.args.map(format(context)))] : [], ] @@ -294,7 +294,7 @@ const formatSingleton: FormatterWithContext = context => (node: Singl const formatClosure: FormatterWithContext = context => node => { const applyMethod = node.members[0] as Method - const parameters = applyMethod.parameters.length > 0 ? + const parameters = notEmpty(applyMethod.parameters) ? [WS, listed(applyMethod.parameters.map(format(context))), WS, '=>'] : [] @@ -320,7 +320,7 @@ const formatWKO: FormatterWithContext = context => node => { return intersperse(WS, [...formatted, members]) } -const inherits = (node: Singleton | Class) => node.supertypes.length > 0 +const inherits = (node: Singleton | Class) => notEmpty(node.supertypes) const formatInheritance: FormatterWithContext = (context: PrintContext) => node => { return intersperse(WS, [ @@ -333,9 +333,19 @@ const formatInheritance: FormatterWithContext = (context: Pri // SEND FORMATTERS const formatSend: FormatterWithContext = context => node => { - return infixOperators.includes(node.message) ? - formatInfixSend(context)(node) - : formatDotSend(context)(node) + let formatter: FormatterWithContext + + if(isInfixOperator(node)) { + formatter = formatInfixSend + } else if( + isPrefixOperator(node) + ) { + formatter = formatPrefixSend + } else { + formatter = formatDotSend + } + + return formatter(context)(node) } const formatDotSend: FormatterWithContext = context => node => [ @@ -353,10 +363,16 @@ const formatInfixSend: FormatterWithContext = context => node => { ]) } +const formatPrefixSend: FormatterWithContext = context => node => { + return [prefixOperatorByMessage[node.message], addParenthesisIfNeeded(context, node.receiver)] +} + function addParenthesisIfNeeded(context: PrintContext, expression: Expression): IDoc { // ToDo: add more cases where parenthesis aren't needed const formatted = format(context)(expression) - return expression.is(Send) && infixOperators.includes(expression.message) ? enclose(parens, formatted) : formatted + return expression.is(Send) && (isInfixOperator(expression) || isPrefixOperator(expression)) ? + enclose(parens, formatted) : + formatted } @@ -402,4 +418,25 @@ const formatModuleMembers = (context: PrintContext) => (members: List node.value.is(Send) && node.value.receiver.is(Reference) && node.value.receiver.name === node.variable.name && node.value.message in assignmentOperationByMessage -const assignmentOperationByMessage = { '||':'||=', '/':'/=', '-':'-=', '+':'+=', '*':'*=', '&&':'&&=', '%':'%=' } as const \ No newline at end of file +const assignmentOperationByMessage = { '||':'||=', '/':'/=', '-':'-=', '+':'+=', '*':'*=', '&&':'&&=', '%':'%=' } as const + +// send utils + +/* + * ToDo: safe way of telling if this is a parser-generated message or a user-defined one + * e.g. x.negate() shouldnt be formatted to !x + */ +const isPrefixOperator = (node: Send): boolean => + Object.values(PREFIX_OPERATORS).includes(node.message) && + isEmpty(node.args) + +const isInfixOperator = (node: Send): boolean => + infixOperators.includes(node.message) && + node.args.length === 1 + +//ToDo: missing 'not' +const prefixOperatorByMessage: Record = { + 'negate': '!', + 'invert': '-', + 'plus': '+', +} \ No newline at end of file diff --git a/test/printer-tests/complex-flow.test.ts b/test/printer-tests/complex-flow.test.ts new file mode 100644 index 00000000..bc6b9225 --- /dev/null +++ b/test/printer-tests/complex-flow.test.ts @@ -0,0 +1,482 @@ +import { should, use } from 'chai' +import { printerAssertions } from '../assertions' + +use(printerAssertions) +should() + + +describe('Complex flow', () => { + it('program_ifInline', () => { + `program p { + const a = 10 + const b = 0 + + const c = if (a > 0) b else + + + 0 + }`.should.be.formattedTo( ` + program p { + const a = 10 + const b = 0 + const c = if (a > 0) b else 0 + }`) + }) + + it('program_ifInlineWithExpressions', () => { + `program p { + const a = 10 + const b = 0 + + const c = if (a > 0) b+1 else b-1 + }`.should.be.formattedTo( ` + program p { + const a = 10 + const b = 0 + const c = if (a > 0) b + 1 else b - 1 + }`) + }) + + it('issue702_forEachAndIf', () => { + ` + object foo { + method bar() { + [3, 4 ,50, 100 ].forEach({ it => if (it > 4) { console.println(4) } else {console.println(it) + } + }) + } + } + `.should.be.formattedTo(` + object foo { + + method bar() { + [3, 4, 50, 100].forEach({ it => + if (it > 4) { + console.println(4) + } else { + console.println(it) + } + }) + } + }`) + }) + + it('issue702_forEachAndIf_2', () => { + ` + object foo { + method bar() { + [3, 4 ,50, 100 ].forEach({ it => if (it > 4) console.println(4) else console.println(it) + + }) + } + } + `.should.be.formattedTo(` + object foo { + method bar() { + [ 3, 4, 50, 100 ].forEach({ it => + if (it > 4) console.println(4) else console.println(it) + }) + } + }`) + }) + + it('program_maxOneLineBreakBetweenLines', () => { + `program p { + const a = 10 + const b = 0 + + + + const c = a + b + }`.should.be.formattedTo( ` + program p { + const a = 10 + const b = 0 + const c = a + b + } + `) + }) + + it('basicTryCatch', () => { + ` +program abc { + console.println(4) + try + { + 5 + 5 + } + catch e : Exception + { + console.println(e) + } + } + `.should.be.formattedTo(` + program abc { + console.println(4) + try { + 5 + 5 + } catch e : Exception { + console.println(e) + } + }`) + }) + + it('tryBlockWithSeveralCatchsAndAFinally', () => { + ` + program abc { + console.println(4) + try{5 + 5} + catch e : UserException { + console.println(e) + } catch e2:Exception {console.println("Bad error") console.println("Do nothing")} + + + + + + then always { console.println("finally") + + + } + } + `.should.be.formattedTo(` + program abc { + console.println(4) + try { + 5 + 5 + } catch e : UserException { + console.println(e) + } catch e2 : Exception { + console.println("Bad error") + console.println("Do nothing") + } then always { + console.println("finally") + } + }`) + }) + + it('oneLineTryCatch', () => { + ` + program abc { + console.println(4) + try + + + + + 5 + 5 + + + catch e : Exception + + + console.println(e) + } + `.should.be.formattedTo(` + program abc { + console.println(4) + try + 5 + 5 + catch e : Exception + console.println(e) + }`) + }) + + it('throwFormattingTest', () => { + + ` + object foo { + method attack(target) { + var attackers = self.standingMembers() + if (attackers.isEmpty()) throw + new CannotAttackException( + + + + message + + + ="No attackers available") attackers.forEach({ + aMember => + + + aMember. + attack(target) }) + } + } + `.should.be.formattedTo(` + object foo { + method attack(target) { + var attackers = self.standingMembers() + if (attackers.isEmpty()) throw new CannotAttackException(message = "No attackers available") + attackers.forEach({ aMember => aMember.attack(target)}) + } + }`) + }) + + it('testAllWithClosure', () => { + + ` + class Cantante { const albumes = new Set() +method esMinimalista() = albumes.all{ + album => + album.sonTodasCancionesCortas() + } + } + `.should.be.formattedTo(` + class Cantante { + const albumes = new Set() + + method esMinimalista() = albumes.all({ album => album.sonTodasCancionesCortas() }) + }`) + }) + + it('testForEachWithComplexClosure', () => { + + ` + class Cantante { const albumes = new Set() +method mejorarAlbumes() { + albumes.forEach{ + album => + album.agregarCancion(new Cancion()) + album.sumarCosto(100) + }} + } + `.should.be.formattedTo(` + class Cantante { + + const albumes = new Set() + + method mejorarAlbumes() { + albumes.forEach({ album => + album.agregarCancion(new Cancion()) + album.sumarCosto(100) + }) + } + + }`) + }) + + it('doubleIfInMethod', () => { + + ` + object pepita { + const posicion = game.at(2, 0) + var energia = 50 + method energia() { + return energia + } + method imagen() { + if (energia < 150) return "pepita.png" + if (energia < 300) return "pepita1.png" + return "pepita2.png" + } + + + } + `.should.be.formattedTo(` + object pepita { + + const posicion = game.at(2, 0) + var energia = 50 + + method energia() { + return energia + } + + method imagen() { + if (energia < 150) return "pepita.png" + if (energia < 300) return "pepita1.png" + return "pepita2.png" + } + + }`) + }) + + it('testWithIfExpression', () => { + + ` + object laTrastienda { + + const capacidadPlantaBaja = 400 + const capacidadPrimerPiso = 300 + + method capacidad(dia) { + if (dia.dayOfWeek() + + + == 6) { + return capacidadPlantaBaja + capacidadPrimerPiso + } else { + return capacidadPlantaBaja + } + } + + } + `.should.be.formattedTo(` + object laTrastienda { + + const capacidadPlantaBaja = 400 + const capacidadPrimerPiso = 300 + + method capacidad(dia) { + if (dia.dayOfWeek() == 6) { + return capacidadPlantaBaja + capacidadPrimerPiso + } else { + return capacidadPlantaBaja + } + } + + }`) + + }) + + it('testFold', () => { + + ` +class Mashup inherits Cancion { + +var nombre = "" + var duracion = 0 + var letra = "" + + var bloqueNumeroPositivo = { num => num > 0 } + + + + + + method concatenarNombres(canciones) { + return canciones.fold("" , { acum , cancion => acum + cancion.nombre() } + + + ) + }) + + } + `.should.be.formattedTo(` + class Mashup inherits Cancion { + + var nombre = "" + var duracion = 0 + var letra = "" + var bloqueNumeroPositivo = { num => num > 0 } + + method concatenarNombres(canciones) { + return canciones.fold("", { acum , cancion => acum + cancion.nombre() }) + } + + } + + ` + ) + }) + + it( 'testReturnAndIf', () => { + ` + object lucia { + + const costePresentacionNoConcurrida = 400 + const costePresentacionConcurrida = 500 + var cantaEnGrupo = true + const habilidad = 70 + + method habilidad() = habilidad + self.sumaHabilidad() + + method sumaHabilidad() { + if (cantaEnGrupo) return - 20 + return 0 + } + } + `.should.be.formattedTo(` + object lucia { + const costePresentacionNoConcurrida = 400 + const costePresentacionConcurrida = 500 + var cantaEnGrupo = true + const habilidad = 70 + + method habilidad() = ( habilidad + self.sumaHabilidad() ) + + method sumaHabilidad() { + if (cantaEnGrupo) return -20 + return 0 + } + }` + ) + }) + + it('testReturnSelfExpression', () => { + ` + class AlbumBuilder { + + var fechaLanzamiento + + method fechaLanzamiento(dia, mes, anio) { + fechaLanzamiento = new Date(day = dia, month = mes, year = anio) + return self + } + + } `.should.be.formattedTo(` + class AlbumBuilder { + var fechaLanzamiento + + method fechaLanzamiento(dia, mes, anio) { + fechaLanzamiento = new Date(day = dia, month = mes, year = anio) + return self + } + }`) + }) + + it('unaryWordExpression', () => { + ` + object lunaPark {} + class Presentacion { var fecha var lugar var musicos } + object pdpalooza inherits Presentacion(fecha = new Date(day = 15, month = 12, year = 2017), lugar = lunaPark, musicos = []){ + const restriccionHabilidad = { musico => if (musico.habilidad() < 70) throw new Exception(message = "La habilidad del músico debe ser mayor a 70")} + const restriccionCompusoAlgunaCancion = {musico => if (not musico.compusoAlgunaCancion()) throw new Exception(message = "El músico debe haber compuesto al menos una canción")} + } + `.should.be.formattedTo(` + object lunaPark { + + } + + class Presentacion { + var fecha + var lugar + var musicos + } + + object pdpalooza inherits Presentacion(fecha = new Date(day = 15, month = 12, year = 2017), lugar = lunaPark, musicos = []) { + const restriccionHabilidad = { musico => + if (musico.habilidad() < 70) throw new Exception(message = "La habilidad del músico debe ser mayor a 70") + } + const restriccionCompusoAlgunaCancion = { musico => + if (not musico.compusoAlgunaCancion()) throw new Exception(message = "El músico debe haber compuesto al menos una canción") + } + }`) + }) + + it('testObjectWithClosureImplementingRestrictions', () => { + + ` + object restriccionCompositor { + + method verificarMusico(musico) { + if (!musico.cancionesPublicadas().any{ unaCancion => musico.esSuCancion(unaCancion)}) { + throw new UserException(message = "No se puede agregar al musico ya que no compuso ninguna cancion") + } + } + + } + `.should.be.formattedTo(` + object restriccionCompositor { + + method verificarMusico(musico) { + if (!musico.cancionesPublicadas().any({ unaCancion => musico.esSuCancion(unaCancion)})) { + throw new UserException(message = "No se puede agregar al musico ya que no compuso ninguna cancion") + } + } + + }`) + }) +}) \ No newline at end of file diff --git a/test/printer.test.ts b/test/printer-tests/printer.test.ts similarity index 87% rename from test/printer.test.ts rename to test/printer-tests/printer.test.ts index 13dad7ec..e859af2b 100644 --- a/test/printer.test.ts +++ b/test/printer-tests/printer.test.ts @@ -1,5 +1,5 @@ import { use, should } from 'chai' -import { printerAssertions } from './assertions' +import { printerAssertions } from '../assertions' use(printerAssertions) should() @@ -110,7 +110,7 @@ describe('Wollok Printer', () => { }) }) }) - describe('Object definitions', () => { + describe('Object', () => { it('testBasicObjectDefinition', () => { `object pepita { var energia = 0 method volar() { energia += 10 } @@ -586,7 +586,7 @@ describe('Wollok Printer', () => { } method quitarParticipante(persona) { - if (not (participantes.isEmpty())) { + if (! (participantes.isEmpty())) { if (participantes.contains(persona)) { participantes.remove(persona) } else { @@ -627,11 +627,11 @@ describe('Wollok Printer', () => { } method quitarParticipante(persona) { - if (participantes.isEmpty().negate()) if (participantes.contains(persona)) - participantes.remove(persona) - else self.error( - "La persona que se desea quitar no era integrante de la presentacion" - ) + if (!participantes.isEmpty()) if (participantes.contains(persona)) + participantes.remove(persona) + else self.error( + "La persona que se desea quitar no era integrante de la presentacion" + ) else self.error("El conjunto de participantes esta vacio") } @@ -694,7 +694,7 @@ describe('Wollok Printer', () => { }`) }) }) - describe('Methods formatter', () => { + describe('Methods', () => { it('testBasicFormattingInMethod', () => { ` object foo { @@ -886,7 +886,7 @@ describe('Wollok Printer', () => { it('testClassFormattingOneLineMethodStaysInNewLine', () => { `class Golondrina { const energia = 10 const kmRecorridos = 0 method comer(gr) { energia = energia + gr - } }`.should.be.formattedTo (` + } }`.should.be.formattedTo(` class Golondrina { const energia = 10 const kmRecorridos = 0 @@ -908,7 +908,7 @@ describe('Wollok Printer', () => { console.println("") console.println("") } - }`.should.be.formattedTo (` + }`.should.be.formattedTo(` object foo { method bar() { self.bar().bar().bar() @@ -920,22 +920,21 @@ describe('Wollok Printer', () => { }`) }) - // ToDo: Not parsable - // it('messageSendParameters', () => { - // `program p { - // const a = null + it('messageSendParameters', () => { + `program p { + const a = null - // a . doSomething ( a, a, a , a , a ) - // a ?. doSomething ( a, a, a , a , a ) - // a ?. doSomething ({=> a .doSomething()}) - // }`.should.be.formattedTo (` - // program p { - // const a = null - // a.doSomething(a, a, a, a, a) - // a?.doSomething(a, a, a, a, a) - // a?.doSomething({=> a.doSomething() }) - // })`) - // }) + a . doSomething ( a, a, a , a , a ) + a. doSomething ( a, a, a , a , a ) + a. doSomething ({=> a .doSomething()}) + }`.should.be.formattedTo(` + program p { + const a = null + a.doSomething(a, a, a, a, a) + a.doSomething(a, a, a, a, a) + a.doSomething({ a.doSomething() }) + }`) + }) it('listWithPreviousConflicts', () => { @@ -1010,7 +1009,7 @@ describe('Wollok Printer', () => { override method volar(minutos) { super (minutos * ( 10 - 2 ) ) } - }`.should.be.formattedTo (` + }`.should.be.formattedTo(` class Ave { var energia = 0 @@ -1104,27 +1103,27 @@ describe('Wollok Printer', () => { }`) }) }) - describe('Package definitions', () => { - // ToDo: package??? - // it('testBasicPackageDefinition', () => { - // ` - // package aves - - - // { - // object pepita { var energia = 0 method volar() { energia += - // 10 } - // }`.should.be.formattedTo(` - // package aves { - // object pepita { - // var energia = 0 - - // method volar() { - // energia += 10 - // } - // } - // }`) - // }) + describe('Package', () => { + // ToDo: package + xit('testBasicPackageDefinition', () => { + ` + package aves + + + { + object pepita { var energia = 0 method volar() { energia += + 10 } + }`.should.be.formattedTo(` + package aves { + object pepita { + var energia = 0 + + method volar() { + energia += 10 + } + } + }`) + }) it('testBasicImportDefinition', () => { `import wollok. game.* @@ -1146,7 +1145,7 @@ describe('Wollok Printer', () => { }`) }) }) - describe('Program formatter', () => { + describe('Program', () => { it('testSimpleProgramWithVariablesAndMessageSend', () => { 'program p { const a = 10 const b = 20 self.println(a + b) }'.should.be.formattedTo(` program p { @@ -1156,7 +1155,7 @@ describe('Wollok Printer', () => { }`) }) }) - describe('Testing formatter', () => { + describe('Testing', () => { it('testConstantsFormatting', () => { `const a = new Sobreviviente() @@ -1175,7 +1174,7 @@ describe('Wollok Printer', () => { it('testSimpleTestFormatting', () => { - 'test "aSimpleTest"{ assert.that(true) }'.should.be.formattedTo (` + 'test "aSimpleTest"{ assert.that(true) }'.should.be.formattedTo(` test "aSimpleTest" { assert.that(true) } @@ -1199,6 +1198,7 @@ describe('Wollok Printer', () => { test "secondTest" { var text = "hola" + assert.equals(4, text.length()) assert.equals(4 - 0, (-4).inverted()) } @@ -1210,7 +1210,7 @@ describe('Wollok Printer', () => { const a = 1 assert.equals( 1 , a) assert.equals(a, a) - }`.should.be.formattedTo (` + }`.should.be.formattedTo(` test "aSimpleTest" { assert.that(true) assert.notThat(false) @@ -1240,7 +1240,7 @@ describe('Wollok Printer', () => { }) it('testSimpleDescribeFormatting2', () => { - 'describe "group of tests"{test "aSimpleTest"{assert.that(true)}}'.should.be.formattedTo (` + 'describe "group of tests"{test "aSimpleTest"{assert.that(true)}}'.should.be.formattedTo(` describe "group of tests" { test "aSimpleTest" { assert.that(true) @@ -1329,7 +1329,7 @@ describe('Wollok Printer', () => { assert.equals(1, a) - }}`.should.be.formattedTo (` + }}`.should.be.formattedTo(` object foo { method bar() = 1 } @@ -1427,7 +1427,8 @@ describe('Wollok Printer', () => { }`) }) - it('testAnotherInitializeWithComplexDefinition', () => { + //ToDo comments + xit('testAnotherInitializeWithComplexDefinition', () => { ` describe "testDeMusicGuide" { @@ -1658,4 +1659,250 @@ describe('Wollok Printer', () => { }`) }) }) + describe('Variables', () => { + it('testSeveralVariableDefinitionsToConstantsInMethods', () => { + ` + class Foo { + var x var y var z + method addition() { var a = x x = 1 y = 2 z=x+y } + }`.should.be.formattedTo (` + class Foo { + var x + var y + var z + + method addition() { + var a = x + x = 1 + y = 2 + z = x + y + } + }`) + }) + + it('testSeveralVariableDefinitionsToConstantsInMethods2', () => { + ` + class Foo { + var x var y = 5 var z + method addition() { + + + var a = x + + + x = 1 + + + y = 2 z = x + y } + + + }`.should.be.formattedTo (` + class Foo { + var x + var y = 5 + var z + + method addition() { + var a = x + + + + x = 1 + + + + y = 2 + z = x + y + } + }`) + }) + + // sourcemap problems + xit('testSeveralVariableDefinitionsToConstantsInMethods3', () => { + ` + class Foo { + var x var y var z + method addition () { + var a = x + x = 1 + y = 2 + z = x + y } + + + }`.should.be.formattedTo (` + class Foo { + var x + var y + var z + + method addition() { + var a = x + x = 1 + y = 2 + z = x + y + } + }`) + }) + + + it('testSeveralVariableDefinitionsToConstantsInMethods4', () => { + ` + class Foo { + var x + method addition() { x = 1 var a = 2 a = x a += 1 a . inverted() } + }`.should.be.formattedTo ( + ` + class Foo { + var x + + method addition() { + x = 1 + var a = 2 + a = x + a += 1 + a.inverted() + } + }`) + }) + + + it('propertyDefinitionInClass', () => { + ` + class Foo { + var property + + + x + + const + property + + + y + = + 1 + }`.should.be.formattedTo (` + class Foo { + var property x + const property y = 1 + }`) + }) + + it('propertyDefinitionInWko', () => { + ` + object romualdo { + var property + + + x + + const + + property + + + y + = + 1 + }`.should.be.formattedTo (` + object romualdo { + var property x + const property y = 1 + }`) + }) + + + it('propertyDefinitionInMixin', () => { + ` + mixin Jugable { + var property + + + x + + const + property + + + y + = + 1 + }`.should.be.formattedTo (` + mixin Jugable { + var property x + const property y = 1 + }`) + }) + + + it('propertyDefinitionInDescribe', () => { + + ` + describe + + "group of tests" + { + var property + + + x + + const property + + + y + = + 1 + + test "true is true" { assert.that(true) } + }`.should.be.formattedTo (` + describe "group of tests" { + var property x + const property y = 1 + + test "true is true" { + assert.that(true) + } + }`) + }) + }) + describe('Constructor call', () => { + it('constructorCallFormatting', () => { + `class A { var a + var b = 2 var c var d + } + class B { + + method buildA() { + new A( a + + + = + + 200 + , + b = "Hello" + + , + + c = new Date() + + , d=#{1 , 8} ) + }} + `.should.be.formattedTo(` + class A { + var a + var b = 2 + var c + var d + } + + class B { + method buildA() { + new A(a = 200, b = "Hello", c = new Date(), d = #{1, 8}) + } + }`) + }) + + }) }) \ No newline at end of file