stash/vendor/github.com/gobuffalo/gogen/add_inside_block.go

82 lines
1.8 KiB
Go

package gogen
import (
"fmt"
"go/ast"
"strings"
"github.com/gobuffalo/genny"
"github.com/pkg/errors"
)
// AddInsideBlock will add anything inside of the app declaration block inside of file
func AddInsideBlock(gf genny.File, search string, expressions ...string) (genny.File, error) {
pf, err := ParseFile(gf)
if err != nil {
return gf, errors.WithStack(err)
}
gf = pf.File
_, end := findBlockCoordinates(search, pf)
if end < 0 {
return gf, errors.Errorf("could not find desired block in %s", gf.Name())
}
if len(pf.Lines) == end {
end = end - 1
}
el := pf.Lines[end:]
sl := []string{}
sf := []string{}
for _, l := range pf.Lines[:end] {
// if there's a app.ServeFiles("/", foo) line it needs to be the last added to the router
if strings.Contains(l, "ServeFiles(\"/\"") {
sf = append(sf, l)
continue
}
sl = append(sl, l)
}
for i := 0; i < len(expressions); i++ {
expressions[i] = fmt.Sprintf("\t\t%s", expressions[i])
}
el = append(sf, el...)
pf.Lines = append(sl, append(expressions, el...)...)
fileContent := strings.Join(pf.Lines, "\n")
return genny.NewFile(gf.Name(), strings.NewReader(fileContent)), nil
}
func findBlockCoordinates(search string, pf ParsedFile) (int, int) {
var end = -1
var start = -1
ast.Inspect(pf.Ast, func(n ast.Node) bool {
switch x := n.(type) {
case *ast.StructType:
line := pf.FileSet.Position(x.Pos()).Line
structDeclaration := fmt.Sprintf("%s\n", pf.Lines[line-1])
if strings.Contains(structDeclaration, search) {
start = line
end = pf.FileSet.Position(x.End()).Line
return false
}
case *ast.BlockStmt:
start = pf.FileSet.Position(x.Lbrace).Line
blockDeclaration := fmt.Sprintf("%s\n", pf.Lines[start-1])
if strings.Contains(blockDeclaration, search) {
end = pf.FileSet.Position(x.Rbrace).Line - 1
}
}
return true
})
return start, end
}