diff --git a/.gitignore b/.gitignore index ca04419..767fd65 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea /gtrace /pinger /buildtags diff --git a/README.md b/README.md index 1ebbd04..6c1b4a2 100644 --- a/README.md +++ b/README.md @@ -213,6 +213,41 @@ func (c *Client) ping(ctx context.Context) error { } ``` +**gtrace** can export **shortcuts** by using comment like `//gtrace:set Shortcut` or `//gtrace:set SHORTCUT`. +This may need if traces placed in external package (for example `trace`): + +```go +package trace + +//go:generate gtrace + +//gtrace:gen +//gtrace:set Shortcut +type Client struct { + OnPing func(ClientPingStart) func(ClientPingDone) +} +``` + +Code snippet bellow exclude `Trace` prefix from struct names because `trace` is a package name. +This allows transform code from `ClientTrace` to `trace.Client`. +After `go generate` we able to call exported _hooks_ like this: + +```go +package lib + +import ( + "context" + "trace" +) + +func (c *Client) ClientTracePing(ctx context.Context) error { + done := trace.ClientOnPing(c.Trace, 1, 2, 3) + err := doPing(ctx, c.conn) + done(1, 2, 3, err) + return err +} +``` + ### Build Tags **gtrace** can generate zero-cost tracing helpers when tracing of your app is optional. That is, your client code will remain the same -- composing traces with needed callbacks, calling non-exported versions of _hooks_ (or _shortcuts_) etc. But after compilation calling the tracing helpers would take no CPU time. diff --git a/cmd/gtrace/main.go b/cmd/gtrace/main.go index 156088b..334a4fa 100644 --- a/cmd/gtrace/main.go +++ b/cmd/gtrace/main.go @@ -302,6 +302,9 @@ func main() { for i, item := range items { t := p.Traces[i] for _, field := range item.StructType.Fields.List { + if _, ok := field.Type.(*ast.FuncType); !ok { + continue + } name := field.Names[0].Name fn, ok := field.Type.(*ast.FuncType) if !ok { @@ -489,6 +492,7 @@ func (f GenFlag) Has(x GenFlag) bool { const ( GenZero GenFlag = 1 << iota >> 1 GenShortcut + GenShortcutPublic GenContext GenAll = ^GenFlag(0) @@ -527,6 +531,8 @@ func (g *GenConfig) ParseParameter(text string) (err error) { switch param { case "shortcut": g.Flag |= GenShortcut + case "Shortcut", "SHORTCUT": + g.Flag |= GenShortcutPublic case "context": g.Flag |= GenContext default: diff --git a/cmd/gtrace/writer.go b/cmd/gtrace/writer.go index 83acefd..12af3fa 100644 --- a/cmd/gtrace/writer.go +++ b/cmd/gtrace/writer.go @@ -91,13 +91,13 @@ func (w *Writer) Write(p Package) error { } for _, trace := range p.Traces { for _, hook := range trace.Hooks { - if !hook.Flag.Has(GenShortcut) { + if !hook.Flag.Has(GenShortcut) && !hook.Flag.Has(GenShortcutPublic) { continue } if w.Stub { - w.stubHookShortcut(trace, hook) + w.stubHookShortcut(trace, hook, hook.Flag.Has(GenShortcutPublic)) } else { - w.hookShortcut(trace, hook) + w.hookShortcut(trace, hook, hook.Flag.Has(GenShortcutPublic)) } } } @@ -209,7 +209,7 @@ func unwrapStruct(t types.Type) (n *types.Named, s *types.Struct) { func (w *Writer) funcImports(dst []dep, flag GenFlag, fn *Func) []dep { for _, p := range fn.Params { dst = w.typeImports(dst, p.Type) - if !flag.Has(GenShortcut) { + if !flag.Has(GenShortcut) && !flag.Has(GenShortcutPublic) { continue } if _, s := unwrapStruct(p.Type); s != nil { @@ -597,9 +597,13 @@ func (w *Writer) stubShortcutFunc(id string, f *Func) (name string) { return name } -func (w *Writer) stubHookShortcut(trace *Trace, hook Hook) { +func (w *Writer) stubHookShortcut(trace *Trace, hook Hook, export bool) { name := tempName(trace.Name, hook.Name) - name = unexported(name) + if export { + name = exported(name) + } else { + name = unexported(name) + } w.mustDeclare(name) id := uniqueTraceHookID(trace, hook) @@ -877,9 +881,13 @@ func (w *Writer) constructStruct(n *types.Named, s *types.Struct, vars []string) return p, vars } -func (w *Writer) hookShortcut(trace *Trace, hook Hook) { +func (w *Writer) hookShortcut(trace *Trace, hook Hook, export bool) { name := tempName(trace.Name, hook.Name) - name = unexported(name) + if export { + name = exported(name) + } else { + name = unexported(name) + } w.mustDeclare(name) w.newScope(func() {