Skip to content

Commit afb1e6d

Browse files
committed
gtrace: allow return of other traces from hooks
1 parent 9ddb690 commit afb1e6d

5 files changed

Lines changed: 346 additions & 98 deletions

File tree

cmd/gtrace/main.go

Lines changed: 50 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func main() {
107107

108108
var writers []*Writer
109109
if isGoGenerate || write {
110-
// We should support Go suffixes like `_linux.go` properly.
110+
// We should respect Go suffixes like `_linux.go`.
111111
name, tags, ext := splitOSArchTags(&buildCtx, gofile)
112112
if verbose {
113113
log.Printf(
@@ -261,9 +261,7 @@ func main() {
261261
text, ok := TrimConfigComment(c.Text)
262262
if ok {
263263
if item == nil {
264-
item = &GenItem{
265-
File: pkgFiles[i],
266-
}
264+
item = &GenItem{}
267265
}
268266
if err := item.ParseComment(text); err != nil {
269267
log.Fatalf(
@@ -292,18 +290,24 @@ func main() {
292290
Package: pkg,
293291
BuildConstraints: buildConstraints,
294292
}
293+
traces := make(map[string]*Trace)
295294
for _, item := range items {
296-
t := Trace{
295+
t := &Trace{
297296
Name: item.Ident.Name,
298297
Flag: item.Flag,
299298
}
299+
p.Traces = append(p.Traces, t)
300+
traces[item.Ident.Name] = t
301+
}
302+
for i, item := range items {
303+
t := p.Traces[i]
300304
for _, field := range item.StructType.Fields.List {
301305
name := field.Names[0].Name
302306
fn, ok := field.Type.(*ast.FuncType)
303307
if !ok {
304308
continue
305309
}
306-
f, err := buildFunc(info, fn)
310+
f, err := buildFunc(info, traces, fn)
307311
if err != nil {
308312
log.Printf(
309313
"skipping hook %s due to error: %v",
@@ -333,7 +337,6 @@ func main() {
333337
Flag: item.GenConfig.Flag | config.Flag,
334338
})
335339
}
336-
p.Traces = append(p.Traces, t)
337340
}
338341
for _, w := range writers {
339342
if err := w.Write(p); err != nil {
@@ -344,7 +347,8 @@ func main() {
344347
log.Println("OK")
345348
}
346349

347-
func buildFunc(info types.Info, fn *ast.FuncType) (ret Func, err error) {
350+
func buildFunc(info types.Info, traces map[string]*Trace, fn *ast.FuncType) (ret *Func, err error) {
351+
ret = new(Func)
348352
for _, p := range fn.Params.List {
349353
t := info.TypeOf(p.Type)
350354
if t == nil {
@@ -363,26 +367,34 @@ func buildFunc(info types.Info, fn *ast.FuncType) (ret Func, err error) {
363367
return ret, nil
364368
}
365369
if len(fn.Results.List) > 1 {
366-
return ret, fmt.Errorf(
370+
return nil, fmt.Errorf(
367371
"unsupported number of function results",
368372
)
369373
}
370374

371-
p := fn.Results.List[0]
372-
fn, ok := p.Type.(*ast.FuncType)
373-
if !ok {
374-
return ret, fmt.Errorf(
375-
"unsupported function result type %s",
376-
info.TypeOf(p.Type),
377-
)
378-
}
379-
result, err := buildFunc(info, fn)
380-
if err != nil {
381-
return ret, err
375+
r := fn.Results.List[0]
376+
377+
switch x := r.Type.(type) {
378+
case *ast.FuncType:
379+
result, err := buildFunc(info, traces, x)
380+
if err != nil {
381+
return nil, err
382+
}
383+
ret.Result = append(ret.Result, result)
384+
return ret, nil
385+
386+
case *ast.Ident:
387+
if t, ok := traces[x.Name]; ok {
388+
t.Nested = true
389+
ret.Result = append(ret.Result, t)
390+
return ret, nil
391+
}
382392
}
383-
ret.Result = append(ret.Result, result)
384393

385-
return ret, nil
394+
return nil, fmt.Errorf(
395+
"unsupported function result type %s",
396+
info.TypeOf(r.Type),
397+
)
386398
}
387399

388400
func splitOSArchTags(ctx *build.Context, name string) (base, tags, ext string) {
@@ -420,18 +432,21 @@ type Package struct {
420432
*types.Package
421433

422434
BuildConstraints []string
423-
Traces []Trace
435+
Traces []*Trace
424436
}
425437

426438
type Trace struct {
427-
Name string
428-
Hooks []Hook
429-
Flag GenFlag
439+
Name string
440+
Hooks []Hook
441+
Flag GenFlag
442+
Nested bool
430443
}
431444

445+
func (*Trace) isFuncResult() bool { return true }
446+
432447
type Hook struct {
433448
Name string
434-
Func Func
449+
Func *Func
435450
Flag GenFlag
436451
}
437452

@@ -440,12 +455,18 @@ type Param struct {
440455
Type types.Type
441456
}
442457

458+
type FuncResult interface {
459+
isFuncResult() bool
460+
}
461+
443462
type Func struct {
444463
Params []Param
445-
Result []Func // 0 or 1.
464+
Result []FuncResult // 0 or 1.
446465
}
447466

448-
func (f Func) HasResult() bool {
467+
func (*Func) isFuncResult() bool { return true }
468+
469+
func (f *Func) HasResult() bool {
449470
return len(f.Result) > 0
450471
}
451472

@@ -506,9 +527,7 @@ func (g *GenConfig) ParseParameter(text string) (err error) {
506527

507528
type GenItem struct {
508529
GenConfig
509-
File *os.File
510530
Ident *ast.Ident
511-
TypeSpec *ast.TypeSpec
512531
StructType *ast.StructType
513532
}
514533

0 commit comments

Comments
 (0)