Skip to content

Commit

Permalink
feat: add gen
Browse files Browse the repository at this point in the history
  • Loading branch information
sashamelentyev committed Aug 5, 2022
1 parent 3619a08 commit 1e5a19e
Show file tree
Hide file tree
Showing 17 changed files with 1,901 additions and 376 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/ci.yaml
Expand Up @@ -25,9 +25,6 @@ jobs:
version: latest
args: --timeout 5m

- name: Go Format
run: gofmt -s -w . && git diff --exit-code

- name: Go Tidy
run: go mod tidy && git diff --exit-code

Expand Down
242 changes: 242 additions & 0 deletions internal/gen.go
@@ -0,0 +1,242 @@
//go:build ignore
// +build ignore

package main

import (
"crypto"
"embed"
"log"
"net/http"
"net/rpc"
"os"
"regexp"
"strconv"
"text/template"
"time"
)

type tmpl struct {
PackageName string
Dict dict
}

type (
dict struct {
Name string
Data []data
}
data struct {
Key string
Value string
}
)

var cryptoHash = dict{
Name: "cryptoHash",
Data: []data{
{Key: crypto.MD4.String(), Value: "crypto.MD4.String()"},
{Key: crypto.MD5.String(), Value: "crypto.MD5.String()"},
{Key: crypto.SHA1.String(), Value: "crypto.SHA1.String()"},
{Key: crypto.SHA224.String(), Value: "crypto.SHA224.String()"},
{Key: crypto.SHA256.String(), Value: "crypto.SHA256.String()"},
{Key: crypto.SHA384.String(), Value: "crypto.SHA384.String()"},
{Key: crypto.SHA512.String(), Value: "crypto.SHA512.String()"},
{Key: crypto.MD5SHA1.String(), Value: "crypto.MD5SHA1.String()"},
{Key: crypto.RIPEMD160.String(), Value: "crypto.RIPEMD160.String()"},
{Key: crypto.SHA3_224.String(), Value: "crypto.SHA3_224.String()"},
{Key: crypto.SHA3_256.String(), Value: "crypto.SHA3_256.String()"},
{Key: crypto.SHA3_384.String(), Value: "crypto.SHA3_384.String()"},
{Key: crypto.SHA3_512.String(), Value: "crypto.SHA3_512.String()"},
{Key: crypto.SHA512_224.String(), Value: "crypto.SHA512_224.String()"},
{Key: crypto.SHA512_256.String(), Value: "crypto.SHA512_256.String()"},
{Key: crypto.BLAKE2s_256.String(), Value: "crypto.BLAKE2s_256.String()"},
{Key: crypto.BLAKE2b_256.String(), Value: "crypto.BLAKE2b_256.String()"},
{Key: crypto.BLAKE2b_384.String(), Value: "crypto.BLAKE2b_384.String()"},
{Key: crypto.BLAKE2b_512.String(), Value: "crypto.BLAKE2b_512.String()"},
},
}

var httpMethod = dict{
Name: "httpMethod",
Data: []data{
{Key: http.MethodGet, Value: "http.MethodGet"},
{Key: http.MethodHead, Value: "http.MethodHead"},
{Key: http.MethodPost, Value: "http.MethodPost"},
{Key: http.MethodPut, Value: "http.MethodPut"},
{Key: http.MethodPatch, Value: "http.MethodPatch"},
{Key: http.MethodDelete, Value: "http.MethodDelete"},
{Key: http.MethodConnect, Value: "http.MethodConnect"},
{Key: http.MethodOptions, Value: "http.MethodOptions"},
{Key: http.MethodTrace, Value: "http.MethodTrace"},
},
}

