-
Notifications
You must be signed in to change notification settings - Fork 7
/
project.go
128 lines (115 loc) · 2.65 KB
/
project.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
127
128
package main
import (
"context"
"fmt"
"go/ast"
"go/doc"
"go/token"
"path"
"path/filepath"
"strings"
"text/template"
"golang.org/x/tools/go/packages"
)
func Packages(ctx context.Context, project string) (*token.FileSet, []*packages.Package, error) {
cfg := &packages.Config{
Context: ctx,
Dir: project,
Tests: true,
Mode: packages.NeedName | packages.NeedFiles | packages.NeedSyntax,
Fset: token.NewFileSet(),
}
ps, err := packages.Load(cfg, "./...")
return cfg.Fset, ps, err
}
type info struct {
pkg, test *packages.Package
doc *doc.Package
examples []*doc.Example
externalExamples []*doc.Example
dir string
data any
oldReadme []byte
template *template.Template
}
func PairPackagesWithXTests(in []*packages.Package) map[string]*info {
m := map[string]*info{}
for _, pkg := range in {
// synthetic package for code generated by test runner
if strings.HasSuffix(pkg.PkgPath, ".test") {
continue
}
path := pkg.PkgPath
test := strings.HasSuffix(pkg.Name, "_test")
if test {
path = path[:len(path)-len("_test")]
}
p, ok := m[path]
if !ok {
p = &info{}
}
if !test {
p.pkg = pkg
} else {
p.test = pkg
}
m[pkg.PkgPath] = p
}
return m
}
func CollectProjectErrors(in map[string]*info) []error {
var acc []error
extend := func(errs []packages.Error) {
for _, err := range errs {
acc = append(acc, err)
}
}
for k, p := range in {
if p.pkg == nil {
acc = append(acc, fmt.Errorf("%s only has external test files, cannot process", k))
} else {
extend(p.pkg.Errors)
}
if p.test != nil {
extend(p.test.Errors)
}
}
return acc
}
func ProcessPackageDir(fset *token.FileSet, p *info, defaultTemplate *template.Template) error {
var goFiles, testFiles []*ast.File
for _, v := range p.pkg.Syntax {
if strings.HasSuffix(fset.Position(v.FileStart).Filename, "_test.go") {
testFiles = append(testFiles, v)
} else {
goFiles = append(goFiles, v)
}
}
var err error
p.doc, err = doc.NewFromFiles(fset, goFiles, p.pkg.PkgPath, doc.PreserveAST)
if err != nil {
return err
}
if len(testFiles) > 0 {
p.examples = doc.Examples(testFiles...)
}
if p.test != nil {
p.externalExamples = doc.Examples(p.test.Syntax...)
}
// One day there may be a p.pkg.Dir but alas not today
p.dir = filepath.FromSlash(path.Dir(p.pkg.GoFiles[0]))
p.data, err = DirData(p.dir)
if err != nil {
return err
}
templateSrc, err := DirTemplate(p.dir)
if err != nil {
return err
}
p.template, err = parseTemplateOr(templateSrc, defaultTemplate)
if err != nil {
return err
}
p.oldReadme, err = DirReadme(p.dir)
return err
}