github.com/fasmat/buffalo@v0.11.0/generators/helpers.go (about) 1 package generators 2 3 import ( 4 "errors" 5 "fmt" 6 "go/ast" 7 "go/parser" 8 "go/token" 9 "io/ioutil" 10 "strings" 11 ) 12 13 // AddRoute adds a new route inside the `action/app.go` file. 14 func AddRoute(method, path, handlerName string) error { 15 routeDefinition := fmt.Sprintf(`app.%v("%v", %v)`, method, path, handlerName) 16 return AddInsideAppBlock(routeDefinition) 17 } 18 19 // AddInsideAppBlock will add anything inside of the app declaration block inside of `actions/app.go` 20 func AddInsideAppBlock(expressions ...string) error { 21 src, err := ioutil.ReadFile("actions/app.go") 22 if err != nil { 23 return err 24 } 25 26 fset := token.NewFileSet() 27 f, err := parser.ParseFile(fset, "actions/app.go", string(src), 0) 28 if err != nil { 29 return err 30 } 31 32 srcContent := string(src) 33 fileLines := strings.Split(srcContent, "\n") 34 35 end := findClosingRouteBlockEnd(f, fset, fileLines) 36 if end < 0 { 37 return errors.New("could not find desired block on the app.go file") 38 } 39 40 el := fileLines[end:] 41 sl := []string{} 42 sf := []string{} 43 for _, l := range fileLines[:end] { 44 // if there's a app.ServeFiles("/", foo) line it needs to be the last added to the router 45 if strings.Contains(l, "ServeFiles(\"/\"") { 46 sf = append(sf, l) 47 continue 48 } 49 sl = append(sl, l) 50 } 51 52 for i := 0; i < len(expressions); i++ { 53 expressions[i] = fmt.Sprintf("\t\t%s", expressions[i]) 54 } 55 56 el = append(sf, el...) 57 fileLines = append(sl, append(expressions, el...)...) 58 59 fileContent := strings.Join(fileLines, "\n") 60 err = ioutil.WriteFile("actions/app.go", []byte(fileContent), 0755) 61 return err 62 } 63 64 func findClosingRouteBlockEnd(f *ast.File, fset *token.FileSet, fileLines []string) int { 65 var end = -1 66 67 ast.Inspect(f, func(n ast.Node) bool { 68 switch x := n.(type) { 69 case *ast.BlockStmt: 70 start := fset.Position(x.Lbrace).Line 71 blockDeclaration := fmt.Sprintf("%s\n", fileLines[start-1]) 72 73 if strings.Contains(blockDeclaration, "if app == nil {") { 74 end = fset.Position(x.Rbrace).Line - 1 75 } 76 77 } 78 return true 79 }) 80 81 return end 82 } 83 84 // AddImport adds n number of import statements into the path provided 85 func AddImport(path string, imports ...string) error { 86 src, err := ioutil.ReadFile(path) 87 if err != nil { 88 return err 89 } 90 91 fset := token.NewFileSet() 92 f, err := parser.ParseFile(fset, path, string(src), 0) 93 if err != nil { 94 return err 95 } 96 97 srcContent := string(src) 98 fileLines := strings.Split(srcContent, "\n") 99 100 end := findLastImport(f, fset, fileLines) 101 102 x := make([]string, len(imports), len(imports)+2) 103 for _, i := range imports { 104 x = append(x, fmt.Sprintf("\t\"%s\"", i)) 105 106 } 107 if end < 0 { 108 x = append([]string{"import ("}, x...) 109 x = append(x, ")") 110 } 111 112 fileLines = append(fileLines[:end], append(x, fileLines[end:]...)...) 113 114 fileContent := strings.Join(fileLines, "\n") 115 err = ioutil.WriteFile(path, []byte(fileContent), 0755) 116 return err 117 } 118 119 func findLastImport(f *ast.File, fset *token.FileSet, fileLines []string) int { 120 var end = -1 121 122 ast.Inspect(f, func(n ast.Node) bool { 123 switch x := n.(type) { 124 case *ast.ImportSpec: 125 end = fset.Position(x.End()).Line 126 return true 127 } 128 return true 129 }) 130 131 return end 132 }