var httpStatusCode = dict{
Name: "httpStatusCode",
Data: []data{
{Key: strconv.Itoa(http.StatusContinue), Value: "http.StatusContinue"},
{Key: strconv.Itoa(http.StatusSwitchingProtocols), Value: "http.StatusSwitchingProtocols"},
{Key: strconv.Itoa(http.StatusProcessing), Value: "http.StatusProcessing"},
{Key: strconv.Itoa(http.StatusEarlyHints), Value: "http.StatusEarlyHints"},

{Key: strconv.Itoa(http.StatusOK), Value: "http.StatusOK"},
{Key: strconv.Itoa(http.StatusCreated), Value: "http.StatusCreated"},
{Key: strconv.Itoa(http.StatusAccepted), Value: "http.StatusAccepted"},
{Key: strconv.Itoa(http.StatusNonAuthoritativeInfo), Value: "http.StatusNonAuthoritativeInfo"},
{Key: strconv.Itoa(http.StatusNoContent), Value: "http.StatusNoContent"},
{Key: strconv.Itoa(http.StatusResetContent), Value: "http.StatusResetContent"},
{Key: strconv.Itoa(http.StatusPartialContent), Value: "http.StatusPartialContent"},
{Key: strconv.Itoa(http.StatusMultiStatus), Value: "http.StatusMultiStatus"},
{Key: strconv.Itoa(http.StatusAlreadyReported), Value: "http.StatusAlreadyReported"},
{Key: strconv.Itoa(http.StatusIMUsed), Value: "http.StatusIMUsed"},

{Key: strconv.Itoa(http.StatusMultipleChoices), Value: "http.StatusMultipleChoices"},
{Key: strconv.Itoa(http.StatusMovedPermanently), Value: "http.StatusMovedPermanently"},
{Key: strconv.Itoa(http.StatusFound), Value: "http.StatusFound"},
{Key: strconv.Itoa(http.StatusSeeOther), Value: "http.StatusSeeOther"},
{Key: strconv.Itoa(http.StatusNotModified), Value: "http.StatusNotModified"},
{Key: strconv.Itoa(http.StatusUseProxy), Value: "http.StatusUseProxy"},
{Key: strconv.Itoa(http.StatusTemporaryRedirect), Value: "http.StatusTemporaryRedirect"},
{Key: strconv.Itoa(http.StatusPermanentRedirect), Value: "http.StatusPermanentRedirect"},

{Key: strconv.Itoa(http.StatusBadRequest), Value: "http.StatusBadRequest"},
{Key: strconv.Itoa(http.StatusUnauthorized), Value: "http.StatusUnauthorized"},
{Key: strconv.Itoa(http.StatusPaymentRequired), Value: "http.StatusPaymentRequired"},
{Key: strconv.Itoa(http.StatusForbidden), Value: "http.StatusForbidden"},
{Key: strconv.Itoa(http.StatusNotFound), Value: "http.StatusNotFound"},
{Key: strconv.Itoa(http.StatusMethodNotAllowed), Value: "http.StatusMethodNotAllowed"},
{Key: strconv.Itoa(http.StatusNotAcceptable), Value: "http.StatusNotAcceptable"},
{Key: strconv.Itoa(http.StatusProxyAuthRequired), Value: "http.StatusProxyAuthRequired"},
{Key: strconv.Itoa(http.StatusRequestTimeout), Value: "http.StatusRequestTimeout"},
{Key: strconv.Itoa(http.StatusConflict), Value: "http.StatusConflict"},
{Key: strconv.Itoa(http.StatusGone), Value: "http.StatusGone"},
{Key: strconv.Itoa(http.StatusLengthRequired), Value: "http.StatusLengthRequired"},
{Key: strconv.Itoa(http.StatusPreconditionFailed), Value: "http.StatusPreconditionFailed"},
{Key: strconv.Itoa(http.StatusRequestEntityTooLarge), Value: "http.StatusRequestEntityTooLarge"},
{Key: strconv.Itoa(http.StatusRequestURITooLong), Value: "http.StatusRequestURITooLong"},
{Key: strconv.Itoa(http.StatusUnsupportedMediaType), Value: "http.StatusUnsupportedMediaType"},
{Key: strconv.Itoa(http.StatusRequestedRangeNotSatisfiable), Value: "http.StatusRequestedRangeNotSatisfiable"},
{Key: strconv.Itoa(http.StatusExpectationFailed), Value: "http.StatusExpectationFailed"},
{Key: strconv.Itoa(http.StatusTeapot), Value: "http.StatusTeapot"},
{Key: strconv.Itoa(http.StatusMisdirectedRequest), Value: "http.StatusMisdirectedRequest"},
{Key: strconv.Itoa(http.StatusUnprocessableEntity), Value: "http.StatusUnprocessableEntity"},
{Key: strconv.Itoa(http.StatusLocked), Value: "http.StatusLocked"},
{Key: strconv.Itoa(http.StatusFailedDependency), Value: "http.StatusFailedDependency"},
{Key: strconv.Itoa(http.StatusTooEarly), Value: "http.StatusTooEarly"},
{Key: strconv.Itoa(http.StatusUpgradeRequired), Value: "http.StatusUpgradeRequired"},
{Key: strconv.Itoa(http.StatusPreconditionRequired), Value: "http.StatusPreconditionRequired"},
{Key: strconv.Itoa(http.StatusTooManyRequests), Value: "http.StatusTooManyRequests"},
{Key: strconv.Itoa(http.StatusRequestHeaderFieldsTooLarge), Value: "http.StatusRequestHeaderFieldsTooLarge"},
{Key: strconv.Itoa(http.StatusUnavailableForLegalReasons), Value: "http.StatusUnavailableForLegalReasons"},

{Key: strconv.Itoa(http.StatusInternalServerError), Value: "http.StatusInternalServerError"},
{Key: strconv.Itoa(http.StatusNotImplemented), Value: "http.StatusNotImplemented"},
{Key: strconv.Itoa(http.StatusBadGateway), Value: "http.StatusBadGateway"},
{Key: strconv.Itoa(http.StatusServiceUnavailable), Value: "http.StatusServiceUnavailable"},
{Key: strconv.Itoa(http.StatusGatewayTimeout), Value: "http.StatusGatewayTimeout"},
{Key: strconv.Itoa(http.StatusHTTPVersionNotSupported), Value: "http.StatusHTTPVersionNotSupported"},
{Key: strconv.Itoa(http.StatusVariantAlsoNegotiates), Value: "http.StatusVariantAlsoNegotiates"},
{Key: strconv.Itoa(http.StatusInsufficientStorage), Value: "http.StatusInsufficientStorage"},
{Key: strconv.Itoa(http.StatusLoopDetected), Value: "http.StatusLoopDetected"},
{Key: strconv.Itoa(http.StatusNotExtended), Value: "http.StatusNotExtended"},
{Key: strconv.Itoa(http.StatusNetworkAuthenticationRequired), Value: "http.StatusNetworkAuthenticationRequired"},
},
}

