package ast_test import ( "testing" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast" "efprojects.com/kitten-ipc/kitcom/internal/tsgo/testutil/parsetestutil" "gotest.tools/v3/assert" ) type NodeComparisonWorkItem struct { original *ast.Node copy *ast.Node } func getChildren(node *ast.Node) []*ast.Node { children := []*ast.Node{} node.VisitEachChild(ast.NewNodeVisitor(func(node *ast.Node) *ast.Node { children = append(children, node) return node }, nil, ast.NodeVisitorHooks{})) return children } func TestDeepCloneNodeSanityCheck(t *testing.T) { t.Parallel() data := []struct { title string input string jsx bool }{ {title: "StringLiteral#1", input: `;"test"`}, {title: "StringLiteral#2", input: `;'test'`}, {title: "NumericLiteral", input: `0`}, {title: "BigIntLiteral", input: `0n`}, {title: "BooleanLiteral#1", input: `true`}, {title: "BooleanLiteral#2", input: `false`}, {title: "NoSubstitutionTemplateLiteral", input: "``"}, {title: "RegularExpressionLiteral#1", input: `/a/`}, {title: "RegularExpressionLiteral#2", input: `/a/g`}, {title: "NullLiteral", input: `null`}, {title: "ThisExpression", input: `this`}, {title: "SuperExpression", input: `super()`}, {title: "ImportExpression", input: `import()`}, {title: "PropertyAccess#1", input: `a.b`}, {title: "PropertyAccess#2", input: `a.#b`}, {title: "PropertyAccess#3", input: `a?.b`}, {title: "PropertyAccess#4", input: `a?.b.c`}, {title: "PropertyAccess#5", input: `1..b`}, {title: "PropertyAccess#6", input: `1.0.b`}, {title: "PropertyAccess#7", input: `0x1.b`}, {title: "PropertyAccess#8", input: `0b1.b`}, {title: "PropertyAccess#9", input: `0o1.b`}, {title: "PropertyAccess#10", input: `10e1.b`}, {title: "PropertyAccess#11", input: `10E1.b`}, {title: "ElementAccess#1", input: `a[b]`}, {title: "ElementAccess#2", input: `a?.[b]`}, {title: "ElementAccess#3", input: `a?.[b].c`}, {title: "CallExpression#1", input: `a()`}, {title: "CallExpression#2", input: `a()`}, {title: "CallExpression#3", input: `a(b)`}, {title: "CallExpression#4", input: `a(b)`}, {title: "CallExpression#5", input: `a(b).c`}, {title: "CallExpression#6", input: `a(b).c`}, {title: "CallExpression#7", input: `a?.(b)`}, {title: "CallExpression#8", input: `a?.(b)`}, {title: "CallExpression#9", input: `a?.(b).c`}, {title: "CallExpression#10", input: `a?.(b).c`}, {title: "CallExpression#11", input: `a()`}, {title: "CallExpression#12", input: `a()`}, {title: "NewExpression#1", input: `new a`}, {title: "NewExpression#2", input: `new a.b`}, {title: "NewExpression#3", input: `new a()`}, {title: "NewExpression#4", input: `new a.b()`}, {title: "NewExpression#5", input: `new a()`}, {title: "NewExpression#6", input: `new a.b()`}, {title: "NewExpression#7", input: `new a(b)`}, {title: "NewExpression#8", input: `new a.b(c)`}, {title: "NewExpression#9", input: `new a(b)`}, {title: "NewExpression#10", input: `new a.b(c)`}, {title: "NewExpression#11", input: `new a(b).c`}, {title: "NewExpression#12", input: `new a(b).c`}, {title: "TaggedTemplateExpression#1", input: "tag``"}, {title: "TaggedTemplateExpression#2", input: "tag``"}, {title: "TypeAssertionExpression#1", input: `a`}, {title: "FunctionExpression#1", input: `(function(){})`}, {title: "FunctionExpression#2", input: `(function f(){})`}, {title: "FunctionExpression#3", input: `(function*f(){})`}, {title: "FunctionExpression#4", input: `(async function f(){})`}, {title: "FunctionExpression#5", input: `(async function*f(){})`}, {title: "FunctionExpression#6", input: `(function(){})`}, {title: "FunctionExpression#7", input: `(function(a){})`}, {title: "FunctionExpression#8", input: `(function():T{})`}, {title: "ArrowFunction#1", input: `a=>{}`}, {title: "ArrowFunction#2", input: `()=>{}`}, {title: "ArrowFunction#3", input: `(a)=>{}`}, {title: "ArrowFunction#4", input: `(a)=>{}`}, {title: "ArrowFunction#5", input: `async a=>{}`}, {title: "ArrowFunction#6", input: `async()=>{}`}, {title: "ArrowFunction#7", input: `async()=>{}`}, {title: "ArrowFunction#8", input: `():T=>{}`}, {title: "ArrowFunction#9", input: `()=>a`}, {title: "DeleteExpression", input: `delete a`}, {title: "TypeOfExpression", input: `typeof a`}, {title: "VoidExpression", input: `void a`}, {title: "AwaitExpression", input: `await a`}, {title: "PrefixUnaryExpression#1", input: `+a`}, {title: "PrefixUnaryExpression#2", input: `++a`}, {title: "PrefixUnaryExpression#3", input: `+ +a`}, {title: "PrefixUnaryExpression#4", input: `+ ++a`}, {title: "PrefixUnaryExpression#5", input: `-a`}, {title: "PrefixUnaryExpression#6", input: `--a`}, {title: "PrefixUnaryExpression#7", input: `- -a`}, {title: "PrefixUnaryExpression#8", input: `- --a`}, {title: "PrefixUnaryExpression#9", input: `+-a`}, {title: "PrefixUnaryExpression#10", input: `+--a`}, {title: "PrefixUnaryExpression#11", input: `-+a`}, {title: "PrefixUnaryExpression#12", input: `-++a`}, {title: "PrefixUnaryExpression#13", input: `~a`}, {title: "PrefixUnaryExpression#14", input: `!a`}, {title: "PostfixUnaryExpression#1", input: `a++`}, {title: "PostfixUnaryExpression#2", input: `a--`}, {title: "BinaryExpression#1", input: `a,b`}, {title: "BinaryExpression#2", input: `a+b`}, {title: "BinaryExpression#3", input: `a**b`}, {title: "BinaryExpression#4", input: `a instanceof b`}, {title: "BinaryExpression#5", input: `a in b`}, {title: "ConditionalExpression", input: `a?b:c`}, {title: "TemplateExpression#1", input: "`a${b}c`"}, {title: "TemplateExpression#2", input: "`a${b}c${d}e`"}, {title: "YieldExpression#1", input: `(function*() { yield })`}, {title: "YieldExpression#2", input: `(function*() { yield a })`}, {title: "YieldExpression#3", input: `(function*() { yield*a })`}, {title: "SpreadElement", input: `[...a]`}, {title: "ClassExpression#1", input: `(class {})`}, {title: "ClassExpression#2", input: `(class a {})`}, {title: "ClassExpression#3", input: `(class{})`}, {title: "ClassExpression#4", input: `(class a{})`}, {title: "ClassExpression#5", input: `(class extends b {})`}, {title: "ClassExpression#6", input: `(class a extends b {})`}, {title: "ClassExpression#7", input: `(class implements b {})`}, {title: "ClassExpression#8", input: `(class a implements b {})`}, {title: "ClassExpression#9", input: `(class implements b, c {})`}, {title: "ClassExpression#10", input: `(class a implements b, c {})`}, {title: "ClassExpression#11", input: `(class extends b implements c, d {})`}, {title: "ClassExpression#12", input: `(class a extends b implements c, d {})`}, {title: "ClassExpression#13", input: `(@a class {})`}, {title: "OmittedExpression", input: `[,]`}, {title: "ExpressionWithTypeArguments", input: `a`}, {title: "AsExpression", input: `a as T`}, {title: "SatisfiesExpression", input: `a satisfies T`}, {title: "NonNullExpression", input: `a!`}, {title: "MetaProperty#1", input: `new.target`}, {title: "MetaProperty#2", input: `import.meta`}, {title: "ArrayLiteralExpression#1", input: `[]`}, {title: "ArrayLiteralExpression#2", input: `[a]`}, {title: "ArrayLiteralExpression#3", input: `[a,]`}, {title: "ArrayLiteralExpression#4", input: `[,a]`}, {title: "ArrayLiteralExpression#5", input: `[...a]`}, {title: "ObjectLiteralExpression#1", input: `({})`}, {title: "ObjectLiteralExpression#2", input: `({a,})`}, {title: "ShorthandPropertyAssignment", input: `({a})`}, {title: "PropertyAssignment", input: `({a:b})`}, {title: "SpreadAssignment", input: `({...a})`}, {title: "Block", input: `{}`}, {title: "VariableStatement#1", input: `var a`}, {title: "VariableStatement#2", input: `let a`}, {title: "VariableStatement#3", input: `const a = b`}, {title: "VariableStatement#4", input: `using a = b`}, {title: "VariableStatement#5", input: `await using a = b`}, {title: "EmptyStatement", input: `;`}, {title: "IfStatement#1", input: `if(a);`}, {title: "IfStatement#2", input: `if(a);else;`}, {title: "IfStatement#3", input: `if(a);else{}`}, {title: "IfStatement#4", input: `if(a);else if(b);`}, {title: "IfStatement#5", input: `if(a);else if(b) {}`}, {title: "IfStatement#6", input: `if(a) {}`}, {title: "IfStatement#7", input: `if(a) {} else;`}, {title: "IfStatement#8", input: `if(a) {} else {}`}, {title: "IfStatement#9", input: `if(a) {} else if(b);`}, {title: "IfStatement#10", input: `if(a) {} else if(b){}`}, {title: "DoStatement#1", input: `do;while(a);`}, {title: "DoStatement#2", input: `do {} while(a);`}, {title: "WhileStatement#1", input: `while(a);`}, {title: "WhileStatement#2", input: `while(a) {}`}, {title: "ForStatement#1", input: `for(;;);`}, {title: "ForStatement#2", input: `for(a;;);`}, {title: "ForStatement#3", input: `for(var a;;);`}, {title: "ForStatement#4", input: `for(;a;);`}, {title: "ForStatement#5", input: `for(;;a);`}, {title: "ForStatement#6", input: `for(;;){}`}, {title: "ForInStatement#1", input: `for(a in b);`}, {title: "ForInStatement#2", input: `for(var a in b);`}, {title: "ForInStatement#3", input: `for(a in b){}`}, {title: "ForOfStatement#1", input: `for(a of b);`}, {title: "ForOfStatement#2", input: `for(var a of b);`}, {title: "ForOfStatement#3", input: `for(a of b){}`}, {title: "ForOfStatement#4", input: `for await(a of b);`}, {title: "ForOfStatement#5", input: `for await(var a of b);`}, {title: "ForOfStatement#6", input: `for await(a of b){}`}, {title: "ContinueStatement#1", input: `continue`}, {title: "ContinueStatement#2", input: `continue a`}, {title: "BreakStatement#1", input: `break`}, {title: "BreakStatement#2", input: `break a`}, {title: "ReturnStatement#1", input: `return`}, {title: "ReturnStatement#2", input: `return a`}, {title: "WithStatement#1", input: `with(a);`}, {title: "WithStatement#2", input: `with(a){}`}, {title: "SwitchStatement", input: `switch (a) {}`}, {title: "CaseClause#1", input: `switch (a) {case b:}`}, {title: "CaseClause#2", input: `switch (a) {case b:;}`}, {title: "DefaultClause#1", input: `switch (a) {default:}`}, {title: "DefaultClause#2", input: `switch (a) {default:;}`}, {title: "LabeledStatement", input: `a:;`}, {title: "ThrowStatement", input: `throw a`}, {title: "TryStatement#1", input: `try {} catch {}`}, {title: "TryStatement#2", input: `try {} finally {}`}, {title: "TryStatement#3", input: `try {} catch {} finally {}`}, {title: "DebuggerStatement", input: `debugger`}, {title: "FunctionDeclaration#1", input: `export default function(){}`}, {title: "FunctionDeclaration#2", input: `function f(){}`}, {title: "FunctionDeclaration#3", input: `function*f(){}`}, {title: "FunctionDeclaration#4", input: `async function f(){}`}, {title: "FunctionDeclaration#5", input: `async function*f(){}`}, {title: "FunctionDeclaration#6", input: `function f(){}`}, {title: "FunctionDeclaration#7", input: `function f(a){}`}, {title: "FunctionDeclaration#8", input: `function f():T{}`}, {title: "FunctionDeclaration#9", input: `function f();`}, {title: "ClassDeclaration#1", input: `class a {}`}, {title: "ClassDeclaration#2", input: `class a{}`}, {title: "ClassDeclaration#3", input: `class a extends b {}`}, {title: "ClassDeclaration#4", input: `class a implements b {}`}, {title: "ClassDeclaration#5", input: `class a implements b, c {}`}, {title: "ClassDeclaration#6", input: `class a extends b implements c, d {}`}, {title: "ClassDeclaration#7", input: `export default class {}`}, {title: "ClassDeclaration#8", input: `export default class{}`}, {title: "ClassDeclaration#9", input: `export default class extends b {}`}, {title: "ClassDeclaration#10", input: `export default class implements b {}`}, {title: "ClassDeclaration#11", input: `export default class implements b, c {}`}, {title: "ClassDeclaration#12", input: `export default class extends b implements c, d {}`}, {title: "ClassDeclaration#13", input: `@a class b {}`}, {title: "ClassDeclaration#14", input: `@a export class b {}`}, {title: "ClassDeclaration#15", input: `export @a class b {}`}, {title: "InterfaceDeclaration#1", input: `interface a {}`}, {title: "InterfaceDeclaration#2", input: `interface a{}`}, {title: "InterfaceDeclaration#3", input: `interface a extends b {}`}, {title: "InterfaceDeclaration#4", input: `interface a extends b, c {}`}, {title: "TypeAliasDeclaration#1", input: `type a = b`}, {title: "TypeAliasDeclaration#2", input: `type a = b`}, {title: "EnumDeclaration#1", input: `enum a{}`}, {title: "EnumDeclaration#2", input: `enum a{b}`}, {title: "EnumDeclaration#3", input: `enum a{b=c}`}, {title: "ModuleDeclaration#1", input: `module a{}`}, {title: "ModuleDeclaration#2", input: `module a.b{}`}, {title: "ModuleDeclaration#3", input: `module "a";`}, {title: "ModuleDeclaration#4", input: `module "a"{}`}, {title: "ModuleDeclaration#5", input: `namespace a{}`}, {title: "ModuleDeclaration#6", input: `namespace a.b{}`}, {title: "ModuleDeclaration#7", input: `global;`}, {title: "ModuleDeclaration#8", input: `global{}`}, {title: "ImportEqualsDeclaration#1", input: `import a = b`}, {title: "ImportEqualsDeclaration#2", input: `import a = b.c`}, {title: "ImportEqualsDeclaration#3", input: `import a = require("b")`}, {title: "ImportEqualsDeclaration#4", input: `export import a = b`}, {title: "ImportEqualsDeclaration#5", input: `export import a = require("b")`}, {title: "ImportEqualsDeclaration#6", input: `import type a = b`}, {title: "ImportEqualsDeclaration#7", input: `import type a = b.c`}, {title: "ImportEqualsDeclaration#8", input: `import type a = require("b")`}, {title: "ImportDeclaration#1", input: `import "a"`}, {title: "ImportDeclaration#2", input: `import a from "b"`}, {title: "ImportDeclaration#3", input: `import type a from "b"`}, {title: "ImportDeclaration#4", input: `import * as a from "b"`}, {title: "ImportDeclaration#5", input: `import type * as a from "b"`}, {title: "ImportDeclaration#6", input: `import {} from "b"`}, {title: "ImportDeclaration#7", input: `import type {} from "b"`}, {title: "ImportDeclaration#8", input: `import { a } from "b"`}, {title: "ImportDeclaration#9", input: `import type { a } from "b"`}, {title: "ImportDeclaration#8", input: `import { a as b } from "c"`}, {title: "ImportDeclaration#9", input: `import type { a as b } from "c"`}, {title: "ImportDeclaration#10", input: `import { "a" as b } from "c"`}, {title: "ImportDeclaration#11", input: `import type { "a" as b } from "c"`}, {title: "ImportDeclaration#12", input: `import a, {} from "b"`}, {title: "ImportDeclaration#13", input: `import a, * as b from "c"`}, {title: "ImportDeclaration#14", input: `import {} from "a" with {}`}, {title: "ImportDeclaration#15", input: `import {} from "a" with { b: "c" }`}, {title: "ImportDeclaration#16", input: `import {} from "a" with { "b": "c" }`}, {title: "ExportAssignment#1", input: `export = a`}, {title: "ExportAssignment#2", input: `export default a`}, {title: "NamespaceExportDeclaration", input: `export as namespace a`}, {title: "ExportDeclaration#1", input: `export * from "a"`}, {title: "ExportDeclaration#2", input: `export type * from "a"`}, {title: "ExportDeclaration#3", input: `export * as a from "b"`}, {title: "ExportDeclaration#4", input: `export type * as a from "b"`}, {title: "ExportDeclaration#5", input: `export { } from "a"`}, {title: "ExportDeclaration#6", input: `export type { } from "a"`}, {title: "ExportDeclaration#7", input: `export { a } from "b"`}, {title: "ExportDeclaration#8", input: `export { type a } from "b"`}, {title: "ExportDeclaration#9", input: `export type { a } from "b"`}, {title: "ExportDeclaration#10", input: `export { a as b } from "c"`}, {title: "ExportDeclaration#11", input: `export { type a as b } from "c"`}, {title: "ExportDeclaration#12", input: `export type { a as b } from "c"`}, {title: "ExportDeclaration#13", input: `export { a as "b" } from "c"`}, {title: "ExportDeclaration#14", input: `export { type a as "b" } from "c"`}, {title: "ExportDeclaration#15", input: `export type { a as "b" } from "c"`}, {title: "ExportDeclaration#16", input: `export { "a" } from "b"`}, {title: "ExportDeclaration#17", input: `export { type "a" } from "b"`}, {title: "ExportDeclaration#18", input: `export type { "a" } from "b"`}, {title: "ExportDeclaration#19", input: `export { "a" as b } from "c"`}, {title: "ExportDeclaration#20", input: `export { type "a" as b } from "c"`}, {title: "ExportDeclaration#21", input: `export type { "a" as b } from "c"`}, {title: "ExportDeclaration#22", input: `export { "a" as "b" } from "c"`}, {title: "ExportDeclaration#23", input: `export { type "a" as "b" } from "c"`}, {title: "ExportDeclaration#24", input: `export type { "a" as "b" } from "c"`}, {title: "ExportDeclaration#25", input: `export { }`}, {title: "ExportDeclaration#26", input: `export type { }`}, {title: "ExportDeclaration#27", input: `export { a }`}, {title: "ExportDeclaration#28", input: `export { type a }`}, {title: "ExportDeclaration#29", input: `export type { a }`}, {title: "ExportDeclaration#30", input: `export { a as b }`}, {title: "ExportDeclaration#31", input: `export { type a as b }`}, {title: "ExportDeclaration#32", input: `export type { a as b }`}, {title: "ExportDeclaration#33", input: `export { a as "b" }`}, {title: "ExportDeclaration#34", input: `export { type a as "b" }`}, {title: "ExportDeclaration#35", input: `export type { a as "b" }`}, {title: "ExportDeclaration#36", input: `export {} from "a" with {}`}, {title: "ExportDeclaration#37", input: `export {} from "a" with { b: "c" }`}, {title: "ExportDeclaration#38", input: `export {} from "a" with { "b": "c" }`}, {title: "KeywordTypeNode#1", input: `type T = any`}, {title: "KeywordTypeNode#2", input: `type T = unknown`}, {title: "KeywordTypeNode#3", input: `type T = never`}, {title: "KeywordTypeNode#4", input: `type T = void`}, {title: "KeywordTypeNode#5", input: `type T = undefined`}, {title: "KeywordTypeNode#6", input: `type T = null`}, {title: "KeywordTypeNode#7", input: `type T = object`}, {title: "KeywordTypeNode#8", input: `type T = string`}, {title: "KeywordTypeNode#9", input: `type T = symbol`}, {title: "KeywordTypeNode#10", input: `type T = number`}, {title: "KeywordTypeNode#11", input: `type T = bigint`}, {title: "KeywordTypeNode#12", input: `type T = boolean`}, {title: "KeywordTypeNode#13", input: `type T = intrinsic`}, {title: "TypePredicateNode#1", input: `function f(): asserts a`}, {title: "TypePredicateNode#2", input: `function f(): asserts a is b`}, {title: "TypePredicateNode#3", input: `function f(): asserts this`}, {title: "TypePredicateNode#4", input: `function f(): asserts this is b`}, {title: "TypeReferenceNode#1", input: `type T = a`}, {title: "TypeReferenceNode#2", input: `type T = a.b`}, {title: "TypeReferenceNode#3", input: `type T = a`}, {title: "TypeReferenceNode#4", input: `type T = a.b`}, {title: "FunctionTypeNode#1", input: `type T = () => a`}, {title: "FunctionTypeNode#2", input: `type T = () => a`}, {title: "FunctionTypeNode#3", input: `type T = (a) => b`}, {title: "ConstructorTypeNode#1", input: `type T = new () => a`}, {title: "ConstructorTypeNode#2", input: `type T = new () => a`}, {title: "ConstructorTypeNode#3", input: `type T = new (a) => b`}, {title: "ConstructorTypeNode#4", input: `type T = abstract new () => a`}, {title: "TypeQueryNode#1", input: `type T = typeof a`}, {title: "TypeQueryNode#2", input: `type T = typeof a.b`}, {title: "TypeQueryNode#3", input: `type T = typeof a`}, {title: "TypeLiteralNode#1", input: `type T = {}`}, {title: "TypeLiteralNode#2", input: `type T = {a}`}, {title: "ArrayTypeNode", input: `type T = a[]`}, {title: "TupleTypeNode#1", input: `type T = []`}, {title: "TupleTypeNode#2", input: `type T = [a]`}, {title: "TupleTypeNode#3", input: `type T = [a,]`}, {title: "RestTypeNode", input: `type T = [...a]`}, {title: "OptionalTypeNode", input: `type T = [a?]`}, {title: "NamedTupleMember#1", input: `type T = [a: b]`}, {title: "NamedTupleMember#2", input: `type T = [a?: b]`}, {title: "NamedTupleMember#3", input: `type T = [...a: b]`}, {title: "UnionTypeNode#1", input: `type T = a | b`}, {title: "UnionTypeNode#2", input: `type T = a | b | c`}, {title: "UnionTypeNode#3", input: `type T = | a | b`}, {title: "IntersectionTypeNode#1", input: `type T = a & b`}, {title: "IntersectionTypeNode#2", input: `type T = a & b & c`}, {title: "IntersectionTypeNode#3", input: `type T = & a & b`}, {title: "ConditionalTypeNode", input: `type T = a extends b ? c : d`}, {title: "InferTypeNode#1", input: `type T = a extends infer b ? c : d`}, {title: "InferTypeNode#2", input: `type T = a extends infer b extends c ? d : e`}, {title: "ParenthesizedTypeNode", input: `type T = (U)`}, {title: "ThisTypeNode", input: `type T = this`}, {title: "TypeOperatorNode#1", input: `type T = keyof U`}, {title: "TypeOperatorNode#2", input: `type T = readonly U[]`}, {title: "TypeOperatorNode#3", input: `type T = unique symbol`}, {title: "IndexedAccessTypeNode", input: `type T = a[b]`}, {title: "MappedTypeNode#1", input: `type T = { [a in b]: c }`}, {title: "MappedTypeNode#2", input: `type T = { [a in b as c]: d }`}, {title: "MappedTypeNode#3", input: `type T = { readonly [a in b]: c }`}, {title: "MappedTypeNode#4", input: `type T = { +readonly [a in b]: c }`}, {title: "MappedTypeNode#5", input: `type T = { -readonly [a in b]: c }`}, {title: "MappedTypeNode#6", input: `type T = { [a in b]?: c }`}, {title: "MappedTypeNode#7", input: `type T = { [a in b]+?: c }`}, {title: "MappedTypeNode#8", input: `type T = { [a in b]-?: c }`}, {title: "MappedTypeNode#9", input: `type T = { [a in b]: c; d }`}, {title: "LiteralTypeNode#1", input: `type T = null`}, {title: "LiteralTypeNode#2", input: `type T = true`}, {title: "LiteralTypeNode#3", input: `type T = false`}, {title: "LiteralTypeNode#4", input: `type T = ""`}, {title: "LiteralTypeNode#5", input: "type T = ''"}, {title: "LiteralTypeNode#6", input: "type T = ``"}, {title: "LiteralTypeNode#7", input: `type T = 0`}, {title: "LiteralTypeNode#8", input: `type T = 0n`}, {title: "LiteralTypeNode#9", input: `type T = -0`}, {title: "LiteralTypeNode#10", input: `type T = -0n`}, {title: "TemplateTypeNode#1", input: "type T = `a${b}c`"}, {title: "TemplateTypeNode#2", input: "type T = `a${b}c${d}e`"}, {title: "ImportTypeNode#1", input: `type T = import(a)`}, {title: "ImportTypeNode#2", input: `type T = import(a).b`}, {title: "ImportTypeNode#3", input: `type T = import(a).b`}, {title: "ImportTypeNode#4", input: `type T = typeof import(a)`}, {title: "ImportTypeNode#5", input: `type T = typeof import(a).b`}, {title: "ImportTypeNode#6", input: `type T = import(a, { with: { } })`}, {title: "ImportTypeNode#6", input: `type T = import(a, { with: { b: "c" } })`}, {title: "ImportTypeNode#7", input: `type T = import(a, { with: { "b": "c" } })`}, {title: "PropertySignature#1", input: "interface I {a}"}, {title: "PropertySignature#2", input: "interface I {readonly a}"}, {title: "PropertySignature#3", input: "interface I {\"a\"}"}, {title: "PropertySignature#4", input: "interface I {'a'}"}, {title: "PropertySignature#5", input: "interface I {0}"}, {title: "PropertySignature#6", input: "interface I {0n}"}, {title: "PropertySignature#7", input: "interface I {[a]}"}, {title: "PropertySignature#8", input: "interface I {a?}"}, {title: "PropertySignature#9", input: "interface I {a: b}"}, {title: "MethodSignature#1", input: "interface I {a()}"}, {title: "MethodSignature#2", input: "interface I {\"a\"()}"}, {title: "MethodSignature#3", input: "interface I {'a'()}"}, {title: "MethodSignature#4", input: "interface I {0()}"}, {title: "MethodSignature#5", input: "interface I {0n()}"}, {title: "MethodSignature#6", input: "interface I {[a]()}"}, {title: "MethodSignature#7", input: "interface I {a?()}"}, {title: "MethodSignature#8", input: "interface I {a()}"}, {title: "MethodSignature#9", input: "interface I {a(): b}"}, {title: "MethodSignature#10", input: "interface I {a(b): c}"}, {title: "CallSignature#1", input: "interface I {()}"}, {title: "CallSignature#2", input: "interface I {():a}"}, {title: "CallSignature#3", input: "interface I {(p)}"}, {title: "CallSignature#4", input: "interface I {()}"}, {title: "ConstructSignature#1", input: "interface I {new ()}"}, {title: "ConstructSignature#2", input: "interface I {new ():a}"}, {title: "ConstructSignature#3", input: "interface I {new (p)}"}, {title: "ConstructSignature#4", input: "interface I {new ()}"}, {title: "IndexSignatureDeclaration#1", input: "interface I {[a]}"}, {title: "IndexSignatureDeclaration#2", input: "interface I {[a: b]}"}, {title: "IndexSignatureDeclaration#3", input: "interface I {[a: b]: c}"}, {title: "PropertyDeclaration#1", input: "class C {a}"}, {title: "PropertyDeclaration#2", input: "class C {readonly a}"}, {title: "PropertyDeclaration#3", input: "class C {static a}"}, {title: "PropertyDeclaration#4", input: "class C {accessor a}"}, {title: "PropertyDeclaration#5", input: "class C {\"a\"}"}, {title: "PropertyDeclaration#6", input: "class C {'a'}"}, {title: "PropertyDeclaration#7", input: "class C {0}"}, {title: "PropertyDeclaration#8", input: "class C {0n}"}, {title: "PropertyDeclaration#9", input: "class C {[a]}"}, {title: "PropertyDeclaration#10", input: "class C {#a}"}, {title: "PropertyDeclaration#11", input: "class C {a?}"}, {title: "PropertyDeclaration#12", input: "class C {a!}"}, {title: "PropertyDeclaration#13", input: "class C {a: b}"}, {title: "PropertyDeclaration#14", input: "class C {a = b}"}, {title: "PropertyDeclaration#15", input: "class C {@a b}"}, {title: "MethodDeclaration#1", input: "class C {a()}"}, {title: "MethodDeclaration#2", input: "class C {\"a\"()}"}, {title: "MethodDeclaration#3", input: "class C {'a'()}"}, {title: "MethodDeclaration#4", input: "class C {0()}"}, {title: "MethodDeclaration#5", input: "class C {0n()}"}, {title: "MethodDeclaration#6", input: "class C {[a]()}"}, {title: "MethodDeclaration#7", input: "class C {#a()}"}, {title: "MethodDeclaration#8", input: "class C {a?()}"}, {title: "MethodDeclaration#9", input: "class C {a()}"}, {title: "MethodDeclaration#10", input: "class C {a(): b}"}, {title: "MethodDeclaration#11", input: "class C {a(b): c}"}, {title: "MethodDeclaration#12", input: "class C {a() {} }"}, {title: "MethodDeclaration#13", input: "class C {@a b() {} }"}, {title: "MethodDeclaration#14", input: "class C {static a() {} }"}, {title: "MethodDeclaration#15", input: "class C {async a() {} }"}, {title: "GetAccessorDeclaration#1", input: "class C {get a()}"}, {title: "GetAccessorDeclaration#2", input: "class C {get \"a\"()}"}, {title: "GetAccessorDeclaration#3", input: "class C {get 'a'()}"}, {title: "GetAccessorDeclaration#4", input: "class C {get 0()}"}, {title: "GetAccessorDeclaration#5", input: "class C {get 0n()}"}, {title: "GetAccessorDeclaration#6", input: "class C {get [a]()}"}, {title: "GetAccessorDeclaration#7", input: "class C {get #a()}"}, {title: "GetAccessorDeclaration#8", input: "class C {get a(): b}"}, {title: "GetAccessorDeclaration#9", input: "class C {get a(b): c}"}, {title: "GetAccessorDeclaration#10", input: "class C {get a() {} }"}, {title: "GetAccessorDeclaration#11", input: "class C {@a get b() {} }"}, {title: "GetAccessorDeclaration#12", input: "class C {static get a() {} }"}, {title: "SetAccessorDeclaration#1", input: "class C {set a()}"}, {title: "SetAccessorDeclaration#2", input: "class C {set \"a\"()}"}, {title: "SetAccessorDeclaration#3", input: "class C {set 'a'()}"}, {title: "SetAccessorDeclaration#4", input: "class C {set 0()}"}, {title: "SetAccessorDeclaration#5", input: "class C {set 0n()}"}, {title: "SetAccessorDeclaration#6", input: "class C {set [a]()}"}, {title: "SetAccessorDeclaration#7", input: "class C {set #a()}"}, {title: "SetAccessorDeclaration#8", input: "class C {set a(): b}"}, {title: "SetAccessorDeclaration#9", input: "class C {set a(b): c}"}, {title: "SetAccessorDeclaration#10", input: "class C {set a() {} }"}, {title: "SetAccessorDeclaration#11", input: "class C {@a set b() {} }"}, {title: "SetAccessorDeclaration#12", input: "class C {static set a() {} }"}, {title: "ConstructorDeclaration#1", input: "class C {constructor()}"}, {title: "ConstructorDeclaration#2", input: "class C {constructor(): b}"}, {title: "ConstructorDeclaration#3", input: "class C {constructor(b): c}"}, {title: "ConstructorDeclaration#4", input: "class C {constructor() {} }"}, {title: "ConstructorDeclaration#5", input: "class C {@a constructor() {} }"}, {title: "ConstructorDeclaration#6", input: "class C {private constructor() {} }"}, {title: "ClassStaticBlockDeclaration", input: "class C {static { }}"}, {title: "SemicolonClassElement#1", input: "class C {;}"}, {title: "ParameterDeclaration#1", input: "function f(a)"}, {title: "ParameterDeclaration#2", input: "function f(a: b)"}, {title: "ParameterDeclaration#3", input: "function f(a = b)"}, {title: "ParameterDeclaration#4", input: "function f(a?)"}, {title: "ParameterDeclaration#5", input: "function f(...a)"}, {title: "ParameterDeclaration#6", input: "function f(this)"}, {title: "ParameterDeclaration#7", input: "function f(a,)"}, {title: "ObjectBindingPattern#1", input: "function f({})"}, {title: "ObjectBindingPattern#2", input: "function f({a})"}, {title: "ObjectBindingPattern#3", input: "function f({a = b})"}, {title: "ObjectBindingPattern#4", input: "function f({a: b})"}, {title: "ObjectBindingPattern#5", input: "function f({a: b = c})"}, {title: "ObjectBindingPattern#6", input: "function f({\"a\": b})"}, {title: "ObjectBindingPattern#7", input: "function f({'a': b})"}, {title: "ObjectBindingPattern#8", input: "function f({0: b})"}, {title: "ObjectBindingPattern#9", input: "function f({[a]: b})"}, {title: "ObjectBindingPattern#10", input: "function f({...a})"}, {title: "ObjectBindingPattern#11", input: "function f({a: {}})"}, {title: "ObjectBindingPattern#12", input: "function f({a: []})"}, {title: "ArrayBindingPattern#1", input: "function f([])"}, {title: "ArrayBindingPattern#2", input: "function f([,])"}, {title: "ArrayBindingPattern#3", input: "function f([a])"}, {title: "ArrayBindingPattern#4", input: "function f([a, b])"}, {title: "ArrayBindingPattern#5", input: "function f([a, , b])"}, {title: "ArrayBindingPattern#6", input: "function f([a = b])"}, {title: "ArrayBindingPattern#7", input: "function f([...a])"}, {title: "ArrayBindingPattern#8", input: "function f([{}])"}, {title: "ArrayBindingPattern#9", input: "function f([[]])"}, {title: "TypeParameterDeclaration#1", input: "function f();"}, {title: "TypeParameterDeclaration#2", input: "function f();"}, {title: "TypeParameterDeclaration#3", input: "function f();"}, {title: "TypeParameterDeclaration#4", input: "function f();"}, {title: "TypeParameterDeclaration#5", input: "function f();"}, {title: "TypeParameterDeclaration#6", input: "function f();"}, {title: "TypeParameterDeclaration#7", input: "function f();"}, {title: "JsxElement1", input: ""}, {title: "JsxElement2", input: ""}, {title: "JsxElement3", input: ""}, {title: "JsxElement4", input: ""}, {title: "JsxElement5", input: ">"}, {title: "JsxElement6", input: ""}, {title: "JsxElement7", input: "b"}, {title: "JsxElement8", input: "{b}"}, {title: "JsxElement9", input: ""}, {title: "JsxElement10", input: ""}, {title: "JsxElement11", input: "<>"}, {title: "JsxSelfClosingElement1", input: ""}, {title: "JsxSelfClosingElement2", input: ""}, {title: "JsxSelfClosingElement3", input: ""}, {title: "JsxSelfClosingElement4", input: ""}, {title: "JsxSelfClosingElement5", input: " />"}, {title: "JsxSelfClosingElement6", input: ""}, {title: "JsxFragment1", input: "<>"}, {title: "JsxFragment2", input: "<>b"}, {title: "JsxFragment3", input: "<>{b}"}, {title: "JsxFragment4", input: "<>"}, {title: "JsxFragment5", input: "<>"}, {title: "JsxFragment6", input: "<><>"}, {title: "JsxAttribute1", input: ""}, {title: "JsxAttribute2", input: ""}, {title: "JsxAttribute3", input: ""}, {title: "JsxAttribute4", input: ""}, {title: "JsxAttribute5", input: ""}, {title: "JsxAttribute6", input: "/>"}, {title: "JsxAttribute7", input: "/>"}, {title: "JsxAttribute8", input: "/>"}, {title: "JsxSpreadAttribute", input: ""}, } for _, rec := range data { t.Run("Clone "+rec.title, func(t *testing.T) { t.Parallel() factory := &ast.NodeFactory{} file := parsetestutil.ParseTypeScript(rec.input, false).AsNode() clone := factory.DeepCloneNode(file.AsNode()).AsNode() work := []NodeComparisonWorkItem{{file, clone}} for len(work) > 0 { nextWork := []NodeComparisonWorkItem{} for _, item := range work { assert.Assert(t, item.original != item.copy) originalChildren := getChildren(item.original) copyChildren := getChildren(item.copy) assert.Equal(t, len(originalChildren), len(copyChildren)) for i, child := range originalChildren { nextWork = append(nextWork, NodeComparisonWorkItem{child, copyChildren[i]}) } } work = nextWork } }) } }