mirror of
https://github.com/containers/podman.git
synced 2025-05-22 01:27:07 +08:00
280 lines
7.1 KiB
Go
280 lines
7.1 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"
|
|
case idl.TypeMaybe:
|
|
return fmt.Sprintf("?%s", typeToString(input.ElementType))
|
|
}
|
|
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, outArg.paramKind)
|
|
|
|
}
|
|
b.WriteString(fmt.Sprintf("\n[func %s(%s) %s](#%s)\n", method.Name, strings.Join(inArgs, ", "), strings.Join(outArgs, ", "), method.Name))
|
|
}
|
|
b.WriteString("\n")
|
|
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)
|
|
if err := ioutil.WriteFile(mdFile, out.Bytes(), 0755); err != nil {
|
|
fmt.Fprintf(os.Stderr, "Error writing file: %v\n", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|