github.com/jingcheng-WU/gonum@v0.9.1-0.20210323123734-f1a2a11a8f7b/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  // +build ignore
     6  
     7  package main
     8  
     9  import (
    10  	"bytes"
    11  	"go/ast"
    12  	"go/format"
    13  	"go/parser"
    14  	"go/token"
    15  	"io/ioutil"
    16  	"log"
    17  	"os"
    18  	"path/filepath"
    19  	"strings"
    20  	"text/template"
    21  )
    22  
    23  const definedTemplate = `// Code generated by "go generate github.com/jingcheng-WU/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  // +build ignore
    30  
    31  package main
    32  
    33  import "github.com/jingcheng-WU/gonum/unit"
    34  
    35  var definedTypes = []struct{
    36  	unit unit.Uniter
    37  	name string
    38  }{
    39  {{range .}}	{unit: unit.{{.}}(1), name: "unit.{{.}}"{{"}"}},
    40  {{end}}}
    41  
    42  func definedEquivalentOf(q unit.Uniter) string {
    43  	for _, u := range definedTypes {
    44  		if unit.DimensionsMatch(q, u.unit) {
    45  			return u.name
    46  		}
    47  	}
    48  	return ""
    49  }
    50  `
    51  
    52  var defined = template.Must(template.New("defined").Parse(definedTemplate))
    53  
    54  func main() {
    55  	names, err := filepath.Glob("../*.go")
    56  	if err != nil {
    57  		log.Fatal(err)
    58  	}
    59  
    60  	var units []string
    61  	fset := token.NewFileSet()
    62  	for _, fn := range names {
    63  		if strings.Contains(fn, "_test") {
    64  			continue
    65  		}
    66  		b, err := ioutil.ReadFile(fn)
    67  		if bytes.Contains(b, []byte("+build ignore")) {
    68  			continue
    69  		}
    70  		f, err := parser.ParseFile(fset, fn, nil, 0)
    71  		if err != nil {
    72  			log.Fatal("failed to parse %q: %v", fn, err) // parse error
    73  		}
    74  		if f.Name.Name != "unit" {
    75  			log.Fatalf("not parsing unit package: %q", f.Name.Name)
    76  		}
    77  		for _, d := range f.Decls {
    78  			if decl, ok := d.(*ast.GenDecl); ok {
    79  				for _, s := range decl.Specs {
    80  					if ts, ok := s.(*ast.TypeSpec); ok {
    81  						if id, ok := ts.Type.(*ast.Ident); !ok || id.Name != "float64" {
    82  							continue
    83  						}
    84  						units = append(units, ts.Name.Name)
    85  					}
    86  				}
    87  			}
    88  		}
    89  	}
    90  
    91  	f, err := os.Create("defined_types.go")
    92  	if err != nil {
    93  		log.Fatal(err)
    94  	}
    95  	defer f.Close()
    96  
    97  	var buf bytes.Buffer
    98  	err = defined.Execute(&buf, units)
    99  	if err != nil {
   100  		log.Fatal(err)
   101  	}
   102  
   103  	b, err := format.Source(buf.Bytes())
   104  	if err != nil {
   105  		f.Write(buf.Bytes()) // This is here to debug bad format.
   106  		log.Fatalf("error formatting %q: %s", f.Name(), err)
   107  	}
   108  
   109  	f.Write(b)
   110  }