-
Notifications
You must be signed in to change notification settings - Fork 9
/
gotestfmt.go
119 lines (102 loc) · 3.05 KB
/
gotestfmt.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
package gotestfmt
import (
"embed"
"fmt"
"io"
"os"
"path"
"github.com/gotesttools/gotestfmt/v2/parser"
"github.com/gotesttools/gotestfmt/v2/renderer"
"github.com/gotesttools/gotestfmt/v2/tokenizer"
)
//go:embed .gotestfmt/*.gotpl
//go:embed .gotestfmt/*/*.gotpl
var fs embed.FS
func New(
templateRoot string,
templateDirs []string,
) (CombinedExitCode, error) {
downloadsTpl := findTemplate(templateRoot, templateDirs, "downloads.gotpl")
packageTpl := findTemplate(templateRoot, templateDirs, "package.gotpl")
return &goTestFmt{
downloadsTpl: downloadsTpl,
packageTpl: packageTpl,
}, nil
}
func findTemplate(root string, dirs []string, tpl string) []byte {
var lastError error
for _, dir := range dirs {
templateContents, err := os.ReadFile(path.Join(root, dir, tpl))
if err == nil {
return templateContents
}
lastError = err
}
for _, dir := range dirs {
templateContents, err := fs.ReadFile(path.Join("./.gotestfmt", dir, tpl))
if err == nil {
return templateContents
}
lastError = err
}
panic(fmt.Errorf("bug: %s not found in binary (%w)", tpl, lastError))
}
// Combined is an interface that combines both the classic GoTestFmt interface and the Formatter interface.
//
//goland:noinspection GoDeprecation
type Combined interface {
GoTestFmt
Formatter
}
// CombinedExitCode contains Combined and adds a function to format with exit code.
type CombinedExitCode interface {
Combined
FormatterExitCode
}
// GoTestFmt implements the classic Format instruction. This is no longer in use.
//
// Deprecated: please use the Formatter interface instead.
//
//goland:noinspection GoDeprecation
type GoTestFmt interface {
Format(input io.Reader, target io.WriteCloser)
}
// Formatter contains an extended format function to accept render settings.
type Formatter interface {
FormatWithConfig(input io.Reader, target io.WriteCloser, cfg renderer.RenderSettings)
}
// FormatterExitCode contains an extended format function to accept render settings and returns an exit code
type FormatterExitCode interface {
FormatWithConfigAndExitCode(input io.Reader, target io.WriteCloser, cfg renderer.RenderSettings) int
}
type goTestFmt struct {
packageTpl []byte
downloadsTpl []byte
}
func (g *goTestFmt) Format(input io.Reader, target io.WriteCloser) {
g.FormatWithConfigAndExitCode(input, target, renderer.RenderSettings{})
}
func (g *goTestFmt) FormatWithConfig(input io.Reader, target io.WriteCloser, cfg renderer.RenderSettings) {
_ = g.FormatWithConfigAndExitCode(input, target, cfg)
}
func (g *goTestFmt) FormatWithConfigAndExitCode(input io.Reader, target io.WriteCloser, cfg renderer.RenderSettings) int {
tokenizerOutput := tokenizer.Tokenize(input)
prefixes, downloads, packages := parser.Parse(tokenizerOutput)
result, exitCodeChan := renderer.RenderWithSettingsAndExitCode(
prefixes,
downloads,
packages,
g.downloadsTpl,
g.packageTpl,
cfg,
)
for {
fragment, ok := <-result
if !ok {
return <-exitCodeChan
}
if _, err := target.Write(fragment); err != nil {
panic(fmt.Errorf("failed to write to output: %w", err))
}
}
}