Skip to content

Instantly share code, notes, and snippets.

@seamusv
Last active October 1, 2020 20:59
Show Gist options
  • Save seamusv/b70175cfbc090310efbb8021cc929892 to your computer and use it in GitHub Desktop.
Save seamusv/b70175cfbc090310efbb8021cc929892 to your computer and use it in GitHub Desktop.
Logger Linter
package main
import (
"fmt"
"go/ast"
"golang.org/x/tools/go/analysis"
"golang.org/x/tools/go/analysis/singlechecker"
)
var Analyzer = &analysis.Analyzer{
Name: "checklogger",
Doc: "Verifies that the logger has the proper function name declared",
Run: run,
}
func run(pass *analysis.Pass) (interface{}, error) {
for _, file := range pass.Files {
ast.Inspect(file, func(fileNode ast.Node) bool {
if funcDecl, ok := fileNode.(*ast.FuncDecl); ok {
ast.Inspect(funcDecl.Body, func(bodyNode ast.Node) bool {
if localLog, ok := bodyNode.(*ast.AssignStmt); ok && isLocalLog(localLog) {
var found = false
ast.Inspect(localLog, func(logNode ast.Node) bool {
if selectorExpr, ok := logNode.(*ast.SelectorExpr); ok && selectorExpr.Sel.Name == "Str" {
if callExpr, ok := selectorExpr.X.(*ast.CallExpr); ok && len(callExpr.Args) == 2 {
if var1, ok := callExpr.Args[0].(*ast.BasicLit); ok && var1.Value == "\"function\"" {
found = true
functionValue := callExpr.Args[1].(*ast.BasicLit).Value
if functionValue != fmt.Sprintf("\"%s\"", funcDecl.Name.Name) {
pass.Reportf(callExpr.Args[1].Pos(), "Function is mislabeled and should be \"%s\"", funcDecl.Name.Name)
}
}
}
}
return true
})
if !found {
pass.Reportf(localLog.Pos(), "Logger is missing 'function' field declaration")
}
}
return true
})
}
return true
})
}
return nil, nil
}
func isLocalLog(n *ast.AssignStmt) bool {
for _, expr := range n.Lhs {
if value, ok := expr.(*ast.Ident); ok && value.Name == "localLog" {
return true
}
}
return false
}
func main() {
singlechecker.Main(Analyzer)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment