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