Skip to content

Commit dbb4edb

Browse files
authored
Merge pull request #181 from applejag/feature/infer-package-name
Infer output:package from output:file
2 parents 2d7ce60 + 376138a commit dbb4edb

20 files changed

+322
-44
lines changed

config/config.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ type Raw struct {
3535
}
3636

3737
type context struct {
38-
Loader *pkgload.PackageLoader
39-
38+
Loader *pkgload.PackageLoader
39+
WorkDir string
4040
EnumTransformers map[string]enum.Transformer
4141
}
4242

@@ -46,7 +46,7 @@ func Parse(raw *Raw) ([]*Converter, error) {
4646
return nil, err
4747
}
4848

49-
ctx := &context{Loader: loader, EnumTransformers: raw.EnumTransformers}
49+
ctx := &context{Loader: loader, EnumTransformers: raw.EnumTransformers, WorkDir: raw.WorkDir}
5050

5151
converters := []*Converter{}
5252
for _, rawConverter := range raw.Converters {

config/converter.go

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import (
1313
)
1414

1515
const (
16-
configExtend = "extend"
16+
configExtend = "extend"
17+
configOutputFile = "output:file"
1718
)
1819

1920
type Format string
@@ -29,10 +30,9 @@ var DefaultCommon = Common{
2930
}
3031

3132
var DefaultConfigInterface = ConverterConfig{
32-
OutputFile: "./generated/generated.go",
33-
OutputPackageName: "generated",
34-
Common: DefaultCommon,
35-
OutputFormat: FormatStruct,
33+
OutputFile: "./generated/generated.go",
34+
Common: DefaultCommon,
35+
OutputFormat: FormatStruct,
3636
}
3737

3838
var DefaultConfigVariables = ConverterConfig{
@@ -109,10 +109,33 @@ func parseConverter(ctx *context, rawConverter *RawConverter, global RawLines) (
109109
return nil, err
110110
}
111111

112+
resolveOutputPackage(ctx, c)
113+
112114
err = parseMethods(ctx, rawConverter, c)
113115
return c, err
114116
}
115117

118+
func resolveOutputPackage(ctx *context, c *Converter) {
119+
targetPackage, err := resolvePackage(c.FileName, c.Package, c.OutputFile)
120+
if err != nil {
121+
return
122+
}
123+
124+
if c.OutputPackagePath == "" {
125+
c.OutputPackagePath = targetPackage
126+
}
127+
128+
pkg := ctx.Loader.GetUncheckedPkg(targetPackage)
129+
130+
if pkg == nil {
131+
return
132+
}
133+
134+
if c.OutputPackageName == "" {
135+
c.OutputPackageName = pkg.Types.Name()
136+
}
137+
}
138+
116139
func initConverter(loader *pkgload.PackageLoader, rawConverter *RawConverter) (*Converter, error) {
117140
c := &Converter{
118141
FileName: rawConverter.FileName,
@@ -161,8 +184,8 @@ func parseConverterLine(ctx *context, c *Converter, value string) (err error) {
161184
c.Name, err = parse.String(rest)
162185
case "output:raw":
163186
c.OutputRaw = append(c.OutputRaw, rest)
164-
case "output:file":
165-
c.OutputFile, err = parse.String(rest)
187+
case configOutputFile:
188+
c.OutputFile, err = parse.File(ctx.WorkDir, rest)
166189
case "output:format":
167190
if len(c.Extend) != 0 {
168191
return fmt.Errorf("Cannot change output:format after extend functions have been added.\nMove the extend below the output:format setting.")

config/package.go

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,37 @@
11
package config
22

33
import (
4+
"path/filepath"
45
"strings"
56

67
"github.com/jmattheis/goverter/config/parse"
78
"github.com/jmattheis/goverter/pkgload"
89
)
910

11+
func resolvePackage(sourceFileName, sourcePackage, targetFile string) (string, error) {
12+
relativeFile := targetFile
13+
if filepath.IsAbs(targetFile) {
14+
var err error
15+
relativeFile, err = filepath.Rel(filepath.Dir(sourceFileName), targetFile)
16+
if err != nil {
17+
return "", err
18+
}
19+
}
20+
21+
return filepath.Dir(filepath.Join(sourcePackage, relativeFile)), nil
22+
}
23+
1024
func getPackages(raw *Raw) []string {
1125
lookup := map[string]struct{}{}
1226
for _, c := range raw.Converters {
1327
lookup[c.PackagePath] = struct{}{}
14-
registerConverterLines(lookup, c.PackagePath, c.Converter)
15-
registerConverterLines(lookup, c.PackagePath, raw.Global)
28+
29+
// the default output:file is in ./generated and is not configured in Raw.
30+
// This preemptively loads this package, in case it already exists.
31+
lookup[filepath.Join(c.PackagePath, "generated")] = struct{}{}
32+
33+
registerConverterLines(lookup, raw.WorkDir, c.FileName, c.PackagePath, c.Converter)
34+
registerConverterLines(lookup, raw.WorkDir, c.FileName, c.PackagePath, raw.Global)
1635
for _, m := range c.Methods {
1736
registerMethodLines(lookup, c.PackagePath, m)
1837
}
@@ -26,33 +45,44 @@ func getPackages(raw *Raw) []string {
2645
return pkgs
2746
}
2847

29-
func registerConverterLines(lookup map[string]struct{}, cwd string, lines RawLines) {
48+
func registerConverterLines(lookup map[string]struct{}, cwd, filename, sourcePackage string, lines RawLines) {
3049
for _, line := range lines.Lines {
3150
cmd, rest := parse.Command(line)
32-
if cmd == configExtend {
51+
switch cmd {
52+
case configExtend:
3353
for _, fullMethod := range strings.Fields(rest) {
34-
registerFullMethod(lookup, cwd, fullMethod)
54+
registerFullMethod(lookup, sourcePackage, fullMethod)
55+
}
56+
case configOutputFile:
57+
file, err := parse.File(cwd, rest)
58+
if err != nil {
59+
continue
60+
}
61+
targetPackage, err := resolvePackage(filename, sourcePackage, file)
62+
if err != nil {
63+
continue
3564
}
65+
lookup[targetPackage] = struct{}{}
3666
}
3767
}
3868
}
3969

40-
func registerMethodLines(lookup map[string]struct{}, cwd string, lines RawLines) {
70+
func registerMethodLines(lookup map[string]struct{}, sourcePackage string, lines RawLines) {
4171
for _, line := range lines.Lines {
4272
cmd, rest := parse.Command(line)
4373
switch cmd {
4474
case configMap:
4575
if _, _, custom, err := parseMethodMap(rest); err == nil && custom != "" {
46-
registerFullMethod(lookup, cwd, custom)
76+
registerFullMethod(lookup, sourcePackage, custom)
4777
}
4878
case configDefault:
49-
registerFullMethod(lookup, cwd, rest)
79+
registerFullMethod(lookup, sourcePackage, rest)
5080
}
5181
}
5282
}
5383

54-
func registerFullMethod(lookup map[string]struct{}, cwd, fullMethod string) {
55-
pkg, _, err := pkgload.ParseMethodString(cwd, fullMethod)
84+
func registerFullMethod(lookup map[string]struct{}, sourcePackage, fullMethod string) {
85+
pkg, _, err := pkgload.ParseMethodString(sourcePackage, fullMethod)
5686
if err == nil {
5787
lookup[pkg] = struct{}{}
5888
}

config/parse/file.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package parse
2+
3+
import (
4+
"path/filepath"
5+
"strings"
6+
)
7+
8+
func File(cwd, rest string) (string, error) {
9+
field, err := String(rest)
10+
if err != nil {
11+
return field, err
12+
}
13+
14+
if strings.HasPrefix(field, "@cwd/") {
15+
return filepath.Abs(filepath.Join(cwd, strings.TrimPrefix(field, "@cwd/")))
16+
}
17+
return field, nil
18+
}

docs/changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import GH from './GH.vue';
99
- Fix go1.24 support. <GH issue="186" pr="187"/>
1010
- Increase minimal go version to go1.22 due to breaking changes in x/tools for
1111
go1.24 <GH pr="187"/>
12+
- Infer [`output:package`](./reference/output.md) from file location
13+
<GH issue="180" pr="181"/>
1214

1315
## v1.7.0
1416

docs/guide/output-same-package.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ interface you can follow these steps:
66
## Configure generation
77

88
Configure [`output`](../reference/output.md) to output the file into the same
9-
directory, define the full package path, and then run [`goverter
10-
gen`](../reference/cli.md).
9+
directory, and then run [`goverter gen`](../reference/cli.md).
1110

1211
::: code-group
1312
<<< @../../example/samepackage/input.go

docs/reference/output.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,11 @@ Default is `:generated`.
7878

7979
### output:package PACKAGE
8080

81-
This is the recommended way to define this setting. If you define the full
82-
package path, goverter is able to prevent edge-cases in the converter
83-
generation. The package name used in the generated `.go` file will be inferred
84-
from the normalized full package path. E.g.
81+
Goverter will infer the package path from `output:file` if it's outputted in
82+
the same go module, but you can override it with this setting. The full package
83+
path is needed is able to prevent edge-cases in the converter generation. If
84+
there is already a package name defined in the package, then it's used
85+
otherwise it will be infered from the full normalized package path. E.g.
8586

8687
```go
8788
// goverter:converter

example/samepackage/input.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package samepackage
22

33
// goverter:converter
44
// goverter:output:file ./generated.go
5-
// goverter:output:package github.com/jmattheis/goverter/example/samepackage
65
type Converter interface {
76
Convert(source *Input) *Output
87
}

generator/filemanager.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"bytes"
55
"fmt"
66
"path/filepath"
7-
"strings"
87

98
"github.com/dave/jennifer/jen"
109
"github.com/jmattheis/goverter/config"
@@ -23,7 +22,7 @@ type managedFile struct {
2322
}
2423

2524
func (m *fileManager) Get(conv *config.Converter, cfg Config) (*jen.File, *namer.Namer, error) {
26-
output := getOutputDir(conv, cfg.WorkingDir)
25+
output := getOutputDir(conv)
2726

2827
f, ok := m.Files[output]
2928
if !ok {
@@ -66,11 +65,7 @@ func (m *fileManager) renderFiles() (map[string][]byte, error) {
6665
return result, nil
6766
}
6867

69-
func getOutputDir(c *config.Converter, cwd string) string {
70-
if strings.HasPrefix(c.OutputFile, "@cwd/") {
71-
return filepath.Join(cwd, strings.TrimPrefix(c.OutputFile, "@cwd/"))
72-
}
73-
68+
func getOutputDir(c *config.Converter) string {
7469
if filepath.IsAbs(c.OutputFile) {
7570
return c.OutputFile
7671
}

generator/generate.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99

1010
// Config the generate config.
1111
type Config struct {
12-
WorkingDir string
1312
BuildConstraint string
1413
}
1514

0 commit comments

Comments
 (0)