Skip to content
This repository was archived by the owner on May 25, 2024. It is now read-only.

Commit 8e6bcfd

Browse files
committedJun 13, 2022
Add some const addable parsing
1 parent 9868536 commit 8e6bcfd

File tree

6 files changed

+126
-3
lines changed

6 files changed

+126
-3
lines changed
 

‎README.md

+8-1
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,19 @@ which contains necessary definitions for resulting SQL queries.
7777
### What this project can currently do
7878
Please see `examples` package to see more uses and available functionality.
7979

80-
* Basic comparisons to constants and most of binary expressions.
80+
* Basic comparisons to values and most of binary expressions.
8181
```go
8282
queryable.Where(func(user User) bool {
8383
return (user.Name == "John" && user.ID == 1) || user.ID >= 4
8484
})
8585
```
86+
* Compare to constants.
87+
```go
88+
const name = "John"
89+
queryable.Where(func(user User) bool {
90+
return user.Name == name
91+
})
92+
```
8693
* Compare to true/false
8794
```go
8895
queryable.Where(func(book *Book) bool {

‎internal/addables.go

+13
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ func init() {
2727
addBinaryGenerators()
2828
addPackageIdentGenerators()
2929

30+
addConstGenerators()
31+
3032
// Basic generators, they are not specific
3133
// to some type, package or variable/const.
3234
addGenerator(func(p *whereBodyParser, s *ast.BasicLit, args map[string]int) Addable {
@@ -64,6 +66,17 @@ func init() {
6466
return NewSimple(param, raw(s.Name))
6567
}
6668

69+
if s.Obj != nil && s.Obj.Kind == ast.Con {
70+
defObj := p.c.TypeInfo.ObjectOf(s.Obj.Decl.(*ast.ValueSpec).Values[0].(*ast.SelectorExpr).Sel)
71+
_ = defObj
72+
73+
if valSpec, ok := s.Obj.Decl.(*ast.ValueSpec); ok {
74+
if basicLit, ok := valSpec.Values[0].(*ast.BasicLit); ok {
75+
return NewSimple(param, getArg(basicLit))
76+
}
77+
}
78+
}
79+
6780
argPos, ok := args[s.Name]
6881
if !ok {
6982
p.c.panicWithPosf(s, "argument is not provided: "+s.Name)

‎internal/addables_test.go

+41-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
//go:generate go run ../cmd/goquery/main.go
22

3-
package internal
3+
package internal_test
44

55
import (
66
"context"
77
"database/sql"
8+
"math"
89
"os"
910
"testing"
1011
"time"
@@ -25,6 +26,8 @@ type Extensive struct {
2526
TimeCol time.Time
2627
}
2728

29+
const packageConst = 1
30+
2831
func TestSimpleAddables(t *testing.T) {
2932
tests := []struct {
3033
name string
@@ -98,6 +101,43 @@ func TestSimpleAddables(t *testing.T) {
98101
},
99102
result: `("time_col" + -3 * INTERVAL '1 second' = NOW())`,
100103
},
104+
{
105+
name: "with const simple",
106+
f: func(q goquery.Queryable[*Extensive]) {
107+
const val = 0
108+
q.Where(func(e *Extensive) bool {
109+
return e.IntCol == val
110+
})
111+
},
112+
result: `("int_col" = 0)`,
113+
},
114+
{
115+
name: "with const from package-level same file",
116+
f: func(q goquery.Queryable[*Extensive]) {
117+
q.Where(func(e *Extensive) bool {
118+
return e.IntCol == packageConst
119+
})
120+
},
121+
result: `("int_col" = 1)`,
122+
},
123+
{
124+
name: "with const from package-level different file",
125+
f: func(q goquery.Queryable[*Extensive]) {
126+
q.Where(func(e *Extensive) bool {
127+
return e.IntCol == anotherFileConst
128+
})
129+
},
130+
result: `("int_col" = 3)`,
131+
},
132+
{
133+
name: "with const from another package",
134+
f: func(q goquery.Queryable[*Extensive]) {
135+
q.Where(func(e *Extensive) bool {
136+
return e.IntCol == math.MaxInt8
137+
})
138+
},
139+
result: `("int_col" = 127)`,
140+
},
101141
}
102142

103143
for _, test := range tests {

‎internal/const_generators.go

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package internal
2+
3+
import (
4+
"go/ast"
5+
"go/types"
6+
)
7+
8+
func addConstGenerators() {
9+
// consts in the form of
10+
// const <name> = <value>
11+
// const <name> = <package>.<name>
12+
// for example
13+
// const val = 55
14+
// const val = math.MaxInt
15+
addGenerator(func(p *whereBodyParser, s *ast.Ident, args map[string]int) Addable {
16+
if s.Obj == nil || s.Obj.Kind != ast.Con {
17+
objVal := p.c.TypeInfo.ObjectOf(s)
18+
if _, ok := objVal.(*types.Const); ok {
19+
// If constant is just an Ident - it means that
20+
// it is defined in the same package
21+
return NewSimple(param, raw(p.c.exprName(s)))
22+
}
23+
24+
return nil
25+
}
26+
27+
switch constVal := s.Obj.Decl.(*ast.ValueSpec).Values[0].(type) {
28+
case *ast.BasicLit:
29+
// Just use a direct value for now.
30+
// TODO: support package constants by name, not value.
31+
return NewSimple(param, getArg(constVal))
32+
case *ast.SelectorExpr:
33+
// If it is a selector - use its name.
34+
// Import for it will be added on template execution.
35+
return NewSimple(param, raw(p.c.exprName(constVal)))
36+
}
37+
38+
return nil
39+
})
40+
41+
// consts in the form of
42+
// <package>.<name>
43+
// for example
44+
// math.MaxInt
45+
addGenerator(func(p *whereBodyParser, s *ast.SelectorExpr, args map[string]int) Addable {
46+
obj := p.c.TypeInfo.ObjectOf(s.Sel)
47+
if obj == nil {
48+
return nil
49+
}
50+
51+
if _, ok := obj.(*types.Const); ok {
52+
// Same as in the above const evaluation - if it is a const
53+
// from another package - it will be imported on the
54+
// template execution.
55+
return NewSimple(param, raw(p.c.exprName(s)))
56+
}
57+
58+
return nil
59+
})
60+
}

‎internal/const_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package internal_test
2+
3+
const anotherFileConst = 3

‎internal/context.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ const InterfaceName = "Queryable"
1616

1717
type Context struct {
1818
FileSet *token.FileSet
19-
AstFile ast.Node
19+
AstFile *ast.File
2020

2121
PackageName string
2222

0 commit comments

Comments
 (0)
This repository has been archived.