Skip to content

Commit ad72616

Browse files
authored
Merge pull request #25 from arran4/Custom
Custom output per type
2 parents 4d67dcd + fa88827 commit ad72616

File tree

8 files changed

+229
-5
lines changed

8 files changed

+229
-5
lines changed

.gitignore

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
*.txt
2-
*.pprof
3-
cmap2/
4-
cache/
5-
debug
1+
/*.txt
2+
/*.pprof
3+
/cmap2/
4+
/cache/
5+
/debug
6+
/testdata/testmodel1/s2ts_gen_*.go
67
/helpers.js

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,18 @@ Args:
131131
132132
```
133133

134+
## Advanced
135+
136+
### Custom output per model
137+
138+
```golang
139+
type CustomTypescript interface {
140+
RenderCustomTypescript(w io.Writer) (err error)
141+
}
142+
```
143+
If your model implements a ```RenderCustomTypescript(w io.Writer) (err error)``` function it will inject what ever you
144+
write to the writer at the end of the model. struct2ts will handle the first level of indenting for you.
145+
134146
## TODO
135147

136148
* Use [xast](https://github.com/OneOfOne/xast) to skip reflection.

go.sum

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc h1:cAKDfWh5Vpd
22
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
33
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf h1:qet1QNfXsQxTZqLG4oE62mJzwPIB8+Tee4RNCL9ulrY=
44
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
5+
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
56
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
7+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
68
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
79
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
10+
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
811
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
912
golang.org/x/tools v0.0.0-20190213135902-6bedcd10978a h1:ncPOGSo3avrTTUKHvDmwoS5E5of95qqNwftSXoxX+Wk=
1013
golang.org/x/tools v0.0.0-20190213135902-6bedcd10978a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

struct.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package struct2ts
22

33
import (
4+
"errors"
45
"fmt"
56
"io"
67
"reflect"
@@ -57,10 +58,52 @@ func (s *Struct) RenderTo(opts *Options, w io.Writer) (err error) {
5758
return
5859
}
5960

61+
if err = s.RenderCustom(opts, w); err != nil {
62+
return
63+
}
64+
6065
_, err = fmt.Fprint(w, "}")
6166
return
6267
}
6368

69+
type CustomTypescript interface {
70+
RenderCustomTypescript(w io.Writer) (err error)
71+
}
72+
73+
func (s *Struct) RenderCustom(opts *Options, w io.Writer) (err error) {
74+
ww := newTabScanner(w, opts.indents[1])
75+
ctit := reflect.TypeOf((*CustomTypescript)(nil)).Elem()
76+
var implementingType reflect.Type = nil
77+
if s.t.Implements(ctit) {
78+
implementingType = ctit
79+
}
80+
if reflect.PtrTo(s.t).Implements(ctit) {
81+
implementingType = reflect.PtrTo(s.t)
82+
}
83+
if implementingType != nil {
84+
m, ok := implementingType.MethodByName("RenderCustomTypescript")
85+
if !ok {
86+
return errors.New("couldn't get method RenderCustomTypescript")
87+
}
88+
_, err = fmt.Fprintf(ww, "\n")
89+
o := reflect.New(s.t)
90+
if implementingType.Kind() != reflect.Ptr {
91+
o = o.Elem()
92+
}
93+
wv := reflect.ValueOf(ww)
94+
r := m.Func.Call([]reflect.Value{o, wv})
95+
if len(r) > 0 && !r[0].IsNil() {
96+
switch r0t := r[0].Interface().(type) {
97+
case error:
98+
return r0t
99+
}
100+
}
101+
_, err = fmt.Fprintf(w, "\n")
102+
}
103+
104+
return
105+
}
106+
64107
func (s *Struct) RenderFields(opts *Options, w io.Writer) (err error) {
65108
for _, f := range s.Fields {
66109
if err = f.RenderTopLevel(w, opts); err != nil {

tabscanner.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package struct2ts
2+
3+
import "io"
4+
5+
type tabScanner struct {
6+
output io.Writer
7+
tabs []byte
8+
}
9+
10+
func (ts *tabScanner) Write(bs []byte) (n int, err error) {
11+
p := 0
12+
var rn int
13+
for pos, b := range bs {
14+
switch b {
15+
case '\n':
16+
rn, err = ts.output.Write(bs[p : pos+1])
17+
n += rn
18+
if err != nil {
19+
return
20+
}
21+
_, err = ts.output.Write(ts.tabs)
22+
if err != nil {
23+
return
24+
}
25+
p = pos + 1
26+
}
27+
}
28+
rn, err = ts.output.Write(bs[p:])
29+
return n + rn, err
30+
}
31+
32+
func newTabScanner(w io.Writer, tabs string) io.Writer {
33+
return &tabScanner{
34+
output: w,
35+
tabs: []byte(tabs),
36+
}
37+
}

tabscanner_test.go

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
package struct2ts
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
)
7+
8+
func TestTabScanner_Write(t *testing.T) {
9+
tests := []struct {
10+
Name string
11+
Input struct {
12+
Tabs string
13+
Buffers []string
14+
}
15+
Expected struct {
16+
Output string
17+
n *int
18+
}
19+
}{
20+
{
21+
"One new line mid string - one input, 3 spaces",
22+
struct {
23+
Tabs string
24+
Buffers []string
25+
}{Tabs: " ", Buffers: []string{"Hello how are you?\nI'm fine thanks!"}},
26+
struct {
27+
Output string
28+
n *int
29+
}{Output: "Hello how are you?\n I'm fine thanks!"},
30+
},
31+
{
32+
"One new line end string - one input, 3 spaces",
33+
struct {
34+
Tabs string
35+
Buffers []string
36+
}{Tabs: " ", Buffers: []string{"Hello how are you?\n"}},
37+
struct {
38+
Output string
39+
n *int
40+
}{Output: "Hello how are you?\n "},
41+
},
42+
{
43+
"One new line start string - one input, 3 spaces",
44+
struct {
45+
Tabs string
46+
Buffers []string
47+
}{Tabs: " ", Buffers: []string{"\nHello how are you?"}},
48+
struct {
49+
Output string
50+
n *int
51+
}{Output: "\n Hello how are you?"},
52+
},
53+
{
54+
"empty string",
55+
struct {
56+
Tabs string
57+
Buffers []string
58+
}{Tabs: " ", Buffers: []string{""}},
59+
struct {
60+
Output string
61+
n *int
62+
}{Output: ""},
63+
},
64+
{
65+
"Just a new line",
66+
struct {
67+
Tabs string
68+
Buffers []string
69+
}{Tabs: " ", Buffers: []string{"\n"}},
70+
struct {
71+
Output string
72+
n *int
73+
}{Output: "\n "},
74+
},
75+
}
76+
for _, test := range tests {
77+
t.Run(test.Name, func(t *testing.T) {
78+
outputBuffer := bytes.NewBuffer(nil)
79+
ts := newTabScanner(outputBuffer, test.Input.Tabs)
80+
for _, s := range test.Input.Buffers {
81+
_, err := ts.Write([]byte(s))
82+
if err != nil {
83+
t.Error("Buffer write error", err)
84+
}
85+
}
86+
if outputBuffer.String() != test.Expected.Output {
87+
t.Log("Output buffer doesn't match. Got ")
88+
t.Log(outputBuffer.String())
89+
t.Log("expected")
90+
t.Log(test.Expected.Output)
91+
t.Fail()
92+
}
93+
})
94+
}
95+
}

testdata/testmodel1/testmodel1.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package testmodel1
2+
3+
import (
4+
"fmt"
5+
"io"
6+
)
7+
8+
type Struct1 struct {
9+
HasNoCustomInterface int
10+
}
11+
12+
type Struct2 struct {
13+
TotallyDoesHaveOneAsAPointer int
14+
}
15+
16+
func (s *Struct2) RenderCustomTypescript(w io.Writer) (err error) {
17+
fmt.Fprint(w, "// Custom Output!!!")
18+
return nil
19+
}
20+
21+
type Struct3 struct {
22+
TotallyDoesHaveOne int
23+
}
24+
25+
func (s Struct3) RenderCustomTypescript(w io.Writer) (err error) {
26+
fmt.Fprint(w, "// Custom Output!!!")
27+
return nil
28+
}

testdata/testmodel1/testmodel1.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#!/bin/bash -Xe
2+
3+
go run github.com/OneOfOne/struct2ts/cmd/struct2ts github.com/OneOfOne/struct2ts/testdata/testmodel1.Struct1
4+
go run github.com/OneOfOne/struct2ts/cmd/struct2ts github.com/OneOfOne/struct2ts/testdata/testmodel1.Struct2
5+
go run github.com/OneOfOne/struct2ts/cmd/struct2ts github.com/OneOfOne/struct2ts/testdata/testmodel1.Struct3

0 commit comments

Comments
 (0)