-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
21 changed files
with
1,685 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package main | ||
|
||
import ( | ||
"go/ast" | ||
"go/parser" | ||
"go/token" | ||
"log" | ||
"os" | ||
) | ||
|
||
func main() { | ||
fset := token.NewFileSet() | ||
|
||
node, err := parser.ParseFile(fset, "./internal/delivery/api/endpoint.go", nil, parser.ParseComments) | ||
if err != nil { | ||
log.Fatalf("파싱 오류: %v", err) | ||
} | ||
|
||
ast.Print(fset, node) | ||
|
||
// write ast to file | ||
f, err := os.Create("ast.txt") | ||
if err != nil { | ||
log.Fatalf("파일 생성 오류: %v", err) | ||
} | ||
defer f.Close() | ||
ast.Fprint(f, fset, node, nil) | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,199 @@ | ||
package main | ||
|
||
import ( | ||
"bytes" | ||
"go/ast" | ||
"go/parser" | ||
"go/token" | ||
"html/template" | ||
"io/ioutil" | ||
"log" | ||
"strings" | ||
) | ||
|
||
const endpointFilePath = "./internal/delivery/api/endpoint.go" | ||
|
||
// endpointDecl은 엔드포인트 선언을 나타냅니다. | ||
type endpointDecl struct { | ||
Name string // 엔드포인트의 이름 | ||
Group string // 엔드포인트의 그룹 | ||
} | ||
|
||
const indexTemplateStr = ` // | ||
package api | ||
type Endpoint int | ||
type EndpointInfo struct { | ||
Name string | ||
Group string | ||
} | ||
` | ||
const endpointTemplateStr = `// Comment below is special purpose for code generation. | ||
// Do not edit this comment. | ||
// Endpoint for Code Generation | ||
const ( | ||
{{- range .}} | ||
{{.Name}} Endpoint = iota | ||
{{- end}} | ||
) | ||
` | ||
|
||
const apiMapTemplateStr = `var ApiMap = map[Endpoint]EndpointInfo{ | ||
{{- range .}} | ||
{{.Name}}: { | ||
Name: "{{.Name}}", | ||
Group: "{{.Group}}", | ||
}, | ||
{{- end}} | ||
} | ||
` | ||
|
||
const stringFunctionTemplateStr = `func (e Endpoint) String() string { | ||
switch e { | ||
{{- range .}} | ||
case {{.Name}}: | ||
return "{{.Name}}" | ||
{{- end}} | ||
default: | ||
return "" | ||
} | ||
} | ||
` | ||
|
||
const getEndpointFunctionTemplateStr = `func GetEndpoint(name string) Endpoint { | ||
switch name { | ||
{{- range .}} | ||
case "{{.Name}}": | ||
return {{.Name}} | ||
{{- end}} | ||
default: | ||
return -1 | ||
} | ||
} | ||
` | ||
|
||
func main() { | ||
fset := token.NewFileSet() | ||
node, err := parser.ParseFile(fset, endpointFilePath, nil, parser.ParseComments) | ||
if err != nil { | ||
log.Fatalf("failed to parse file: %v", err) | ||
} | ||
|
||
var endpoints []endpointDecl | ||
var currentGroup string | ||
|
||
// AST를 탐색합니다. | ||
ast.Inspect(node, func(n ast.Node) bool { | ||
switch x := n.(type) { | ||
case *ast.GenDecl: | ||
if x.Tok == token.CONST { | ||
if x.Doc != nil { | ||
for _, comment := range x.Doc.List { | ||
// "Endpoint" 주석 이후에 나오는 주석을 그룹 이름으로 사용합니다. | ||
if strings.Contains(comment.Text, "Endpoint for Code Generation") { | ||
continue | ||
} | ||
if strings.HasPrefix(comment.Text, "//") { | ||
currentGroup = strings.TrimSpace(strings.TrimPrefix(comment.Text, "//")) | ||
} | ||
} | ||
} | ||
for _, spec := range x.Specs { | ||
vs, ok := spec.(*ast.ValueSpec) | ||
if !ok { | ||
continue | ||
} | ||
if vs.Doc != nil { | ||
for _, comment := range vs.Doc.List { | ||
if strings.HasPrefix(comment.Text, "//") { | ||
currentGroup = strings.TrimSpace(strings.TrimPrefix(comment.Text, "//")) | ||
} | ||
} | ||
} | ||
|
||
for _, name := range vs.Names { | ||
endpoints = append(endpoints, endpointDecl{ | ||
Name: name.Name, | ||
Group: currentGroup, | ||
}) | ||
} | ||
} | ||
} | ||
} | ||
return true | ||
}) | ||
|
||
// 추출된 엔드포인트 정보를 출력합니다. | ||
for _, ep := range endpoints { | ||
log.Printf("Endpoint: %s, Group: %s\n", ep.Name, ep.Group) | ||
} | ||
|
||
// TODO: 추출된 정보를 바탕으로 ApiMap, String() 메서드, GetEndpoint() 함수 코드를 생성합니다. | ||
|
||
// contents for index | ||
indexTemplate := template.New("index") | ||
indexTemplate, err = indexTemplate.Parse(indexTemplateStr) | ||
if err != nil { | ||
log.Fatalf("failed to parse template: %v", err) | ||
} | ||
var indexCode bytes.Buffer | ||
if err := indexTemplate.Execute(&indexCode, endpoints); err != nil { | ||
log.Fatalf("failed to execute template: %v", err) | ||
} | ||
|
||
// contents for endpoint | ||
endpointTemplate := template.New("endpoint") | ||
endpointTemplate, err = endpointTemplate.Parse(endpointTemplateStr) | ||
if err != nil { | ||
log.Fatalf("failed to parse template: %v", err) | ||
} | ||
var endpointCode bytes.Buffer | ||
if err := endpointTemplate.Execute(&endpointCode, endpoints); err != nil { | ||
log.Fatalf("failed to execute template: %v", err) | ||
} | ||
|
||
// contents for apiMap | ||
apiMapTemplate := template.New("apiMap") | ||
apiMapTemplate, err = apiMapTemplate.Parse(apiMapTemplateStr) | ||
if err != nil { | ||
log.Fatalf("failed to parse template: %v", err) | ||
} | ||
var apiMapCode bytes.Buffer | ||
if err := apiMapTemplate.Execute(&apiMapCode, endpoints); err != nil { | ||
log.Fatalf("failed to execute template: %v", err) | ||
} | ||
|
||
// contents for stringFunction | ||
stringFunctionTemplate := template.New("stringFunction") | ||
stringFunctionTemplate, err = stringFunctionTemplate.Parse(stringFunctionTemplateStr) | ||
if err != nil { | ||
log.Fatalf("failed to parse template: %v", err) | ||
} | ||
var stringFunctionCode bytes.Buffer | ||
if err := stringFunctionTemplate.Execute(&stringFunctionCode, endpoints); err != nil { | ||
log.Fatalf("failed to execute template: %v", err) | ||
} | ||
|
||
// contents for getEndpointFunction | ||
getEndpointFunctionTemplate := template.New("getEndpointFunction") | ||
getEndpointFunctionTemplate, err = getEndpointFunctionTemplate.Parse(getEndpointFunctionTemplateStr) | ||
if err != nil { | ||
log.Fatalf("failed to parse template: %v", err) | ||
} | ||
var getEndpointFunctionCode bytes.Buffer | ||
if err := getEndpointFunctionTemplate.Execute(&getEndpointFunctionCode, endpoints); err != nil { | ||
log.Fatalf("failed to execute template: %v", err) | ||
} | ||
|
||
// replace original file(endpointFilePath) with new contents | ||
contents := indexCode.String() + endpointCode.String() + apiMapCode.String() + stringFunctionCode.String() + getEndpointFunctionCode.String() | ||
newFilePath := strings.Replace(endpointFilePath, "endpoint", "generated_endpoints.go", 1) | ||
|
||
if err := ioutil.WriteFile(newFilePath, []byte(contents), 0644); err != nil { | ||
log.Fatalf("failed to write file: %v", err) | ||
} | ||
|
||
log.Println("Code generation is done.") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
package api | ||
|
||
// | ||
//import ( | ||
// "github.com/gorilla/mux" | ||
// "net/http" | ||
//) | ||
// | ||
//type IApi interface { | ||
// //SetPath() | ||
// API() Api | ||
// //SetMethod() | ||
// //GetMethod() string | ||
// //SetHandler() | ||
// //GetHandler() http.Handler | ||
// // | ||
// //RegisterApi(router *mux.Router) | ||
//} | ||
//type Api struct { | ||
// Path string | ||
// Method string | ||
// Handler http.Handler | ||
//} | ||
// | ||
//func (a Api) GetPath() string { | ||
// return a.Path | ||
//} | ||
// | ||
//func (a Api) GetMethod() string { | ||
// return a.Method | ||
//} | ||
// | ||
//func (a Api) GetHandler() http.Handler { | ||
// return a.Handler | ||
//} | ||
// | ||
//func (a Api) SetBasePath(path string) { | ||
// a.Path = path | ||
//} | ||
// | ||
//func (a Api) SetMethod(method string) { | ||
// a.Method = method | ||
//} | ||
// | ||
//func (a Api) SetHandler(handler http.Handler) { | ||
// a.Handler = handler | ||
//} | ||
// | ||
//func (a Api) RegisterApi(router *mux.Router) { | ||
// router.Handle(a.GetPath(), a.GetHandler()) | ||
//} |
Oops, something went wrong.