From 6751be9645d8d4ae1826704c1f74156acc2b2424 Mon Sep 17 00:00:00 2001 From: Delius Date: Mon, 21 Jan 2019 12:29:36 +0300 Subject: [PATCH] checkers: add hexLiterals (#772) --- checkers/hexLiterals_checker.go | 94 +++++++++++++++++++ .../testdata/hexLiterals/negative_tests.go | 7 ++ .../testdata/hexLiterals/positive_tests.go | 15 +++ 3 files changed, 116 insertions(+) create mode 100644 checkers/hexLiterals_checker.go create mode 100644 checkers/testdata/hexLiterals/negative_tests.go create mode 100644 checkers/testdata/hexLiterals/positive_tests.go diff --git a/checkers/hexLiterals_checker.go b/checkers/hexLiterals_checker.go new file mode 100644 index 000000000..6f24b2980 --- /dev/null +++ b/checkers/hexLiterals_checker.go @@ -0,0 +1,94 @@ +package checkers + +import ( + "go/ast" + "strings" + "unicode" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" + "github.com/go-toolsmith/astp" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "hexLiterals" + info.Tags = []string{"style", "experimental"} + info.Summary = "" + info.Before = ` +x := 0X12 +y := 0xfF` + info.After = ` +x := 0x12 +// (A) +y := 0xff +// (B) +y := 0xFF` + + collection.AddChecker(&info, func(ctx *lintpack.CheckerContext) lintpack.FileWalker { + return astwalk.WalkerForExpr(&hexLiteralChecker{ctx: ctx}) + }) +} + +type hexLiteralChecker struct { + astwalk.WalkHandler + ctx *lintpack.CheckerContext +} + +func (c *hexLiteralChecker) VisitExpr(expr ast.Expr) { + if !astp.IsBasicLit(expr) { + return + } + v := astcast.ToBasicLit(expr) + + if !strings.HasPrefix(v.Value, "0X") && !strings.HasPrefix(v.Value, "0x") { + return + } + + prefix := v.Value[:2] + value := v.Value[2:] + + switch prefix { + case "0X": + if isAnyLetter(value) { + if isGoodHex(value) { + c.ctx.Warn(expr, "Should be 0x%s", value) + return + } + c.ctx.Warn(expr, + "Should be 0x%s or 0x%s", + strings.ToLower(value), + strings.ToUpper(value)) + return + } + + c.ctx.Warn(expr, "Should be 0x%s", value) + case "0x": + if isAnyLetter(value) { + if isGoodHex(value) { + return + } + c.ctx.Warn(expr, + "Should be 0x%s or 0x%s", + strings.ToLower(value), + strings.ToUpper(value)) + return + } + + c.ctx.Warn(expr, "Should be 0x%s", value) + } +} + +func isAnyLetter(s string) bool { + for _, r := range s { + if unicode.IsLetter(r) { + return true + } + } + return false +} + +func isGoodHex(value string) bool { + return value == strings.ToLower(value) || value == strings.ToUpper(value) +} diff --git a/checkers/testdata/hexLiterals/negative_tests.go b/checkers/testdata/hexLiterals/negative_tests.go new file mode 100644 index 000000000..4ebac8dff --- /dev/null +++ b/checkers/testdata/hexLiterals/negative_tests.go @@ -0,0 +1,7 @@ +package checker_test + +func negatives() { + _ = 0xFF + _ = 0xff + _ = "0xfF" +} diff --git a/checkers/testdata/hexLiterals/positive_tests.go b/checkers/testdata/hexLiterals/positive_tests.go new file mode 100644 index 000000000..407a919ed --- /dev/null +++ b/checkers/testdata/hexLiterals/positive_tests.go @@ -0,0 +1,15 @@ +package checker_test + +func someTest() { + /*! Should be 0x12 */ + _ = 0X12 + + /*! Should be 0xff or 0xFF */ + _ = 0xfF + + /*! Should be 0xEE */ + _ = 0XEE + + /*! Should be 0xaa */ + _ = 0Xaa +}