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  }