Skip to content

Commit

Permalink
Move to a layered call approach for the client template (#15)
Browse files Browse the repository at this point in the history
Move to a layered call approach for the client template.

Instead of prefixing everything with underscore, I've created a separate
unexported method that uses the positional arguments. The exported
companion has named arguments.
  • Loading branch information
brettbuddin committed Jan 30, 2021
1 parent c7f7dd6 commit 1933144
Show file tree
Hide file tree
Showing 9 changed files with 445 additions and 327 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
uses: actions/setup-go@v2
with:
stable: false
go-version: 1.16.0-beta1
go-version: 1.16.0-rc1
- name: Lint
run: |
go get honnef.co/go/tools/cmd/staticcheck
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
GO ?= go1.16beta1
GO ?= go1.16rc1
export GO

.PHONY: build
Expand Down
82 changes: 68 additions & 14 deletions internal/generate/gocode/gotemplate/func.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,32 @@ import (
"sort"
"strings"
"text/template"
"unicode"

"github.com/TruceRPC/truce"
)

var tmplFuncs = template.FuncMap{
"args": args,
"backtick": backtick,
"errorFmt": errorFmt,
"goType": goType,
"method": method,
"name": name,
"pathJoin": pathJoin,
"signature": signature,
"stringHasPrefix": strings.HasPrefix,
"tags": tags,
"backtick": backtick,
"callUnexported": callUnexported,
"errorFmt": errorFmt,
"goType": goType,
"method": method,
"name": name,
"pathJoin": pathJoin,
"posArgs": posArgs,
"signature": signature,
"sortQueryParams": sortQueryParams,
"stringHasPrefix": strings.HasPrefix,
"tags": tags,
"unexportedSignature": unexportedSignature,
}

func unexported(v string) string {
if v == "" {
return v
}
return string(unicode.ToLower(rune(v[0]))) + v[1:]
}

func name(f truce.Field) (v string) {
Expand Down Expand Up @@ -60,13 +71,45 @@ func signature(f truce.Function) string {
}
fmt.Fprintf(builder, "%s %s", arg.Name, goType(arg.Type))
}
builder.WriteString(") ")
builder.WriteString(signatureReturn(f))
return builder.String()
}

func unexportedSignature(f truce.Function) string {
builder := &strings.Builder{}
fmt.Fprintf(builder, "%s(ctxt context.Context, ", unexported(f.Name))
for i, arg := range f.Arguments {
if i > 0 {
builder.WriteString(", ")
}
fmt.Fprintf(builder, "v%d %s", i, goType(arg.Type))
}
builder.WriteString(") ")
builder.WriteString(signatureReturn(f))
return builder.String()
}

builder.WriteString(") (")
func signatureReturn(f truce.Function) string {
builder := &strings.Builder{}
builder.WriteString("(")
if rtn := f.Return; rtn.Name != "" {
fmt.Fprintf(builder, "%s, ", goType(rtn.Type))
}
builder.WriteString("error)")
return builder.String()
}

func callUnexported(f truce.Function) string {
builder := &strings.Builder{}
fmt.Fprintf(builder, "%s(ctxt, ", unexported(f.Name))
for i, arg := range f.Arguments {
if i > 0 {
builder.WriteString(", ")
}
fmt.Fprintf(builder, "%s", arg.Name)
}
builder.WriteString(")")
return builder.String()
}

Expand All @@ -88,12 +131,12 @@ func pathJoin(path Path) string {
return fmt.Sprintf(`%q`, path.FmtString())
}

func args(f truce.Function) (v string) {
for i, arg := range f.Arguments {
func posArgs(fields []truce.Field) (v string) {
for i := range fields {
if i > 0 {
v += ", "
}
v += arg.Name
v += fmt.Sprintf("v%d", i)
}
return
}
Expand Down Expand Up @@ -135,3 +178,14 @@ func sortedFields(m map[string]truce.Field) []truce.Field {
})
return l
}

func sortQueryParams(m map[string]QueryParam) []QueryParam {
var l []QueryParam
for _, f := range m {
l = append(l, f)
}
sort.Slice(l, func(i, j int) bool {
return l[i].Pos < l[j].Pos
})
return l
}
30 changes: 14 additions & 16 deletions internal/generate/gocode/gotemplate/func_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"gotest.tools/v3/assert"
)

