treerack/scripts/createhead.go

145 lines
2.7 KiB
Go
Raw Permalink Normal View History

2018-01-05 19:06:10 +01:00
package main
import (
"bytes"
"flag"
"fmt"
2025-08-20 03:22:39 +02:00
"github.com/iancoleman/strcase"
2018-01-05 19:06:10 +01:00
"go/ast"
"go/parser"
"go/printer"
"go/token"
"io"
"log"
"os"
2025-08-20 03:22:39 +02:00
"regexp"
2018-01-05 19:06:10 +01:00
"strconv"
"strings"
)
2025-08-20 03:22:39 +02:00
var exportedSymbols = []string{
"ErrInvalidUnicodeCharacter",
"CommitType",
"None",
"Alias",
"Whitespace",
"NoWhitespace",
"Keyword",
"NoKeyword",
"FailPass",
"Root",
"Node",
"ParseError",
}
func unexporter() map[string]*regexp.Regexp {
m := make(map[string]*regexp.Regexp)
for _, name := range exportedSymbols {
m[name] = regexp.MustCompile(fmt.Sprintf("\\b%s\\b", name))
}
return m
}
func concatGo(w io.Writer, exported bool, r ...io.Reader) error {
2018-01-05 19:06:10 +01:00
var others []ast.Decl
imports := &ast.GenDecl{
Tok: token.IMPORT,
Lparen: 1,
Rparen: 1,
}
importPaths := make(map[string]bool)
for i := range r {
f, err := parser.ParseFile(token.NewFileSet(), "", r[i], 0)
if err != nil {
return err
}
for j := range f.Decls {
d := f.Decls[j]
switch dd := d.(type) {
case *ast.GenDecl:
if dd.Tok != token.IMPORT {
others = append(others, d)
continue
}
for k := range dd.Specs {
i := dd.Specs[k].(*ast.ImportSpec)
path := i.Path.Value
name := ""
if i.Name != nil {
name = i.Name.Name
}
key := "(" + name + ")" + path
if importPaths[key] {
continue
}
importPaths[key] = true
imports.Specs = append(imports.Specs, i)
}
default:
others = append(others, d)
}
}
}
return printer.Fprint(w, token.NewFileSet(), &ast.File{
Name: &ast.Ident{Name: ""},
Decls: append([]ast.Decl{imports}, others...),
})
}
func removePackage(gO string) string {
// so we know that it's the first line
nl := strings.Index(gO, "\n")
return gO[nl+2:]
}
func main() {
2025-08-20 03:22:39 +02:00
var (
packageName string
exported bool
)
2018-01-05 19:06:10 +01:00
flag.StringVar(&packageName, "package", "treerack", "package name of the generated code file")
2025-08-20 03:22:39 +02:00
flag.BoolVar(&exported, "exported", false, "export required symbols")
2018-01-05 19:06:10 +01:00
flag.Parse()
var files []io.Reader
for _, fn := range flag.Args() {
f, err := os.Open(fn)
if err != nil {
log.Fatalln(err)
}
defer f.Close()
files = append(files, f)
}
var headCode bytes.Buffer
2025-08-20 03:22:39 +02:00
if err := concatGo(&headCode, exported, files...); err != nil {
2018-01-05 19:06:10 +01:00
log.Fatalln(err)
}
code := headCode.String()
code = removePackage(code)
2025-08-20 03:22:39 +02:00
if !exported {
unexp := unexporter()
for name, exp := range unexp {
code = exp.ReplaceAllString(code, strcase.ToLowerCamel(name))
}
}
2018-01-05 19:06:10 +01:00
quotedCode := strconv.Quote(code)
2025-08-20 03:22:39 +02:00
varName := "headCode"
if exported {
varName = "headCodeExported"
}
2018-01-05 19:06:10 +01:00
2025-08-20 03:22:39 +02:00
fmt.Printf("package %s\n\n// generated with scripts/createhead.go\nconst %s=%s", packageName, varName, quotedCode)
2018-01-05 19:06:10 +01:00
}