github.com/servernoj/jade@v0.0.0-20231225191405-efec98d19db1/cmd/jade/go_ast_wstr.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "fmt" 6 "go/ast" 7 "strings" 8 ) 9 10 func (a *goAST) collapseWriteString(strInline bool, constName string) { 11 // ast.Print(a.fset, a.node) 12 13 var wrSt = writeStrings{inline: strInline, constName: constName} 14 ast.Inspect(a.node, func(n ast.Node) bool { 15 if n != nil { 16 switch x := n.(type) { 17 case *ast.CaseClause: 18 wrSt.push(x.Body) 19 case *ast.BlockStmt: 20 wrSt.push(x.List) 21 // case *ast.CallExpr: 22 // return false 23 } 24 } 25 return true 26 }) 27 28 wrSt.fillConstNode(a.node.Decls) 29 } 30 31 // 32 33 type writeStrings struct { 34 constSlice []struct { 35 str string 36 name string 37 } 38 constName string 39 constCount int 40 inline bool 41 } 42 43 func (ws *writeStrings) push(in []ast.Stmt) { 44 type wStr struct { 45 s string 46 a *ast.CallExpr 47 z *ast.Stmt 48 } 49 List := [][]wStr{} 50 subList := make([]wStr, 0, 4) 51 52 for k, ex := range in { 53 if es, ok := ex.(*ast.ExprStmt); ok { 54 if ce, ok := es.X.(*ast.CallExpr); ok { 55 if fun, ok := ce.Fun.(*ast.SelectorExpr); ok && len(ce.Args) == 1 && fun.Sel.Name == "WriteString" { 56 if arg, ok := ce.Args[0].(*ast.BasicLit); ok { 57 subList = append(subList, wStr{s: strings.Trim(arg.Value, "`"), a: ce, z: &in[k]}) 58 continue 59 } 60 } 61 } 62 } 63 if len(subList) > 0 { 64 List = append(List, subList) 65 subList = make([]wStr, 0, 4) 66 } 67 } 68 if len(subList) > 0 { 69 List = append(List, subList) 70 } 71 72 // 73 74 var st = new(bytes.Buffer) 75 for _, block := range List { 76 77 st.WriteString(block[0].s) 78 for i := 1; i < len(block); i++ { 79 st.WriteString(block[i].s) 80 *block[i].z = new(ast.EmptyStmt) // remove a node 81 } 82 83 if ws.inline { 84 block[0].a.Args[0].(*ast.BasicLit).Value = "`" + st.String() + "`" 85 } else { 86 str := st.String() 87 if name, ok := dict[str]; ok { 88 block[0].a.Args = []ast.Expr{&ast.Ident{Name: name}} 89 } else { 90 newName := fmt.Sprintf("%s__%d", ws.constName, ws.constCount) 91 block[0].a.Args = []ast.Expr{&ast.Ident{Name: newName}} 92 dict[str] = newName 93 ws.constSlice = append(ws.constSlice, struct { 94 str string 95 name string 96 }{ 97 str, 98 newName, 99 }) 100 } 101 } 102 103 st.Reset() 104 ws.constCount += 1 105 } 106 } 107 108 func (ws *writeStrings) fillConstNode(decl []ast.Decl) { 109 if constNode, ok := decl[1].(*ast.GenDecl); ok && !ws.inline { 110 for _, v := range ws.constSlice { 111 constNode.Specs = append(constNode.Specs, &ast.ValueSpec{ 112 Names: []*ast.Ident{ 113 &ast.Ident{Name: v.name}, 114 }, 115 Values: []ast.Expr{ 116 &ast.BasicLit{Kind: 9, Value: "`" + v.str + "`"}, // 9 => string 117 }, 118 }) 119 } 120 } 121 }