func TestArgs(t *testing.T) {
func TestPosArgs(t *testing.T) {
testcases := []struct {
name string
in []truce.Field
Expand All @@ -18,15 +18,15 @@ func TestArgs(t *testing.T) {
in: []truce.Field{
{Name: "a", Type: "string"},
},
out: "a",
out: "v0",
},
{
name: "multiple fields",
in: []truce.Field{
{Name: "a", Type: "string"},
{Name: "b", Type: "string"},
},
out: "a, b",
out: "v0, v1",
},
{
name: "no fields",
Expand All @@ -36,9 +36,7 @@ func TestArgs(t *testing.T) {
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
v := args(truce.Function{
Arguments: tc.in,
})
v := posArgs(tc.in)
assert.Equal(t, v, tc.out)
})
}
Expand Down Expand Up @@ -181,29 +179,29 @@ func TestPath(t *testing.T) {
{
name: "single variable",
in: Path{
{Var: "x", Type: "variable", Value: "a"},
{VarPos: 0, Var: "x", Type: "variable", Value: "a"},
},
out: `fmt.Sprintf("/%v", x)`,
out: `fmt.Sprintf("/%v", v0)`,
},
{
name: "multiple variables",
in: Path{
{Var: "x", Type: "variable", Value: "a"},
{Var: "y", Type: "variable", Value: "b"},
{Var: "z", Type: "variable", Value: "c"},
{VarPos: 0, Var: "x", Type: "variable", Value: "a"},
{VarPos: 1, Var: "y", Type: "variable", Value: "b"},
{VarPos: 2, Var: "z", Type: "variable", Value: "c"},
},
out: `fmt.Sprintf("/%v/%v/%v", x, y, z)`,
out: `fmt.Sprintf("/%v/%v/%v", v0, v1, v2)`,
},
{
name: "variables and static elements",
in: Path{
{Value: "api", Type: "static"},
{Var: "x", Type: "variable", Value: "a"},
{Var: "y", Type: "variable", Value: "b"},
{VarPos: 0, Var: "x", Type: "variable", Value: "a"},
{VarPos: 1, Var: "y", Type: "variable", Value: "b"},
{Value: "private", Type: "static"},
{Var: "z", Type: "variable", Value: "c"},
{VarPos: 2, Var: "z", Type: "variable", Value: "c"},
},
out: `fmt.Sprintf("/api/%v/%v/private/%v", x, y, z)`,
out: `fmt.Sprintf("/api/%v/%v/private/%v", v0, v1, v2)`,
},
}
for _, tc := range testcases {
Expand Down
58 changes: 40 additions & 18 deletions internal/generate/gocode/gotemplate/http.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ type Function struct {
type Path []Element

func parsePath(vars map[string]string, v string) (p Path) {
var varOffset int
for i, val := range strings.Split(v, "/") {
if i == 0 && val == "" {
continue
Expand All @@ -169,11 +170,17 @@ func parsePath(vars map[string]string, v string) (p Path) {
varn = vars[val]
}

p = append(p, Element{
Type: typ,
Value: val,
Var: varn,
})
el := Element{
Type: typ,
Value: val,
Var: varn,
VarPos: varOffset,
}
p = append(p, el)

if el.Type == "variable" {
varOffset++
}
}

return
Expand Down Expand Up @@ -206,17 +213,18 @@ func (p Path) ArgString() (v string) {
if i > 0 {
v += ", "
}
v += e.Var
v += fmt.Sprintf("v%d", e.VarPos)
i++
}
return
}

// Element is a Path segment. It can either be static or variable.
type Element struct {
Type string
Value string
Var string
Type string
Value string
Var string
VarPos int
}

// String implements fmt.Stringer
Expand Down Expand Up @@ -251,22 +259,27 @@ func NewFunction(config *truce.HTTP, function truce.Function) (*Function, error)

transport := *function.Transports.HTTP

b := &Function{Definition: function, Query: map[string]QueryParam{}}
b := &Function{
Definition: function,
Query: map[string]QueryParam{},
}

type argument struct {
variable string
typ string
variable string
posVariable string
typ string
}

var (
pathMappings = map[string]string{}
args = map[string]argument{}
)

for _, field := range function.Arguments {
for i, field := range function.Arguments {
args[field.Name] = argument{
typ: string(field.Type),
variable: field.Name,
typ: string(field.Type),
posVariable: fmt.Sprintf("v%d", i),
variable: field.Name,
}
}

Expand All @@ -286,8 +299,17 @@ func NewFunction(config *truce.HTTP, function truce.Function) (*Function, error)

b.Method = transport.Method

var qpos int
// Sort the arguments by name for consistent positional ordering.
var argVals []truce.ArgumentValue
for _, arg := range transport.Arguments {
argVals = append(argVals, arg)
}
sort.Slice(argVals, func(i, j int) bool {
return argVals[i].Name < argVals[j].Name
})

var qpos int
for _, arg := range argVals {
a, ok := args[arg.Name]

switch arg.From {
Expand All @@ -296,7 +318,7 @@ func NewFunction(config *truce.HTTP, function truce.Function) (*Function, error)
continue
}

b.BodyVar = a.variable
b.BodyVar = a.posVariable
b.BodyType = a.typ
case "path":
if !ok {
Expand All @@ -312,7 +334,7 @@ func NewFunction(config *truce.HTTP, function truce.Function) (*Function, error)
b.Query[arg.Var] = QueryParam{
Pos: qpos,
QueryVar: arg.Var,
GoVar: a.variable,
GoVar: a.posVariable,
Type: a.typ,
}

Expand Down
Loading

0 comments on commit 1933144

Please sign in to comment.