-
Notifications
You must be signed in to change notification settings - Fork 1
/
main.go
126 lines (100 loc) · 2.62 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"fmt"
"log"
"os"
"path"
"path/filepath"
"sort"
"strings"
"github.com/dave/jennifer/jen"
"github.com/diamondburned/cchat/cmd/internal/cchat-generator/genutils"
"github.com/diamondburned/cchat/repository"
)
const OutputDir = "."
func init() {
log.SetFlags(0)
}
var comment = repository.Comment{Raw: `
Package empty provides no-op asserter method implementations of interfaces
in cchat's root and text packages.
`}
type Package struct {
Path string
repository.Package
}
func main() {
gen := genutils.NewFile("empty")
gen.PackageComment(comment.GoString(1))
// Sort.
var packages = make([]Package, 0, len(repository.Main))
for pkgpath, pk := range repository.Main {
packages = append(packages, Package{
Path: pkgpath,
Package: pk,
})
}
sort.Slice(packages, func(i, j int) bool {
return packages[i].Path < packages[j].Path
})
for _, pkg := range packages {
gen.ImportName(pkg.Path, path.Base(pkg.Path))
for _, iface := range pkg.Interfaces {
// Skip structs without asserter methods.
if !hasAsserter(iface) {
continue
}
var ifaceName = newIfaceName(pkg.Path, iface)
gen.Commentf("%[1]s provides no-op asserters for cchat.%[1]s.", ifaceName)
gen.Type().Id(ifaceName).Struct()
gen.Line()
for _, embed := range iface.Embeds {
if iface := pkg.Interface(embed.InterfaceName); iface != nil {
genIfaceMethods(gen, *iface, ifaceName, pkg.Path)
}
}
genIfaceMethods(gen, iface, ifaceName, pkg.Path)
gen.Line()
}
}
f, err := os.Create(filepath.Join(os.Args[1], "empty.go"))
if err != nil {
log.Fatalln("Failed to create output file:", err)
}
defer f.Close()
if err := gen.Render(f); err != nil {
log.Fatalln("Failed to render output:", err)
}
}
func newIfaceName(pkgpath string, iface repository.Interface) string {
if pkgpath == repository.RootPath {
return iface.Name
} else {
return strings.Title(repository.TrimRoot(pkgpath)) + iface.Name
}
}
func genIfaceMethods(gen *jen.File, iface repository.Interface, ifaceName, pkgpath string) {
for _, method := range iface.Methods {
am, ok := method.(repository.AsserterMethod)
if !ok {
continue
}
name := fmt.Sprintf("As%s", am.ChildType)
gen.Comment(fmt.Sprintf("%s returns nil.", name))
stmt := jen.Func()
stmt.Parens(jen.Id(ifaceName))
stmt.Id(name)
stmt.Params()
stmt.Add(genutils.GenerateExternType(pkgpath, am))
stmt.Values(jen.Return(jen.Nil()))
gen.Add(stmt)
}
}
func hasAsserter(iface repository.Interface) bool {
for _, method := range iface.Methods {
if _, isA := method.(repository.AsserterMethod); isA {
return true
}
}
return false
}