Skip to content

Instantly share code, notes, and snippets.

@jbardin
Last active November 21, 2019 14:27
Show Gist options
  • Save jbardin/e2103a51972e108809a3b01752a52562 to your computer and use it in GitHub Desktop.
Save jbardin/e2103a51972e108809a3b01752a52562 to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"go/ast"
"go/token"
"go/types"
"strings"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/passes/inspect"
"golang.org/x/tools/go/analysis/unitchecker"
"golang.org/x/tools/go/ast/inspector"
)
var Analyzer = &analysis.Analyzer{
Name: "diags",
Doc: "check for diagnostic assignments to error variables",
Requires: []*analysis.Analyzer{inspect.Analyzer},
Run: run,
}
func run(pass *analysis.Pass) (interface{}, error) {
inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
nodeFilter := []ast.Node{
(*ast.AssignStmt)(nil),
}
inspect.Preorder(nodeFilter, func(n ast.Node) {
stmt := n.(*ast.AssignStmt)
if stmt.Tok != token.DEFINE {
return // ignore =
}
for _, x := range stmt.Lhs {
id, isId := x.(*ast.Ident)
if !isId {
continue
}
// any e, err, myErr, etc
if !(id.Name == "e" || strings.Contains(id.Name, "err") || strings.Contains(id.Name, "Err")) {
continue
}
def := pass.TypesInfo.Defs[id]
if def == nil {
continue
}
named, ok := def.Type().(*types.Named)
if !ok {
continue
}
typeName := named.Obj().Name()
if strings.HasPrefix(typeName, "Diagnostic") {
pass.Reportf(stmt.Pos(), fmt.Sprintf("%s type assigned to variable named %q", typeName, id.Name))
}
}
})
return nil, nil
}
func main() {
unitchecker.Main(Analyzer)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment