package main import ( "encoding/json" "fmt" "os" "reflect" "sort" "strings" "github.com/filecoin-project/lotus/api" "github.com/filecoin-project/lotus/api/apistruct" "github.com/filecoin-project/lotus/api/docgen" ) func main() { comments, groupComments := docgen.ParseApiASTInfo(os.Args[1], os.Args[2]) groups := make(map[string]*docgen.MethodGroup) var t reflect.Type var permStruct, commonPermStruct reflect.Type switch os.Args[2] { case "FullNode": t = reflect.TypeOf(new(struct{ api.FullNode })).Elem() permStruct = reflect.TypeOf(apistruct.FullNodeStruct{}.Internal) commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal) case "StorageMiner": t = reflect.TypeOf(new(struct{ api.StorageMiner })).Elem() permStruct = reflect.TypeOf(apistruct.StorageMinerStruct{}.Internal) commonPermStruct = reflect.TypeOf(apistruct.CommonStruct{}.Internal) case "WorkerAPI": t = reflect.TypeOf(new(struct{ api.WorkerAPI })).Elem() permStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal) commonPermStruct = reflect.TypeOf(apistruct.WorkerStruct{}.Internal) default: panic("unknown type") } for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) groupName := docgen.MethodGroupFromName(m.Name) g, ok := groups[groupName] if !ok { g = new(docgen.MethodGroup) g.Header = groupComments[groupName] g.GroupName = groupName groups[groupName] = g } var args []interface{} ft := m.Func.Type() for j := 2; j < ft.NumIn(); j++ { inp := ft.In(j) args = append(args, docgen.ExampleValue(m.Name, inp, nil)) } v, err := json.MarshalIndent(args, "", " ") if err != nil { panic(err) } outv := docgen.ExampleValue(m.Name, ft.Out(0), nil) ov, err := json.MarshalIndent(outv, "", " ") if err != nil { panic(err) } g.Methods = append(g.Methods, &docgen.Method{ Name: m.Name, Comment: comments[m.Name], InputExample: string(v), ResponseExample: string(ov), }) } var groupslice []*docgen.MethodGroup for _, g := range groups { groupslice = append(groupslice, g) } sort.Slice(groupslice, func(i, j int) bool { return groupslice[i].GroupName < groupslice[j].GroupName }) fmt.Printf("# Groups\n") for _, g := range groupslice { fmt.Printf("* [%s](#%s)\n", g.GroupName, g.GroupName) for _, method := range g.Methods { fmt.Printf(" * [%s](#%s)\n", method.Name, method.Name) } } for _, g := range groupslice { g := g fmt.Printf("## %s\n", g.GroupName) fmt.Printf("%s\n\n", g.Header) sort.Slice(g.Methods, func(i, j int) bool { return g.Methods[i].Name < g.Methods[j].Name }) for _, m := range g.Methods { fmt.Printf("### %s\n", m.Name) fmt.Printf("%s\n\n", m.Comment) meth, ok := permStruct.FieldByName(m.Name) if !ok { meth, ok = commonPermStruct.FieldByName(m.Name) if !ok { panic("no perms for method: " + m.Name) } } perms := meth.Tag.Get("perm") fmt.Printf("Perms: %s\n\n", perms) if strings.Count(m.InputExample, "\n") > 0 { fmt.Printf("Inputs:\n```json\n%s\n```\n\n", m.InputExample) } else { fmt.Printf("Inputs: `%s`\n\n", m.InputExample) } if strings.Count(m.ResponseExample, "\n") > 0 { fmt.Printf("Response:\n```json\n%s\n```\n\n", m.ResponseExample) } else { fmt.Printf("Response: `%s`\n\n", m.ResponseExample) } } } }