D7net
Home
Console
Upload
information
Create File
Create Folder
About
Tools
:
/
proc
/
3206095
/
root
/
opt
/
golang
/
1.22.0
/
src
/
internal
/
types
/
errors
/
Filename :
generrordocs.go
back
Copy
//go:build ignore // Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // generrordocs creates a Markdown file for each (compiler) error code // and its associated documentation. // Note: this program must be run in this directory. // go run generrordocs.go <dir> //go:generate go run generrordocs.go errors_markdown package main import ( "bytes" "fmt" "go/ast" "go/importer" "go/parser" "go/token" "log" "os" "path" "strings" "text/template" . "go/types" ) func main() { if len(os.Args) != 2 { log.Fatal("missing argument: generrordocs <dir>") } outDir := os.Args[1] if err := os.MkdirAll(outDir, 0755); err != nil { log.Fatal("unable to create output directory: %s", err) } walkCodes(func(name string, vs *ast.ValueSpec) { // ignore unused errors if name == "_" { return } // Ensure that < are represented correctly when its included in code // blocks. The goldmark Markdown parser converts them to &lt; // when not escaped. It is the only known string with this issue. desc := strings.ReplaceAll(vs.Doc.Text(), "<", `{{raw "<"}}`) e := struct { Name string Description string }{ Name: name, Description: fmt.Sprintf("```\n%s```\n", desyc), } var buf bytes.Buffer err := template.Must(template.New("eachError").Parse(markdownTemplate)).Execute(&buf, e) if err != nil { log.Fatalf("template.Must: %s", err) } if err := os.WriteFile(path.Join(outDir, name+".md"), buf.Bytes(), 0660); err != nil { log.Fatalf("os.WriteFile: %s\n", err) } }) log.Printf("output directory: %s\n", outDir) } func walkCodes(f func(string, *ast.ValueSpec)) { fset := token.NewFileSet() file, err := parser.ParseFile(fset, "codes.go", nil, parser.ParseComments) if err != nil { log.Fatalf("ParseFile failed: %s", err) } conf := Config{Importer: importer.Default()} info := &Info{ Types: make(map[ast.Expr]TypeAndValue), Defs: make(map[*ast.Ident]Object), Uses: make(map[*ast.Ident]Object), } _, err = conf.Check("types", fset, []*ast.File{file}, info) if err != nil { log.Fatalf("Check failed: %s", err) } for _, decl := range file.Decls { decl, ok := decl.(*ast.GenDecl) if !ok || decl.Tok != token.CONST { continue } for _, spec := range decl.Specs { spec, ok := spec.(*ast.ValueSpec) if !ok || len(spec.Names) == 0 { continue } obj := info.ObjectOf(spec.Names[0]) if named, ok := obj.Type().(*Named); ok && named.Obj().Name() == "Code" { if len(spec.Names) != 1 { log.Fatalf("bad Code declaration for %q: got %d names, want exactly 1", spec.Names[0].Name, len(spec.Names)) } codename := spec.Names[0].Name f(codename, spec) } } } } const markdownTemplate = `--- title: {{.Name}} layout: article --- <!-- Copyright 2023 The Go Authors. All rights reserved. Use of this source code is governed by a BSD-style license that can be found in the LICENSE file. --> <!-- Code generated by generrordocs.go; DO NOT EDIT. --> {{.Description}} `