Skip to content

Commit e8cce16

Browse files
committed
chore: replace 'string' identifiers with Identifier type
Type includes package and prefix information. Allowing package collisions to be more gracefully handled.
1 parent d9cf060 commit e8cce16

File tree

22 files changed

+312
-75
lines changed

22 files changed

+312
-75
lines changed

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,14 @@ interface SimpleType<T extends Comparable> {
2828
}
2929
```
3030

31+
# How to use it
32+
33+
`guts` is a library, not a command line utility. This is to allow configuration with code, and also helps with package resolution.
34+
35+
See the [simple example](./example/simple) for a basic usage of the library.
36+
37+
```go
38+
3139
# How it works
3240

3341
`guts` first parses a set of golang packages. The Go AST is traversed to find all the types defined in the packages.

bindings/ast.go

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

33
import (
44
"fmt"
5+
"go/types"
56

67
"github.com/dop251/goja"
78
)
@@ -13,7 +14,20 @@ type isTypescriptNode struct{}
1314

1415
func (isTypescriptNode) isNode() {}
1516

16-
type Identifier string
17+
type Identifier struct {
18+
Name string
19+
Package *types.Package
20+
Prefix string
21+
}
22+
23+
func (i Identifier) String() string {
24+
return i.Name
25+
}
26+
27+
// Ref returns the identifier reference to be used in the generated code.
28+
func (i Identifier) Ref() string {
29+
return i.Prefix + i.Name
30+
}
1731

