Skip to content

Commit 4250159

Browse files
abhinavprashantv
andauthored
cmd: Warn on unused //errtrace:skip (#62)
If we find `//errtrace:skip` comments on lines that wouldn't be instrumented, print warnings about them. Resolves #61 --------- Co-authored-by: Prashant V <prashant@prashantv.com>
1 parent dbbf10f commit 4250159

File tree

6 files changed

+69
-17
lines changed

6 files changed

+69
-17
lines changed

cmd/errtrace/main.go

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,21 @@ func (cmd *mainCmd) processFile(r fileRequest) error {
266266
}
267267
ast.Walk(&w, f)
268268

269+
// Look for unused optouts and warn about them.
270+
if len(w.optouts) > 0 {
271+
unusedOptouts := make([]int, 0, len(w.optouts))
272+
for line, used := range w.optouts {
273+
if used == 0 {
274+
unusedOptouts = append(unusedOptouts, line)
275+
}
276+
}
277+
sort.Ints(unusedOptouts)
278+
279+
for _, line := range unusedOptouts {
280+
cmd.log.Printf("%s:%d:unused errtrace:skip", r.Filename, line)
281+
}
282+
}
283+
269284
if r.List {
270285
if len(inserts) > 0 {
271286
_, err = fmt.Fprintf(cmd.Stdout, "%s\n", r.Filename)
@@ -420,10 +435,11 @@ type walker struct {
420435
// Inputs
421436

422437
fset *token.FileSet // file set for positional information
423-
optouts map[int]struct{}
424-
errtrace string // name of the errtrace package
438+
errtrace string // name of the errtrace package
425439
logger *log.Logger
426440

441+
optouts map[int]int // map from line to number of uses
442+
427443
// Outputs
428444

429445
// inserts is the list of inserts to make.
@@ -694,14 +710,15 @@ func (t *walker) wrapExpr(n int, expr ast.Expr) {
694710
case t.isErrtraceWrap(expr):
695711
return // already wrapped
696712

697-
case t.optout(expr.Pos()):
698-
return
699-
700713
case isIdent(expr, "nil"):
701714
// Optimization: ignore if it's "nil".
702715
return
703716
}
704717

718+
if t.optout(expr.Pos()) {
719+
return
720+
}
721+
705722
*t.inserts = append(*t.inserts,
706723
&insertWrapOpen{N: n, Before: expr.Pos()},
707724
&insertWrapClose{After: expr.End()},
@@ -731,10 +748,13 @@ func (t *walker) isErrtraceWrap(expr ast.Expr) bool {
731748
}
732749

733750
// optout reports whether the line at the given position
734-
// is opted out of tracing.
751+
// is opted out of tracing, incrementing uses if so.
735752
func (t *walker) optout(pos token.Pos) bool {
736753
line := t.fset.Position(pos).Line
737754
_, ok := t.optouts[line]
755+
if ok {
756+
t.optouts[line]++
757+
}
738758
return ok
739759
}
740760

@@ -857,13 +877,13 @@ func setOf[T comparable](xs []T) map[T]struct{} {
857877
func optoutLines(
858878
fset *token.FileSet,
859879
comments []*ast.CommentGroup,
860-
) map[int]struct{} {
861-
lines := make(map[int]struct{})
880+
) map[int]int {
881+
lines := make(map[int]int)
862882
for _, cg := range comments {
863883
for _, c := range cg.List {
864884
if strings.Contains(c.Text, "//errtrace:skip") {
865885
lineNo := fset.Position(c.Pos()).Line
866-
lines[lineNo] = struct{}{}
886+
lines[lineNo] = 0
867887
}
868888
}
869889
}

cmd/errtrace/main_test.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -461,13 +461,12 @@ func extractLogs(src []byte) ([]logLine, error) {
461461
var logs []logLine
462462
for _, c := range f.Comments {
463463
for _, l := range c.List {
464-
if !strings.HasPrefix(l.Text, "// want:") {
464+
_, lit, ok := strings.Cut(l.Text, "// want:")
465+
if !ok {
465466
continue
466467
}
467468

468469
pos := fset.Position(l.Pos())
469-
lit := strings.TrimPrefix(l.Text, "// want:")
470-
471470
s, err := strconv.Unquote(lit)
472471
if err != nil {
473472
return nil, fmt.Errorf("%s:bad string literal: %s", pos, lit)
@@ -499,11 +498,18 @@ func parseLogOutput(file, s string) ([]logLine, error) {
499498
}
500499

501500
var msg string
502-
switch len(parts) {
503-
case 3:
504-
msg = parts[2] // file:line:msg
505-
case 4:
506-
msg = parts[3] // file:line:column:msg
501+
if len(parts) == 4 {
502+
if _, err := strconv.Atoi(parts[2]); err == nil {
503+
// file:line:column:msg
504+
msg = parts[3]
505+
}
506+
}
507+
if msg == "" && len(parts) >= 2 {
508+
// file:line:msg
509+
msg = strings.Join(parts[2:], ":")
510+
}
511+
if msg == "" {
512+
return nil, fmt.Errorf("bad log line: %q", line)
507513
}
508514

509515
lineNum, err := strconv.Atoi(parts[1])

cmd/errtrace/testdata/golden/noop.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ func immediatelyInvoked() error {
3131
return errors.New("failure") //errtrace:skip
3232
}()
3333
}
34+
35+
func multipleReturns() (error, error) {
36+
return errors.New("a"), errors.New("b") //errtrace:skip
37+
}

cmd/errtrace/testdata/golden/noop.go.golden

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,7 @@ func immediatelyInvoked() error {
3131
return errors.New("failure") //errtrace:skip
3232
}()
3333
}
34+
35+
func multipleReturns() (error, error) {
36+
return errors.New("a"), errors.New("b") //errtrace:skip
37+
}

cmd/errtrace/testdata/golden/optout.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,12 @@ func Try(problem bool) (int, error) {
2323

2424
return bar.Baz() //errtrace:skip // caller wants unwrapped error
2525
}
26+
27+
func unused() error {
28+
return nil //errtrace:skip // want:"unused errtrace:skip"
29+
}
30+
31+
func multipleReturns() (a, b error) {
32+
return errors.New("a"),
33+
errors.New("b") //errtrace:skip
34+
}

cmd/errtrace/testdata/golden/optout.go.golden

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,12 @@ func Try(problem bool) (int, error) {
2323

2424
return bar.Baz() //errtrace:skip // caller wants unwrapped error
2525
}
26+
27+
func unused() error {
28+
return nil //errtrace:skip // want:"unused errtrace:skip"
29+
}
30+
31+
func multipleReturns() (a, b error) {
32+
return errtrace.Wrap(errors.New("a")),
33+
errors.New("b") //errtrace:skip
34+
}

0 commit comments

Comments
 (0)