Files
podman/docs/varlink/apidoc.go
baude a74107b506 alphabetize the varlink methods, types, and errors in the docs
We have decided to alphabetize things in the API documentation to help users
find things easier.  It also solves an issue where when being made, the API.md doc
would remake itself in a different order resulting in massive diffs in the pull
requests but no new content.

Signed-off-by: baude <bbaude@redhat.com>

Closes: #739
Approved by: baude
2018-05-10 14:32:34 +00:00

274 lines
7.0 KiB
Go

package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"sort"
"strings"
"github.com/varlink/go/varlink/idl"
)
func readFileToString(path string) (string, error) {
content, err := ioutil.ReadFile(path)
if err != nil {
return "", err
}
return string(content), nil
}
func exit(err error) {
fmt.Println(err.Error())
os.Exit(1)
}
func typeToString(input *idl.Type) string {
switch input.Kind {
case idl.TypeString:
return "string"
case idl.TypeBool:
return "bool"
case idl.TypeFloat:
return "float"
case idl.TypeArray:
result := input.ElementType.Alias
if result == "" {
return fmt.Sprintf("[]%s", typeToString(input.ElementType))
}
return result
case idl.TypeAlias:
return input.Alias
case idl.TypeMap:
return "map[string]"
case idl.TypeInt:
return "int"
}
return ""
}
func typeToLink(input string) string {
switch input {
case "string":
return "https://godoc.org/builtin#string"
case "int":
return "https://godoc.org/builtin#int"
case "bool":
return "https://godoc.org/builtin#bool"
case "float":
return "https://golang.org/src/builtin/builtin.go#L58"
default:
return fmt.Sprintf("#%s", input)
}
}
type funcArgs struct {
paramName string
paramKind string
}
type funcDescriber struct {
Name string
inputParams []funcArgs
returnParams []funcArgs
doc string
}
type funcSorter []funcDescriber
func (a funcSorter) Len() int { return len(a) }
func (a funcSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a funcSorter) Less(i, j int) bool { return a[i].Name < a[j].Name }
type typeAttrs struct {
Name string
AttrType string
}
type typeDescriber struct {
Name string
doc string
Attrs []typeAttrs
}
type typeSorter []typeDescriber
func (a typeSorter) Len() int { return len(a) }
func (a typeSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a typeSorter) Less(i, j int) bool { return a[i].Name < a[j].Name }
type err struct {
Name string
doc string
}
type errorSorter []err
func (a errorSorter) Len() int { return len(a) }
func (a errorSorter) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a errorSorter) Less(i, j int) bool { return a[i].Name < a[j].Name }
// collects defined types in the idl
func getTypes(tidl *idl.IDL) []typeDescriber {
var types []typeDescriber
for _, x := range tidl.Aliases {
i := typeDescriber{
Name: x.Name,
doc: x.Doc,
}
ta := []typeAttrs{}
for _, y := range x.Type.Fields {
result := typeToString(y.Type)
ta = append(ta, typeAttrs{Name: y.Name, AttrType: result})
}
i.Attrs = ta
types = append(types, i)
}
return types
}
// collects defined methods in the idl
func getMethods(midl *idl.IDL) []funcDescriber {
var methods []funcDescriber
for _, t := range midl.Methods {
m := funcDescriber{
Name: t.Name,
doc: t.Doc,
}
fa := []funcArgs{}
fo := []funcArgs{}
for _, i := range t.In.Fields {
fa = append(fa, funcArgs{paramName: i.Name, paramKind: typeToString(i.Type)})
}
for _, f := range t.Out.Fields {
fo = append(fo, funcArgs{paramName: f.Name, paramKind: typeToString(f.Type)})
}
m.inputParams = fa
m.returnParams = fo
methods = append(methods, m)
}
return methods
}
// collects defined errors in the idl
func getErrors(midl *idl.IDL) []err {
var errors []err
for _, e := range midl.Errors {
myError := err{
Name: e.Name,
doc: e.Doc,
}
errors = append(errors, myError)
}
return errors
}
// generates the index for the top of the markdown page
func generateIndex(methods []funcDescriber, types []typeDescriber, errors []err, b bytes.Buffer) bytes.Buffer {
// Sort the methods, types, and errors by alphabetical order
sort.Sort(funcSorter(methods))
sort.Sort(typeSorter(types))
sort.Sort(errorSorter(errors))
for _, method := range methods {
var inArgs []string
var outArgs []string
for _, inArg := range method.inputParams {
inArgs = append(inArgs, fmt.Sprintf("%s: %s", inArg.paramName, inArg.paramKind))
}
for _, outArg := range method.returnParams {
outArgs = append(outArgs, fmt.Sprintf("%s", outArg.paramKind))
}
b.WriteString(fmt.Sprintf("\n[func %s(%s) %s](#%s)\n", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", "), method.Name))
}
for _, t := range types {
b.WriteString(fmt.Sprintf("[type %s](#%s)\n\n", t.Name, t.Name))
}
for _, e := range errors {
b.WriteString(fmt.Sprintf("[error %s](#%s)\n\n", e.Name, e.Name))
}
return b
}
// performs the output for defined methods
func generateFuncDescriptions(methods []funcDescriber, b bytes.Buffer) bytes.Buffer {
for _, method := range methods {
b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>func %s\n", method.Name, method.Name))
var inArgs []string
var outArgs []string
for _, inArg := range method.inputParams {
inArgs = append(inArgs, fmt.Sprintf("%s: [%s](%s)", inArg.paramName, inArg.paramKind, typeToLink(inArg.paramKind)))
}
for _, outArg := range method.returnParams {
outArgs = append(outArgs, fmt.Sprintf("[%s](%s)", outArg.paramKind, typeToLink(outArg.paramKind)))
}
b.WriteString(fmt.Sprintf("<div style=\"background-color: #E8E8E8; padding: 15px; margin: 10px; border-radius: 10px;\">\n\nmethod %s(%s) %s</div>", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", ")))
b.WriteString("\n")
b.WriteString(method.doc)
b.WriteString("\n")
}
return b
}
// performs the output for defined types/structs
func generateTypeDescriptions(types []typeDescriber, b bytes.Buffer) bytes.Buffer {
for _, t := range types {
b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>type %s\n", t.Name, t.Name))
b.WriteString(fmt.Sprintf("\n%s\n", t.doc))
for _, i := range t.Attrs {
b.WriteString(fmt.Sprintf("\n%s [%s](%s)\n", i.Name, i.AttrType, typeToLink(i.AttrType)))
}
}
return b
}
// performs the output for defined errors
func generateErrorDescriptions(errors []err, b bytes.Buffer) bytes.Buffer {
for _, e := range errors {
b.WriteString(fmt.Sprintf("### <a name=\"%s\"></a>type %s\n", e.Name, e.Name))
b.WriteString(fmt.Sprintf("\n%s\n", e.doc))
}
return b
}
func main() {
args := os.Args
if len(args) < 2 {
exit(fmt.Errorf("you must provide an input and output path"))
}
varlinkFile := args[1]
mdFile := args[2]
varlinkInput, err := readFileToString(varlinkFile)
if err != nil {
exit(err)
}
varlinkInput = strings.TrimRight(varlinkInput, "\n")
// Run the idl parser
midl, err := idl.New(varlinkInput)
if err != nil {
exit(err)
}
// Collect up the info from the idl
methods := getMethods(midl)
types := getTypes(midl)
errors := getErrors(midl)
out := bytes.Buffer{}
out.WriteString(fmt.Sprintf("# %s\n", midl.Name))
out.WriteString(fmt.Sprintf("%s\n", midl.Doc))
out.WriteString("## Index\n")
out = generateIndex(methods, types, errors, out)
out.WriteString("## Methods\n")
out = generateFuncDescriptions(methods, out)
out.WriteString("## Types\n")
out = generateTypeDescriptions(types, out)
out.WriteString("## Errors\n")
out = generateErrorDescriptions(errors, out)
ioutil.WriteFile(mdFile, out.Bytes(), 0755)
}