github.com/gopherd/gonum@v0.0.4/unit/constant/generate_defined_types.go (about)

     1  // Copyright ©2019 The Gonum Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build ignore
     6  // +build ignore
     7  
     8  package main
     9  
    10  import (
    11  	"bytes"
    12  	"go/ast"
    13  	"go/format"
    14  	"go/parser"
    15  	"go/token"
    16  	"log"
    17  	"os"
    18  	"path/filepath"
    19  	"strings"
    20  	"text/template"
    21  )
    22  
    23  const definedTemplate = `// Code generated by "go generate github.com/gopherd/gonum/unit/constant”; DO NOT EDIT.
    24  
    25  // Copyright ©2019 The Gonum Authors. All rights reserved.
    26  // Use of this source code is governed by a BSD-style
    27  // license that can be found in the LICENSE file.
    28  
    29  //go:build ignore
    30  // +build ignore
    31  
    32  package main
    33  
    34  import "github.com/gopherd/gonum/unit"
    35  
    36  var definedTypes = []struct{
    37  	unit unit.Uniter
    38  	name string
    39  }{
    40  {{range .}}	{unit: unit.{{.}}(1), name: "unit.{{.}}"{{"}"}},
    41  {{end}}}
    42  
    43  func definedEquivalentOf(q unit.Uniter) string {
    44  	for _, u := range definedTypes {
    45  		if unit.DimensionsMatch(q, u.unit) {
    46  			return u.name
    47  		}
    48  	}
    49  	return ""
    50  }
    51  `
    52  
    53  var defined = template.Must(template.New("defined").Parse(definedTemplate))
    54  
    55  func main() {
    56  	names, err := filepath.Glob("../*.go")
    57  	if err != nil {
    58  		log.Fatal(err)
    59  	}
    60  
    61  	var units []string
    62  	fset := token.NewFileSet()
    63  	for _, fn := range names {
    64  		if strings.Contains(fn, "_test") {
    65  			continue
    66  		}
    67  		b, err := os.ReadFile(fn)
    68  		if bytes.Contains(b, []byte("+build ignore")) {
    69  			continue
    70  		}
    71  		f, err := parser.ParseFile(fset, fn, nil, 0)
    72  		if err != nil {
    73  			log.Fatal("failed to parse %q: %v", fn, err) // parse error
    74  		}
    75  		if f.Name.Name != "unit" {
    76  			log.Fatalf("not parsing unit package: %q", f.Name.Name)
    77  		}
    78  		for _, d := range f.Decls {
    79  			if decl, ok := d.(*ast.GenDecl); ok {
    80  				for _, s := range decl.Specs {
    81  					if ts, ok := s.(*ast.TypeSpec); ok {
    82  						if id, ok := ts.Type.(*ast.Ident); !ok || id.Name != "float64" {
    83  							continue
    84  						}
    85  						units = append(units, ts.Name.Name)
    86  					}
    87  				}
    88  			}
    89  		}
    90  	}
    91  
    92  	f, err := os.Create("defined_types.go")
    93  	if err != nil {
    94  		log.Fatal(err)
    95  	}
    96  	defer f.Close()
    97  
    98  	var buf bytes.Buffer
    99  	err = defined.Execute(&buf, units)
   100  	if err != nil {
   101  		log.Fatal(err)
   102  	}
   103  
   104  	b, err := format.Source(buf.Bytes())
   105  	if err != nil {
   106  		f.Write(buf.Bytes()) // This is here to debug bad format.
   107  		log.Fatalf("error formatting %q: %s", f.Name(), err)
   108  	}
   109  
   110  	f.Write(b)
   111  }