griesemer / tryhard

tryhard finds and rewrites code suitable for try.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

consider counting and listing instances of uniform error handling within a func

thepudds opened this issue · comments

As far as I understand, this first-cut version of tryhard currently undercounts possible uses of try because tryhard does not look for cases of uniform error handling within a function.

Consider reporting at least certain classes of uniform error handling within a function.

These would be candidates for try + defer. Actually re-writing to use defer could be left as an exercise for the reader.

For example, it would be nice to identify f() and g() below as each having two candidate locations for try:

// f uses a function literal to annotate errors uniformly
func f(arg int) error {
	report := func(err error) error { return fmt.Errorf("f failed for %v: %v", arg, err) }

	err := g(arg)
	if err != nil {
		return report(err)
	}

	err = h(arg)
	if err != nil {
		return report(err)
	}
	return nil
}

// g uses repeated code (e.g., copy/paste) to annotate errors uniformly
func g(arg int) error {
	err := h(arg)
	if err != nil {
		return fmt.Errorf("g failed for %v: %v", arg, err)
	}

	err = f(arg)
	if err != nil {
		return fmt.Errorf("g failed with %v: %v", arg, err)
	}
	return nil
}

func h(arg int) error {
	return nil
}

This is a variation (I think?) of the suggestions in golang/go#32437 (comment).

I encountered this as well while tryhard'ing my own code; see golang/go#32437 (comment).

@thepudds Just FYI, in your example above, g has different error returns - the format string is not the same in both cases.

Anyway, I just uploaded a new version of tryhard that recognizes these cases. Note that there is a significant change of false positives for that new count. If a function has shared error returns they will be reported but if there are other error returns that don't fit the try pattern, using a defer may not be straight-forward.

Closing. try proposal was abandoned.