var defaultRPCPath = dict{
Name: "defaultRPCPath",
Data: []data{
{Key: rpc.DefaultRPCPath, Value: "rpc.DefaultRPCPath"},
{Key: rpc.DefaultDebugPath, Value: "rpc.DefaultDebugPath"},
},
}

var timeWeekday = dict{
Name: "timeWeekday",
Data: []data{
{Key: time.Sunday.String(), Value: "time.Sunday.String()"},
{Key: time.Monday.String(), Value: "time.Monday.String()"},
{Key: time.Tuesday.String(), Value: "time.Tuesday.String()"},
{Key: time.Wednesday.String(), Value: "time.Wednesday.String()"},
{Key: time.Thursday.String(), Value: "time.Thursday.String()"},
{Key: time.Friday.String(), Value: "time.Friday.String()"},
{Key: time.Saturday.String(), Value: "time.Saturday.String()"},
},
}

var timeMonth = dict{
Name: "timeMonth",
Data: []data{
{Key: time.January.String(), Value: "time.January.String()"},
{Key: time.February.String(), Value: "time.February.String()"},
{Key: time.March.String(), Value: "time.March.String()"},
{Key: time.April.String(), Value: "time.April.String()"},
{Key: time.May.String(), Value: "time.May.String()"},
{Key: time.June.String(), Value: "time.June.String()"},
{Key: time.July.String(), Value: "time.July.String()"},
{Key: time.August.String(), Value: "time.August.String()"},
{Key: time.September.String(), Value: "time.September.String()"},
{Key: time.October.String(), Value: "time.October.String()"},
{Key: time.November.String(), Value: "time.November.String()"},
{Key: time.December.String(), Value: "time.December.String()"},
},
}

var timeLayout = dict{
Name: "timeLayout",
Data: []data{
{Key: time.Layout, Value: "time.Layout"},
{Key: time.ANSIC, Value: "time.ANSIC"},
{Key: time.UnixDate, Value: "time.UnixDate"},
{Key: time.RubyDate, Value: "time.RubyDate"},
{Key: time.RFC822, Value: "time.RFC822"},
{Key: time.RFC822Z, Value: "time.RFC822Z"},
{Key: time.RFC850, Value: "time.RFC850"},
{Key: time.RFC1123, Value: "time.RFC1123"},
{Key: time.RFC1123Z, Value: "time.RFC1123Z"},
{Key: time.RFC3339, Value: "time.RFC3339"},
{Key: time.RFC3339Nano, Value: "time.RFC3339Nano"},
{Key: time.Kitchen, Value: "time.Kitchen"},
{Key: time.Stamp, Value: "time.Stamp"},
{Key: time.StampMilli, Value: "time.StampMilli"},
{Key: time.StampMicro, Value: "time.StampMicro"},
{Key: time.StampNano, Value: "time.StampNano"},
},
}

//go:embed template/*
var templateDir embed.FS