1832
type Source struct {
1933
File string

bindings/bindings.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (b *Bindings) Reference(ref *ReferenceType) (*goja.Object, error) {
128128
}
129129

130130
res, err := modifier(goja.Undefined(),
131-
b.vm.ToValue(ref.Name),
131+
b.vm.ToValue(ref.Name.Ref()),
132132
b.vm.NewArray(args...),
133133
)
134134
if err != nil {
@@ -225,7 +225,7 @@ func (b *Bindings) Interface(ti *Interface) (*goja.Object, error) {
225225

226226
res, err := interfaceDecl(goja.Undefined(),
227227
b.vm.ToValue(ToStrings(ti.Modifiers)),
228-
b.vm.ToValue(string(ti.Name)),
228+
b.vm.ToValue(ti.Name.Ref()),
229229
b.vm.NewArray(typeParams...),
230230
b.vm.NewArray(heritage...),
231231
b.vm.NewArray(fields...),
@@ -321,7 +321,7 @@ func (b *Bindings) Alias(alias *Alias) (*goja.Object, error) {
321321

322322
res, err := aliasFunc(goja.Undefined(),
323323
b.vm.ToValue(ToStrings(alias.Modifiers)),
324-
b.vm.ToValue(string(alias.Name)),
324+
b.vm.ToValue(alias.Name.Ref()),
325325
b.vm.NewArray(typeParams...),
326326
siObj,
327327
)
@@ -361,7 +361,7 @@ func (b *Bindings) TypeParameter(ty *TypeParameter) (*goja.Object, error) {
361361

362362
res, err := typeParamF(goja.Undefined(),
363363
b.vm.ToValue(ToStrings(ty.Modifiers)),
364-
b.vm.ToValue(ty.Name),
364+
b.vm.ToValue(ty.Name.Ref()),
365365
paramType,
366366
defaultType,
367367
)
@@ -580,7 +580,7 @@ func (b *Bindings) VariableDeclaration(decl *VariableDeclaration) (*goja.Object,
580580

581581
res, err := aliasFunc(
582582
goja.Undefined(),
583-
b.vm.ToValue(decl.Name),
583+
b.vm.ToValue(decl.Name.Ref()),
584584
b.vm.ToValue(decl.ExclamationMark),
585585
declType,
586586
declInit,

bindings/declarations.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (*Alias) isDeclarationType() {}
5656
// - Type: Comparable
5757
// - DefaultType: nil
5858
type TypeParameter struct {
59-
Name string
59+
Name Identifier
6060
Modifiers []Modifier
6161
Type ExpressionType
6262
// DefaultType does not map to any Golang concepts and will never be
@@ -71,7 +71,7 @@ func Simplify(p []*TypeParameter) ([]*TypeParameter, error) {
7171
params := make([]*TypeParameter, 0, len(p))
7272
exists := make(map[string]*TypeParameter)
7373
for _, tp := range p {
74-
if found, ok := exists[tp.Name]; ok {
74+
if found, ok := exists[tp.Name.Ref()]; ok {
7575
// Compare types, make sure they are the same
7676
equal := reflect.DeepEqual(found, tp)
7777
if !equal {
@@ -80,7 +80,7 @@ func Simplify(p []*TypeParameter) ([]*TypeParameter, error) {
8080
continue
8181
}
8282
params = append(params, tp)
83-
exists[tp.Name] = tp
83+
exists[tp.Name.Ref()] = tp
8484
}
8585
return params, nil
8686
}

bindings/expressions.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,14 +51,14 @@ func (*LiteralType) isExpressionType() {}
5151

5252
// ReferenceType can be used to reference another type by name
5353
type ReferenceType struct {
54-
Name string `json:"name"`
54+
Name Identifier `json:"name"`
5555
// TODO: Generics
5656
Arguments []ExpressionType `json:"arguments"`
5757

5858
isTypescriptNode
5959
}
6060

61-
func Reference(name string, args ...ExpressionType) *ReferenceType {
61+
func Reference(name Identifier, args ...ExpressionType) *ReferenceType {
6262
return &ReferenceType{Name: name, Arguments: args}
6363
}
6464

@@ -122,7 +122,7 @@ type VariableDeclarationList struct {
122122
func (*VariableDeclarationList) isExpressionType() {}
123123

124124
type VariableDeclaration struct {
125-
Name string
125+
Name Identifier
126126
ExclamationMark bool
127127
Type ExpressionType
128128
Initializer ExpressionType

bindings/string.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import "fmt"
44

55
// These string functions are purely for debugging
66

7-
func (i Identifier) String() string { return string(i) }
87
func (a Alias) String() string { return fmt.Sprintf("Alias:%s", a.Name) }
98
func (k LiteralKeyword) String() string { return string(k) }
109
func (a ArrayType) String() string { return fmt.Sprintf("[]%s", a.Node) }

builtins.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,25 @@ package guts
22

33
import "github.com/coder/guts/bindings"
44

5-
const (
6-
builtInComparable = "Comparable"
5+
var (
6+
builtInComparable = bindings.Identifier{Name: "Comparable"}
7+
builtInString = bindings.Identifier{Name: "string"}
8+
builtInNumber = bindings.Identifier{Name: "number"}
9+
builtInBoolean = bindings.Identifier{Name: "boolean"}
10+
builtInRecord = bindings.Identifier{Name: "Record"}
711
)
812

913
func (ts *Typescript) includeComparable() {
1014
// The zzz just pushes it to the end of the sorting.
1115
// Kinda strange, but it works.
12-
_ = ts.setNode(builtInComparable, typescriptNode{
16+
_ = ts.setNode(builtInComparable.Ref(), typescriptNode{
1317
Node: &bindings.Alias{
1418
Name: builtInComparable,
1519
Modifiers: []bindings.Modifier{},
1620
Type: bindings.Union(
17-
bindings.Reference("string"),
18-
bindings.Reference("number"),
19-
bindings.Reference("boolean"),
21+
bindings.Reference(builtInString),
22+
bindings.Reference(builtInNumber),
23+
bindings.Reference(builtInBoolean),
2024
),
2125
Parameters: []*bindings.TypeParameter{},
2226
Source: bindings.Source{},

cmd/gots/main.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ func main() {
1616
}
1717

1818
for _, arg := range os.Args[1:] {
19-
err = gen.Include(arg, true)
19+
err = gen.IncludeGenerate(arg)
2020
if err != nil {
2121
panic(err)
2222
}

config/mutations.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,12 @@ func EnumLists(ts *guts.Typescript) {
8686
Declarations: &bindings.VariableDeclarationList{
8787
Declarations: []*bindings.VariableDeclaration{
8888
{
89-
Name: name,
89+
// TODO: Fix this with Identifier's instead of "string"
90+
Name: bindings.Identifier{Name: name},
9091
ExclamationMark: false,
9192
Type: &bindings.ArrayType{
9293
// The type is the enum type
93-
Node: bindings.Reference(key),
94+
Node: bindings.Reference(bindings.Identifier{Name: key}),
9495
},
9596
Initializer: &bindings.ArrayLiteralType{
9697
Elements: values,
@@ -112,3 +113,38 @@ func EnumLists(ts *guts.Typescript) {
112113
}
113114
}
114115
}
116+
117+
// MissingReferencesToAny will change any references to types that are not found in the
118+
// typescript tree to 'any'.
119+
func MissingReferencesToAny(ts *guts.Typescript) {
120+
// Find all valid references to types
121+
valid := make(map[string]struct{})
122+
ts.ForEach(func(key string, node bindings.Node) {
123+
switch node.(type) {
124+
case *bindings.Alias, *bindings.Interface, *bindings.VariableDeclaration:
125+
valid[key] = struct{}{}
126+
}
127+
})
128+
129+
ts.ForEach(func(key string, node bindings.Node) {
130+
fixMissingReferences(valid, node)
131+
})
132+
}
133+
134+
func fixMissingReferences(valid map[string]struct{}, node bindings.Node) bool {
135+
switch node := node.(type) {
136+
case *bindings.Interface:
137+
for _, field := range node.Fields {
138+
if !fixMissingReferences(valid, field.Type) {
139+
field.FieldComments = append(field.FieldComments, "Reference not found, changed to 'any'")
140+
}
141+
}
142+
case *bindings.Alias:
143+
if _, ok := valid[node.Name.Ref()]; !ok {
144+
// Invalid reference, change to 'any'
145+
node.Type = ptr(bindings.KeywordAny)
146+
return false
147+
}
148+
}
149+
return true
150+
}

0 commit comments

Comments
 (0)