module Test.Language.Javascript.RoundTrip ( testRoundTrip ) where import Test.Hspec import Language.JavaScript.Parser import qualified Language.JavaScript.Parser.AST as AST testRoundTrip :: Spec testRoundTrip = describe "Roundtrip:" $ do it "multi comment" $ do testRT "/*a*/\n//foo\nnull" testRT "/*a*/x" testRT "/*a*/null" testRT "/*b*/false" testRT "true/*c*/" testRT "/*c*/true" testRT "/*d*/0x1234fF" testRT "/*e*/1.0e4" testRT "/*x*/011" testRT "/*f*/\"hello\\nworld\"" testRT "/*g*/'hello\\nworld'" testRT "/*h*/this" testRT "/*i*//blah/" testRT "//j\nthis_" it "arrays" $ do testRT "/*a*/[/*b*/]" testRT "/*a*/[/*b*/,/*c*/]" testRT "/*a*/[/*b*/,/*c*/,/*d*/]" testRT "/*a*/[/*b/*,/*c*/,/*d*/x/*e*/]" testRT "/*a*/[/*b*/,/*c*/,/*d*/x/*e*/]" testRT "/*a*/[/*b*/,/*c*/x/*d*/,/*e*/,/*f*/x/*g*/]" testRT "/*a*/[/*b*/x/*c*/]" testRT "/*a*/[/*b*/x/*c*/,/*d*/]" it "object literals" $ do testRT "/*a*/{/*b*/}" testRT "/*a*/{/*b*/x/*c*/:/*d*/1/*e*/}" testRT "/*a*/{/*b*/x/*c*/}" testRT "/*a*/{/*b*/of/*c*/}" testRT "x=/*a*/{/*b*/x/*c*/:/*d*/1/*e*/,/*f*/y/*g*/:/*h*/2/*i*/}" testRT "x=/*a*/{/*b*/x/*c*/:/*d*/1/*e*/,/*f*/y/*g*/:/*h*/2/*i*/,/*j*/z/*k*/:/*l*/3/*m*/}" testRT "a=/*a*/{/*b*/x/*c*/:/*d*/1/*e*/,/*f*/}" testRT "/*a*/{/*b*/[/*c*/x/*d*/+/*e*/y/*f*/]/*g*/:/*h*/1/*i*/}" testRT "/*a*/{/*b*/a/*c*/(/*d*/x/*e*/,/*f*/y/*g*/)/*h*/{/*i*/}/*j*/}" testRT "/*a*/{/*b*/[/*c*/x/*d*/+/*e*/y/*f*/]/*g*/(/*h*/)/*i*/{/*j*/}/*k*/}" testRT "/*a*/{/*b*/*/*c*/a/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/}" it "miscellaneous" $ do testRT "/*a*/(/*b*/56/*c*/)" testRT "/*a*/true/*b*/?/*c*/1/*d*/:/*e*/2" testRT "/*a*/x/*b*/||/*c*/y" testRT "/*a*/x/*b*/&&/*c*/y" testRT "/*a*/x/*b*/|/*c*/y" testRT "/*a*/x/*b*/^/*c*/y" testRT "/*a*/x/*b*/&/*c*/y" testRT "/*a*/x/*b*/==/*c*/y" testRT "/*a*/x/*b*/!=/*c*/y" testRT "/*a*/x/*b*/===/*c*/y" testRT "/*a*/x/*b*/!==/*c*/y" testRT "/*a*/x/*b*//*c*/y" testRT "/*a*/x/*b*/<=/*c*/y" testRT "/*a*/x/*b*/>=/*c*/y" testRT "/*a*/x /*b*/instanceof /*c*/y" testRT "/*a*/x/*b*/=/*c*/{/*d*/get/*e*/ foo/*f*/(/*g*/)/*h*/ {/*i*/return/*j*/ 1/*k*/}/*l*/,/*m*/set/*n*/ foo/*o*/(/*p*/a/*q*/) /*r*/{/*s*/x/*t*/=/*u*/a/*v*/}/*w*/}" testRT "x = { set foo(/*a*/[/*b*/a/*c*/,/*d*/b/*e*/]/*f*/=/*g*/y/*h*/) {} }" testRT "... /*a*/ x" testRT "a => {}" testRT "(a) => { a + 2 }" testRT "(a, b) => {}" testRT "(a, b) => a + b" testRT "() => { 42 }" testRT "(...a) => a" testRT "(a=1, b=2) => a + b" testRT "([a, b]) => a + b" testRT "({a, b}) => a + b" testRT "function (...a) {}" testRT "function (a=1, b=2) {}" testRT "function ([a, ...b]) {}" testRT "function ({a, b: c}) {}" testRT "/*a*/function/*b*/*/*c*/f/*d*/(/*e*/)/*f*/{/*g*/yield/*h*/a/*i*/}/*j*/" testRT "function*(a, b) { yield a ; yield b ; }" testRT "/*a*/`<${/*b*/x/*c*/}>`/*d*/" testRT "`\\${}`" testRT "`\n\n`" testRT "{}+``" -- ^ https://github.com/erikd/language-javascript/issues/104 it "statement" $ do testRT "if (1) {}" testRT "if (1) {} else {}" testRT "if (1) x=1; else {}" testRT "do {x=1} while (true);" testRT "do x=x+1;while(x<4);" testRT "while(true);" testRT "for(;;);" testRT "for(x=1;x<10;x++);" testRT "for(var x;;);" testRT "for(var x=1;;);" testRT "for(var x;y;z){}" testRT "for(x in 5){}" testRT "for(var x in 5){}" testRT "for(let x;y;z){}" testRT "for(let x in 5){}" testRT "for(let x of 5){}" testRT "for(const x;y;z){}" testRT "for(const x in 5){}" testRT "for(const x of 5){}" testRT "for(x of 5){}" testRT "for(var x of 5){}" testRT "var x=1;" testRT "const x=1,y=2;" testRT "continue;" testRT "continue x;" testRT "break;" testRT "break x;" testRT "return;" testRT "return x;" testRT "with (x) {};" testRT "abc:x=1" testRT "switch (x) {}" testRT "switch (x) {case 1:break;}" testRT "switch (x) {case 0:\ncase 1:break;}" testRT "switch (x) {default:break;}" testRT "switch (x) {default:\ncase 1:break;}" testRT "var x=1;let y=2;" testRT "var [x, y]=z;" testRT "let {x: [y]}=z;" testRT "let yield=1" it "module" $ do testRTModule "import def from 'mod'" testRTModule "import def from \"mod\";" testRTModule "import * as foo from \"mod\" ; " testRTModule "import def, * as foo from \"mod\" ; " testRTModule "import { baz, bar as foo } from \"mod\" ; " testRTModule "import def, { baz, bar as foo } from \"mod\" ; " testRTModule "export {};" testRTModule " export {} ; " testRTModule "export { a , b , c };" testRTModule "export { a, X as B, c }" testRTModule "export {} from \"mod\";" testRTModule "export const a = 1 ; " testRTModule "export function f () { } ; " testRTModule "export function * f () { } ; " testRTModule "export class Foo\nextends Bar\n{ get a () { return 1 ; } static b ( x,y ) {} ; } ; " testRT :: String -> Expectation testRT = testRTWith readJs testRTModule :: String -> Expectation testRTModule = testRTWith readJsModule testRTWith :: (String -> AST.JSAST) -> String -> Expectation testRTWith f str = renderToString (f str) `shouldBe` str