kittenipc/kitcom/internal/tsgo/ast/deepclone_test.go
2025-10-15 10:12:44 +03:00

600 lines
33 KiB
Go

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<T>()`},
{title: "CallExpression#3", input: `a(b)`},
{title: "CallExpression#4", input: `a<T>(b)`},
{title: "CallExpression#5", input: `a(b).c`},
{title: "CallExpression#6", input: `a<T>(b).c`},
{title: "CallExpression#7", input: `a?.(b)`},
{title: "CallExpression#8", input: `a?.<T>(b)`},
{title: "CallExpression#9", input: `a?.(b).c`},
{title: "CallExpression#10", input: `a?.<T>(b).c`},
{title: "CallExpression#11", input: `a<T, U>()`},
{title: "CallExpression#12", input: `a<T,>()`},
{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<T>()`},
{title: "NewExpression#6", input: `new a.b<T>()`},
{title: "NewExpression#7", input: `new a(b)`},
{title: "NewExpression#8", input: `new a.b(c)`},
{title: "NewExpression#9", input: `new a<T>(b)`},
{title: "NewExpression#10", input: `new a.b<T>(c)`},
{title: "NewExpression#11", input: `new a(b).c`},
{title: "NewExpression#12", input: `new a<T>(b).c`},
{title: "TaggedTemplateExpression#1", input: "tag``"},
{title: "TaggedTemplateExpression#2", input: "tag<T>``"},
{title: "TypeAssertionExpression#1", input: `<T>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<T>(){})`},
{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: `<T>(a)=>{}`},
{title: "ArrowFunction#5", input: `async a=>{}`},
{title: "ArrowFunction#6", input: `async()=>{}`},
{title: "ArrowFunction#7", input: `async<T>()=>{}`},
{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<T>{})`},
{title: "ClassExpression#4", input: `(class a<T>{})`},
{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<T>`},
{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<T>(){}`},
{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<T>{}`},
{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<T>{}`},
{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<T>{}`},
{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<T> = 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<U>`},
{title: "TypeReferenceNode#4", input: `type T = a.b<U>`},
{title: "FunctionTypeNode#1", input: `type T = () => a`},
{title: "FunctionTypeNode#2", input: `type T = <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 <T>() => 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<U>`},
{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<U>`},
{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<T>()}"},
{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 {<T>()}"},
{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 <T>()}"},
{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<T>()}"},
{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<T>();"},
{title: "TypeParameterDeclaration#2", input: "function f<in T>();"},
{title: "TypeParameterDeclaration#3", input: "function f<T extends U>();"},
{title: "TypeParameterDeclaration#4", input: "function f<T = U>();"},
{title: "TypeParameterDeclaration#5", input: "function f<T extends U = V>();"},
{title: "TypeParameterDeclaration#6", input: "function f<T, U>();"},
{title: "TypeParameterDeclaration#7", input: "function f<T,>();"},
{title: "JsxElement1", input: "<a></a>"},
{title: "JsxElement2", input: "<this></this>"},
{title: "JsxElement3", input: "<a:b></a:b>"},
{title: "JsxElement4", input: "<a.b></a.b>"},
{title: "JsxElement5", input: "<a<b>></a>"},
{title: "JsxElement6", input: "<a b></a>"},
{title: "JsxElement7", input: "<a>b</a>"},
{title: "JsxElement8", input: "<a>{b}</a>"},
{title: "JsxElement9", input: "<a><b></b></a>"},
{title: "JsxElement10", input: "<a><b /></a>"},
{title: "JsxElement11", input: "<a><></></a>"},
{title: "JsxSelfClosingElement1", input: "<a />"},
{title: "JsxSelfClosingElement2", input: "<this />"},
{title: "JsxSelfClosingElement3", input: "<a:b />"},
{title: "JsxSelfClosingElement4", input: "<a.b />"},
{title: "JsxSelfClosingElement5", input: "<a<b> />"},
{title: "JsxSelfClosingElement6", input: "<a b/>"},
{title: "JsxFragment1", input: "<></>"},
{title: "JsxFragment2", input: "<>b</>"},
{title: "JsxFragment3", input: "<>{b}</>"},
{title: "JsxFragment4", input: "<><b></b></>"},
{title: "JsxFragment5", input: "<><b /></>"},
{title: "JsxFragment6", input: "<><></></>"},
{title: "JsxAttribute1", input: "<a b/>"},
{title: "JsxAttribute2", input: "<a b:c/>"},
{title: "JsxAttribute3", input: "<a b=\"c\"/>"},
{title: "JsxAttribute4", input: "<a b='c'/>"},
{title: "JsxAttribute5", input: "<a b={c}/>"},
{title: "JsxAttribute6", input: "<a b=<c></c>/>"},
{title: "JsxAttribute7", input: "<a b=<c />/>"},
{title: "JsxAttribute8", input: "<a b=<></>/>"},
{title: "JsxSpreadAttribute", input: "<a {...b}/>"},
}
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
}
})
}
}