-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathrun.go
149 lines (118 loc) · 3.2 KB
/
run.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
package sts
import (
"errors"
"fmt"
"path/filepath"
"strings"
"golang.org/x/tools/imports"
)
var (
format = `format is "/path/to/file.go:struct_name"`
ErrIncorectSourceParam = errors.New(`incorrect source, ` + format)
ErrIncorectDestParam = errors.New(`incorrect destination, ` + format)
)
// split splits string by ":" into two parts.
func split(s string) (string, string) {
parts := strings.Split(s, ":")
if len(parts) != 2 {
return "", ""
}
return parts[0], parts[1]
}
// pkgFromPath returns package name as last elements from path.
func pkgFromPath(p string) string {
s := strings.Split(p, "/")
return s[len(s)-1]
}
// Tags to inspect:
// * sts
// * custom
func Run(
// source and destination structures in format <path/to/*.go file>:<structure>
src, dst string,
sourceTag string, // Tag on source structure.
validDstTags string, // Comma-separated list of tags on destination structure.
outputDir string,
hpkg string, // Package name with helper functions.
version string, // App version.
debug bool, // If true, add debug info to output file.
cfgmap *FieldConfig, // field map from yaml config
) (string, []byte, error) {
sf, ssn := split(src)
if sf == "" || ssn == "" {
return "", nil, ErrIncorectSourceParam
}
df, dsn := split(dst)
if df == "" || dsn == "" {
return "", nil, ErrIncorectDestParam
}
parsedSrc, err := Parse(sf, []string{sourceTag})
if err != nil {
return "", nil, err
}
ss, ok := parsedSrc.Structs[ssn]
if !ok {
return "", nil, fmt.Errorf("source structure %q not found: ", ssn)
}
vt := strings.Split(validDstTags, ",")
parsedDst, err := Parse(df, vt)
if err != nil {
return "", nil, err
}
ds, ok := parsedDst.Structs[dsn]
if !ok {
return "", nil, fmt.Errorf("destination structure %q not found: ", dsn)
}
abs, err := filepath.Abs(outputDir)
if err != nil {
return "", nil, err
}
opkg := pkgFromPath(abs)
// do not use package name for structures when destination package is the
// same as output one.
srcp, dstp := parsedSrc.Package, parsedDst.Package
if srcp == opkg {
srcp = ""
dstp = ""
}
linkedFields, err := link(ss, ds, sourceTag, vt, cfgmap)
if err != nil {
return "", nil, err
}
ff := newTemplate(ssn, dsn, srcp, dstp, linkedFields)
fmt.Fprintf(ff, "// Code generated by sts v%s. DO NOT EDIT.\n\npackage %s\n\n", version, opkg)
err = ff.Print(false, debug, hpkg)
if err != nil {
return "", nil, err
}
err = ff.Print(true, debug, hpkg)
if err != nil {
return "", nil, err
}
ff.PrintWithBothPointers(false)
ff.PrintWithBothPointers(true)
//=====
// List of values on the left => list of value on the right
ff.PrintList(false, false, false)
ff.PrintList(true, false, false)
ff.PrintList(false, false, true)
ff.PrintList(true, false, true)
ff.PrintList(false, true, false)
ff.PrintList(true, true, false)
ff.PrintList(false, true, true)
ff.PrintList(true, true, true)
ic, err := imports.Process("output.go", ff.Bytes(), nil)
if err != nil {
return "", nil, err
}
ff.Reset()
ff.Write(ic)
if ssn == dsn {
ssn = srcp + "_" + ssn
dsn = dstp + "_" + dsn
}
ofile := filepath.Join(
outputDir, strings.ToLower(fmt.Sprintf("%s_to_%s.sts.go", ssn, dsn)),
)
return ofile, ff.Bytes(), nil
}