github.com/meulengracht/snapd@v0.0.0-20210719210640-8bde69bcc84e/docs/error-kinds.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/doc"
     7  	"go/parser"
     8  	"go/token"
     9  	"os"
    10  	"sort"
    11  	"strconv"
    12  	"strings"
    13  )
    14  
    15  const (
    16  	errorKindsHdr      = `## <h3 id='heading--errors'>Error kinds</h3>`
    17  	maintErrorKindsHdr = `## <h4 id='heading--maint-errors'>Maintenance error kinds</h4>
    18  
    19  These are used only inside the ` + "`maintenance` field of responses."
    20  )
    21  
    22  func fail(err error) {
    23  	fmt.Fprintf(os.Stderr, "error: %v", err)
    24  	os.Exit(1)
    25  }
    26  
    27  func main() {
    28  	fset := token.NewFileSet()
    29  	pkgs, err := parser.ParseDir(fset, "../client", nil, parser.ParseComments)
    30  	if err != nil {
    31  		fail(err)
    32  	}
    33  
    34  	p := doc.New(pkgs["client"], "github.com/snapcore/snapd/client", 0)
    35  	var errorKindT *doc.Type
    36  	for _, t := range p.Types {
    37  		if t.Name == "ErrorKind" {
    38  			errorKindT = t
    39  			break
    40  		}
    41  	}
    42  	if errorKindT == nil {
    43  		fail(fmt.Errorf("expected ErrorKind type not defined"))
    44  	}
    45  	for _, c := range errorKindT.Consts {
    46  		if strings.HasPrefix(c.Doc, "Error kinds.") {
    47  			fmt.Println(errorKindsHdr)
    48  		} else if strings.HasPrefix(c.Doc, "Maintenance error kinds") {
    49  			fmt.Println()
    50  			fmt.Println(maintErrorKindsHdr)
    51  		} else {
    52  			fmt.Fprintf(os.Stderr, "unexpected error kind group: %v\n", c.Doc)
    53  			continue
    54  		}
    55  		fmt.Println()
    56  
    57  		kinds := make([]string, 0, len(c.Decl.Specs))
    58  		docs := make(map[string]string, len(c.Decl.Specs))
    59  		for _, spec := range c.Decl.Specs {
    60  			vs, ok := spec.(*ast.ValueSpec)
    61  			if !ok {
    62  				fmt.Printf("%#v\n", spec)
    63  				continue
    64  			}
    65  			kind, err := strconv.Unquote(vs.Values[0].(*ast.BasicLit).Value)
    66  			if err != nil {
    67  				// unexpected
    68  				fail(err)
    69  			}
    70  			doc := vs.Doc.Text()
    71  			name := vs.Names[0]
    72  			pfx := name.String() + ":"
    73  			if !strings.HasPrefix(doc, pfx) {
    74  				fmt.Fprintf(os.Stderr, "expected %s: doc string prefix, got %q\n", name, doc)
    75  			} else {
    76  				doc = doc[len(pfx):]
    77  			}
    78  			doc = strings.Replace(doc, "\n", " ", -1)
    79  			doc = strings.Replace(doc, "  ", " ", -1)
    80  			doc = strings.TrimSpace(doc)
    81  			if !strings.HasSuffix(doc, ".") {
    82  				fmt.Fprintf(os.Stderr, "expected dot at the end %q for %s\n", doc, name)
    83  			}
    84  			if strings.HasPrefix(doc, "deprecated") {
    85  				// skip
    86  				continue
    87  			}
    88  			if doc == "" {
    89  				doc = name.String() + "..."
    90  			}
    91  			kinds = append(kinds, kind)
    92  			docs[kind] = doc
    93  		}
    94  
    95  		sort.Strings(kinds)
    96  		for _, kind := range kinds {
    97  			fmt.Printf("* `%s`: %s\n", kind, docs[kind])
    98  		}
    99  	}
   100  }