package main import ( "github.com/Fuwn/iku/engine" "testing" ) type ecmaScriptTestCase struct { name string source string expected string } var ecmaScriptTestCases = []ecmaScriptTestCase{ { name: "blank lines around if block", source: `const x = 1; if (x > 0) { doSomething(); } const y = 2; `, expected: `const x = 1; if (x > 0) { doSomething(); } const y = 2; `, }, { name: "blank lines around for loop", source: `const items = [1, 2, 3]; for (const item of items) { process(item); } const result = done(); `, expected: `const items = [1, 2, 3]; for (const item of items) { process(item); } const result = done(); `, }, { name: "blank lines between different top-level types", source: `import { foo } from "bar"; const x = 1; function main() { return x; } class Foo { bar() {} } `, expected: `import { foo } from "bar"; const x = 1; function main() { return x; } class Foo { bar() {} } `, }, { name: "no blank between same type", source: `const x = 1; const y = 2; const z = 3; `, expected: `const x = 1; const y = 2; const z = 3; `, }, { name: "consecutive imports stay together", source: `import { a } from "a"; import { b } from "b"; import { c } from "c"; `, expected: `import { a } from "a"; import { b } from "b"; import { c } from "c"; `, }, { name: "switch with case clauses", source: `const x = getValue(); switch (x) { case "a": handleA(); break; case "b": handleB(); break; } cleanup(); `, expected: `const x = getValue(); switch (x) { case "a": handleA(); break; case "b": handleB(); break; } cleanup(); `, }, { name: "try catch finally", source: `setup(); try { riskyOperation(); } catch (error) { handleError(error); } finally { cleanup(); } done(); `, expected: `setup(); try { riskyOperation(); } catch (error) { handleError(error); } finally { cleanup(); } done(); `, }, { name: "consecutive scoped blocks", source: `if (a) { doA(); } if (b) { doB(); } `, expected: `if (a) { doA(); } if (b) { doB(); } `, }, { name: "export prefixes", source: `export const x = 1; export function foo() { return x; } export class Bar { baz() {} } `, expected: `export const x = 1; export function foo() { return x; } export class Bar { baz() {} } `, }, { name: "async function", source: `const data = prepare(); async function fetchData() { return await fetch(url); } const result = process(); `, expected: `const data = prepare(); async function fetchData() { return await fetch(url); } const result = process(); `, }, { name: "typescript interface and type", source: `type ID = string; interface User { name: string; id: ID; } const defaultUser: User = { name: "", id: "" }; `, expected: `type ID = string; interface User { name: string; id: ID; } const defaultUser: User = { name: "", id: "" }; `, }, { name: "multi-line function call preserved", source: `const result = someFunction( longArgument, otherArgument, ); const next = 1; `, expected: `const result = someFunction( longArgument, otherArgument, ); const next = 1; `, }, { name: "method chaining preserved", source: `const result = someArray .filter(x => x > 0) .map(x => x * 2); const next = 1; `, expected: `const result = someArray .filter(x => x > 0) .map(x => x * 2); const next = 1; `, }, { name: "block comment passthrough", source: `/* * This is a block comment */ const x = 1; `, expected: `/* * This is a block comment */ const x = 1; `, }, { name: "collapses extra blank lines", source: `const x = 1; const y = 2; `, expected: `const x = 1; const y = 2; `, }, { name: "while loop", source: `let count = 0; while (count < 10) { count++; } const done = true; `, expected: `let count = 0; while (count < 10) { count++; } const done = true; `, }, { name: "nested scopes", source: `function main() { const x = 1; if (x > 0) { for (let i = 0; i < x; i++) { process(i); } cleanup(); } return x; } `, expected: `function main() { const x = 1; if (x > 0) { for (let i = 0; i < x; i++) { process(i); } cleanup(); } return x; } `, }, { name: "template literal passthrough", source: "const x = `\nhello\n\nworld\n`;\nconst y = 1;\n", expected: "const x = `\nhello\n\nworld\n`;\nconst y = 1;\n", }, { name: "jsx expressions", source: `function Component() { const data = useMemo(); if (!data) { return null; } return (