Skip to content

Commit

Permalink
Merge pull request #219 from cho4036/dev_project
Browse files Browse the repository at this point in the history
Project RBAC 구현을 위한 공통 코드 개발
  • Loading branch information
ktkfree authored Jan 24, 2024
2 parents 742c5c5 + 3e8c181 commit f02d82b
Show file tree
Hide file tree
Showing 20 changed files with 2,309 additions and 161 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ jobs:
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: v1.51.0
args: --timeout=5m
args: --timeout=10m
# Optional: working directory, useful for monorepos
# working-directory: somedir

Expand Down
356 changes: 356 additions & 0 deletions go.work.sum

Large diffs are not rendered by default.

21 changes: 21 additions & 0 deletions hack/ast-generator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package main

//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)
//
//}
195 changes: 195 additions & 0 deletions hack/endpoint-codegen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package main

import (
"bytes"
"go/ast"
"go/parser"
"go/token"
"html/template"
"io/ioutil"
"log"
"strings"
)

const endpointFilePath = "./internal/delivery/api/endpoint.go"

type endpointDecl struct {
Name string
Group string
}

//const indexTemplateStr = ` // This is generated code. DO NOT EDIT.
//
//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 {
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)
}

//// 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()
contents := 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.")
}
Loading

0 comments on commit f02d82b

Please sign in to comment.