1 package javascript 2 3 import ( 4 "fmt" 5 "reflect" 6 "testing" 7 ) 8 9 const disabled = true 10 11 var allTypes = []interface{}{ 12 AdditiveExpression{}, 13 Argument{}, 14 Arguments{}, 15 ArrayAssignmentPattern{}, 16 ArrayBindingPattern{}, 17 ArrayElement{}, 18 ArrayLiteral{}, 19 ArrowFunction{}, 20 AssignmentElement{}, 21 AssignmentExpression{}, 22 AssignmentPattern{}, 23 AssignmentProperty{}, 24 BindingElement{}, 25 BindingProperty{}, 26 BitwiseANDExpression{}, 27 BitwiseORExpression{}, 28 BitwiseXORExpression{}, 29 Block{}, 30 CallExpression{}, 31 CaseClause{}, 32 ClassDeclaration{}, 33 ClassElement{}, 34 ClassElementName{}, 35 CoalesceExpression{}, 36 ConditionalExpression{}, 37 ParenthesizedExpression{}, 38 Declaration{}, 39 DestructuringAssignmentTarget{}, 40 EqualityExpression{}, 41 ExponentiationExpression{}, 42 ExportClause{}, 43 ExportDeclaration{}, 44 ExportSpecifier{}, 45 Expression{}, 46 FieldDefinition{}, 47 FormalParameters{}, 48 FromClause{}, 49 FunctionDeclaration{}, 50 IfStatement{}, 51 ImportClause{}, 52 ImportDeclaration{}, 53 ImportSpecifier{}, 54 IterationStatementDo{}, 55 IterationStatementFor{}, 56 IterationStatementWhile{}, 57 LeftHandSideExpression{}, 58 LexicalBinding{}, 59 LexicalDeclaration{}, 60 LogicalANDExpression{}, 61 LogicalORExpression{}, 62 MemberExpression{}, 63 MethodDefinition{}, 64 Module{}, 65 ModuleItem{}, 66 MultiplicativeExpression{}, 67 NamedImports{}, 68 NewExpression{}, 69 ObjectAssignmentPattern{}, 70 ObjectBindingPattern{}, 71 ObjectLiteral{}, 72 OptionalChain{}, 73 OptionalExpression{}, 74 PrimaryExpression{}, 75 PropertyDefinition{}, 76 PropertyName{}, 77 RelationalExpression{}, 78 Script{}, 79 ShiftExpression{}, 80 Statement{}, 81 StatementListItem{}, 82 SwitchStatement{}, 83 TemplateLiteral{}, 84 TryStatement{}, 85 UnaryExpression{}, 86 UpdateExpression{}, 87 VariableStatement{}, 88 WithStatement{}, 89 } 90 91 func TestTypeFormatting(*testing.T) { 92 if disabled { 93 return 94 } 95 for _, typ := range allTypes { 96 t := reflect.TypeOf(typ) 97 fmt.Printf("\n\n// Format implements the fmt.Formatter interface\nfunc (f %[1]s) Format(s fmt.State, v rune) {\n if v == 'v' && s.Flag('#') {\n type X = %[1]s\n type %[1]s X\n fmt.Fprintf(s, \"%%#v\", %[1]s(f))\n } else {\n format(&f, s, v)\n }\n}", t.Name()) 98 } 99 } 100 101 func TestTypePrinting(*testing.T) { 102 if disabled { 103 return 104 } 105 stringer := reflect.TypeOf(struct{ S fmt.Stringer }{}).Field(0).Type 106 fmt.Printf("package javascript\n\nimport \"io\"\n\nvar (") 107 done := make(map[string]struct{}) 108 for _, typ := range allTypes { 109 t := reflect.TypeOf(typ) 110 name := t.Name() 111 if _, ok := done[name]; !ok { 112 fmt.Printf("\n name%s = %v", name, toSlice(name)) 113 done[name] = struct{}{} 114 } 115 for i := 0; i < t.NumField(); i++ { 116 if k := t.Field(i).Type.Kind(); k == reflect.Bool || k == reflect.Uint { 117 continue 118 } 119 name := t.Field(i).Name 120 if _, ok := done[name]; !ok { 121 fmt.Printf("\n name%s = %v", name, toSlice(name)) 122 done[name] = struct{}{} 123 } 124 } 125 } 126 fmt.Printf("\n)\n\n") 127 for _, typ := range allTypes { 128 t := reflect.TypeOf(typ) 129 fmt.Printf("func (f *%s) printType(w io.Writer, v bool) {\n w.Write(name%s[1:%d])\n w.Write(objectOpen)\n pp := indentPrinter{w}\n", t.Name(), t.Name(), len(t.Name())+1) 130 for i := 0; i < t.NumField(); i++ { 131 f := t.Field(i) 132 if f.Name == "Tokens" { 133 fmt.Printf(" if v {\n pp.Write(tokensTo)\n f.Tokens.printType(&pp, v)\n }\n") 134 } else if f.Type.Kind() == reflect.Ptr { 135 fmt.Printf(" if f.%s != nil {\n pp.Write(name%s)\n f.%s.printType(&pp, v)\n } else if v {\n pp.Write(name%s)\n pp.Write(nilStr)\n }\n", f.Name, f.Name, f.Name, f.Name) 136 } else if f.Type.Kind() == reflect.Struct { 137 fmt.Printf(" pp.Write(name%s)\n f.%s.printType(&pp, v)\n", f.Name, f.Name) 138 } else if f.Type.Implements(stringer) { 139 fmt.Printf(" pp.Write(name%s)\n io.WriteString(&pp, f.%s.String())\n", f.Name, f.Name) 140 } else if f.Type.Kind() == reflect.Slice { 141 fmt.Printf(" if f.%s == nil {\n pp.Write(name%s)\n pp.Write(nilStr)\n } else if len(f.%s) > 0 {\n pp.Write(name%s)\n pp.Write(arrayOpen)\n ipp := indentPrinter{&pp}\n for n, e := range f.%s {\n ipp.Printf(\"\\n%%d:\", n)\n e.printType(&ipp, v)\n }\n pp.Write(arrayClose)\n } else if v {\n pp.Write(name%s)\n pp.Write(arrayOpenClose)\n }\n", f.Name, f.Name, f.Name, f.Name, f.Name, f.Name) 142 } else if f.Type.Kind() == reflect.Bool { 143 fmt.Printf(" if f.%s || v {\n pp.Printf(\"\\n%s: %%v\", f.%s)\n }\n", f.Name, f.Name, f.Name) 144 } else if f.Type.Kind() == reflect.Uint { 145 fmt.Printf(" pp.Printf(\"\\n%s: %%d\", f.%s)\n", f.Name, f.Name) 146 } 147 } 148 fmt.Printf(" w.Write(objectClose)\n}\n\n") 149 } 150 } 151 152 func toSlice(str string) string { 153 s := "[]byte{'\\n'" 154 for _, b := range []byte(str) { 155 s += ", '" + string(rune(b)) + "'" 156 } 157 return s + ", ':', ' '}" 158 } 159