func main() {
t := template.Must(
template.New("template").
Funcs(map[string]any{"quoteMeta": regexp.QuoteMeta}).
ParseFS(templateDir, "template/*.tmpl"),
)
execute("pkg/analyzer/mapping.go", t, "mapping.tmpl", []dict{cryptoHash, httpMethod, httpStatusCode, defaultRPCPath, timeWeekday, timeMonth, timeLayout})
execute("pkg/analyzer/testdata/src/a/crypto/crypto.go", t, "template.tmpl", tmpl{PackageName: "crypto", Dict: cryptoHash})
execute("pkg/analyzer/testdata/src/a/http/method.go", t, "httpmethod.tmpl", httpMethod)
execute("pkg/analyzer/testdata/src/a/http/statuscode.go", t, "httpstatuscode.tmpl", httpStatusCode)
execute("pkg/analyzer/testdata/src/a/rpc/rpc.go", t, "template.tmpl", tmpl{PackageName: "rpc", Dict: defaultRPCPath})
execute("pkg/analyzer/testdata/src/a/time/weekday.go", t, "template.tmpl", tmpl{PackageName: "time", Dict: timeWeekday})
execute("pkg/analyzer/testdata/src/a/time/month.go", t, "template.tmpl", tmpl{PackageName: "time", Dict: timeMonth})
execute("pkg/analyzer/testdata/src/a/time/layout.go", t, "template.tmpl", tmpl{PackageName: "time", Dict: timeLayout})
}

func execute(fileName string, t *template.Template, templateName string, data any) {
f, err := os.Create(fileName)
mustNil(err)
defer f.Close()
t.ExecuteTemplate(
f,
templateName,
data,
)
}

func mustNil(err error) {
if err != nil {
log.Panic(err)
}
}
37 changes: 37 additions & 0 deletions internal/template/httpmethod.tmpl
@@ -0,0 +1,37 @@
// Code generated by usestdlibvars, DO NOT EDIT.

package http

import "net/http"

var (
{{- range $key, $data := .Data }}
_ = "{{ $data.Key }}"
{{- end }}
)

const (
{{- range $key, $data := .Data }}
_ = "{{ $data.Key }}"
{{- end }}
)

func _() {
{{- range $key, $data := .Data }}
_, _ = http.NewRequest("{{ $data.Key }}", "", nil) // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
{{- end }}
}

func _() {
{{- range $key, $data := .Data }}
_, _ = http.NewRequestWithContext(nil, "{{ $data.Key }}", "", nil) // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
{{- end }}
}

func _() {
{{- range $key, $data := .Data }}
_ = &http.Request{
Method: "{{ $data.Key }}", // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
}
{{- end }}
}
31 changes: 31 additions & 0 deletions internal/template/httpstatuscode.tmpl
@@ -0,0 +1,31 @@
// Code generated by usestdlibvars, DO NOT EDIT.

package http

import "net/http"

var (
{{- range $key, $data := .Data }}
_ = {{ $data.Key }}
{{- end }}
)

const (
{{- range $key, $data := .Data }}
_ = {{ $data.Key }}
{{- end }}
)
{{ range $key, $data := .Data }}
func _() {
var w http.ResponseWriter
w.WriteHeader({{ $data.Key }}) // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
}
{{ end -}}

{{ range $key, $data := .Data }}
func _() {
_ = &http.Response{
StatusCode: {{ $data.Key }}, // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
}
}
{{ end -}}
10 changes: 10 additions & 0 deletions internal/template/mapping.tmpl
@@ -0,0 +1,10 @@
// Code generated by usestdlibvars, DO NOT EDIT.

package analyzer
{{ range $key, $value := . }}
var {{ $value.Name }} = map[string]string{
{{- range $key, $data := $value.Data }}
"{{ $data.Key }}":"{{ $data.Value }}",
{{- end }}
}
{{ end -}}
33 changes: 33 additions & 0 deletions internal/template/template.tmpl
@@ -0,0 +1,33 @@
// Code generated by usestdlibvars, DO NOT EDIT.

package {{ .PackageName }}

import "fmt"

var (
{{- range $key, $data := .Dict.Data }}
_ = "{{ $data.Key }}" // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
{{- end }}
)

const (
{{- range $key, $data := .Dict.Data }}
_ = "{{ $data.Key }}" // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
{{- end }}
)

func _() {
{{- range $key, $data := .Dict.Data }}
_ = func(s string)string{return s}("{{ $data.Key }}") // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
_ = func(s string)string{return s}("text before key {{ $data.Key }}")
_ = func(s string)string{return s}("{{ $data.Key }} text after key")
{{- end }}
}

func _() {
{{- range $key, $data := .Dict.Data }}
_ = fmt.Sprint("{{ $data.Key }}") // want `"{{ quoteMeta $data.Key }}" can be replaced by {{ quoteMeta $data.Value }}`
_ = fmt.Sprint("text before key {{ $data.Key }}")
_ = fmt.Sprint("{{ $data.Key }} text after key")
{{- end }}
}
3 changes: 3 additions & 0 deletions main.go
Expand Up @@ -6,6 +6,9 @@ import (
"github.com/sashamelentyev/usestdlibvars/pkg/analyzer"
)

//go:generate go run internal/gen.go
//go:generate gofmt -s -w .

func main() {
singlechecker.Main(analyzer.New())
}

0 comments on commit 1e5a19e

Please sign in to comment.