11// SPDX-License-Identifier: MIT
22
3- // config-fields emits source-backed middleware config fields for the website.
3+ // config-fields emits source-backed middleware API facts for the website.
44// It does not claim to determine runtime defaults or behavior.
55package main
66
@@ -33,22 +33,33 @@ type config struct {
3333 Fields []field `json:"fields"`
3434}
3535
36+ type function struct {
37+ Name string `json:"name"`
38+ Signature string `json:"signature"`
39+ File string `json:"file"`
40+ Line int `json:"line"`
41+ }
42+
3643type manifest struct {
37- Module string `json:"module"`
38- Revision string `json:"revision,omitempty"`
39- Configs []config `json:"configs"`
44+ Module string `json:"module"`
45+ Revision string `json:"revision,omitempty"`
46+ Configs []config `json:"configs"`
47+ Functions []function `json:"functions"`
4048}
4149
4250func main () {
4351 root := flag .String ("root" , "" , "Echo repository root" )
4452 revision := flag .String ("revision" , "" , "exact Echo commit or tag used for this build" )
53+ module := flag .String ("module" , "github.com/labstack/echo/v5" , "module path containing the source" )
54+ directory := flag .String ("directory" , "middleware" , "package directory relative to the module root" )
55+ packageName := flag .String ("package" , "middleware" , "Go package name" )
4556 flag .Parse ()
4657 if * root == "" {
4758 fmt .Fprintln (os .Stderr , "-root is required" )
4859 os .Exit (2 )
4960 }
5061
51- result , err := extract (* root , * revision )
62+ result , err := extractPackage (* root , * revision , * module , * directory , * packageName )
5263 if err != nil {
5364 fmt .Fprintln (os .Stderr , err )
5465 os .Exit (1 )
@@ -62,26 +73,43 @@ func main() {
6273}
6374
6475func extract (root , revision string ) (manifest , error ) {
76+ return extractPackage (root , revision , "github.com/labstack/echo/v5" , "middleware" , "middleware" )
77+ }
78+
79+ func extractPackage (root , revision , module , directory , packageName string ) (manifest , error ) {
6580 root , err := filepath .Abs (root )
6681 if err != nil {
6782 return manifest {}, err
6883 }
6984 fs := token .NewFileSet ()
70- packageDir := filepath .Join (root , "middleware" )
85+ packageDir := filepath .Join (root , directory )
7186 packages , err := parser .ParseDir (fs , packageDir , func (info os.FileInfo ) bool {
7287 return strings .HasSuffix (info .Name (), ".go" ) && ! strings .HasSuffix (info .Name (), "_test.go" )
7388 }, parser .ParseComments )
7489 if err != nil {
7590 return manifest {}, err
7691 }
77- pkg , ok := packages ["middleware" ]
92+ pkg , ok := packages [packageName ]
7893 if ! ok {
79- return manifest {}, fmt .Errorf ("middleware package not found in %s" , packageDir )
94+ return manifest {}, fmt .Errorf ("package %s not found in %s" , packageName , packageDir )
8095 }
8196
82- result := manifest {Module : "github.com/labstack/echo/v5" , Revision : revision , Configs : []config {}}
97+ result := manifest {Module : module , Revision : revision , Configs : []config {}, Functions : [] function {}}
8398 for filename , source := range pkg .Files {
8499 for _ , declaration := range source .Decls {
100+ if fn , ok := declaration .(* ast.FuncDecl ); ok && fn .Recv == nil && ast .IsExported (fn .Name .Name ) {
101+ var rendered bytes.Buffer
102+ if err := format .Node (& rendered , fs , fn .Type ); err != nil {
103+ return manifest {}, err
104+ }
105+ result .Functions = append (result .Functions , function {
106+ Name : fn .Name .Name ,
107+ Signature : strings .Replace (rendered .String (), "func(" , "func " + fn .Name .Name + "(" , 1 ),
108+ File : filepath .ToSlash (strings .TrimPrefix (filename , root + string (filepath .Separator ))),
109+ Line : fs .Position (fn .Pos ()).Line ,
110+ })
111+ continue
112+ }
85113 group , ok := declaration .(* ast.GenDecl )
86114 if ! ok || group .Tok != token .TYPE {
87115 continue
@@ -121,6 +149,7 @@ func extract(root, revision string) (manifest, error) {
121149 }
122150 }
123151 sort .Slice (result .Configs , func (i , j int ) bool { return result .Configs [i ].Name < result .Configs [j ].Name })
152+ sort .Slice (result .Functions , func (i , j int ) bool { return result .Functions [i ].Name < result .Functions [j ].Name })
124153 return result , nil
125154}
126155
0 commit comments