diff --git a/checkers/hexLiteral_checker.go b/checkers/hexLiteral_checker.go new file mode 100644 index 000000000..8216417a8 --- /dev/null +++ b/checkers/hexLiteral_checker.go @@ -0,0 +1,60 @@ +package checkers + +import ( + "go/ast" + "go/token" + "strings" + + "github.com/go-lintpack/lintpack" + "github.com/go-lintpack/lintpack/astwalk" + "github.com/go-toolsmith/astcast" +) + +func init() { + var info lintpack.CheckerInfo + info.Name = "hexLiteral" + 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) warn0X(lit *ast.BasicLit) { + suggest := "0x" + lit.Value[len("0X"):] + c.ctx.Warn(lit, "prefer 0x over 0X, s/%s/%s/", lit.Value, suggest) +} + +func (c *hexLiteralChecker) warnMixedDigits(lit *ast.BasicLit) { + c.ctx.Warn(lit, "don't mix hex literal letter digits casing") +} + +func (c *hexLiteralChecker) VisitExpr(expr ast.Expr) { + lit := astcast.ToBasicLit(expr) + if lit.Kind != token.INT || len(lit.Value) < 3 { + return + } + if strings.HasPrefix(lit.Value, "0X") { + c.warn0X(lit) + return + } + digits := lit.Value[len("0x"):] + if strings.ToLower(digits) != digits && strings.ToUpper(digits) != digits { + c.warnMixedDigits(lit) + } +} diff --git a/checkers/hexLiterals_checker.go b/checkers/hexLiterals_checker.go deleted file mode 100644 index 6f24b2980..000000000 --- a/checkers/hexLiterals_checker.go +++ /dev/null @@ -1,94 +0,0 @@ -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/hexLiteral/negative_tests.go b/checkers/testdata/hexLiteral/negative_tests.go new file mode 100644 index 000000000..dcc1bd224 --- /dev/null +++ b/checkers/testdata/hexLiteral/negative_tests.go @@ -0,0 +1,23 @@ +package checker_test + +func negatives() { + _ = 0xFF + _ = 0xff + _ = "0xfF" +} + +func noLetters() { + _ = 0x11 + _ = 0x0 +} + +func digitsAndLetters() { + _ = 0x1aa + _ = 0x1AA +} + +func decimals() { + _ = 1 + _ = 10 + _ = 12345 +} diff --git a/checkers/testdata/hexLiteral/positive_tests.go b/checkers/testdata/hexLiteral/positive_tests.go new file mode 100644 index 000000000..da62101a9 --- /dev/null +++ b/checkers/testdata/hexLiteral/positive_tests.go @@ -0,0 +1,23 @@ +package checker_test + +func bad0X() { + /*! prefer 0x over 0X, s/0X12/0x12/ */ + _ = 0X12 + /*! prefer 0x over 0X, s/0XEE/0xEE/ */ + _ = 0XEE + /*! prefer 0x over 0X, s/0Xaa/0xaa/ */ + _ = 0Xaa +} + +func mixedLetterDigits() { + /*! don't mix hex literal letter digits casing */ + _ = 0xfF + /*! don't mix hex literal letter digits casing */ + _ = 0xFf + /*! don't mix hex literal letter digits casing */ + _ = 0x11f0F + /*! don't mix hex literal letter digits casing */ + _ = 0xff11FF + /*! don't mix hex literal letter digits casing */ + _ = 0xabcdE +} diff --git a/checkers/testdata/hexLiterals/negative_tests.go b/checkers/testdata/hexLiterals/negative_tests.go deleted file mode 100644 index 4ebac8dff..000000000 --- a/checkers/testdata/hexLiterals/negative_tests.go +++ /dev/null @@ -1,7 +0,0 @@ -package checker_test - -func negatives() { - _ = 0xFF - _ = 0xff - _ = "0xfF" -} diff --git a/checkers/testdata/hexLiterals/positive_tests.go b/checkers/testdata/hexLiterals/positive_tests.go deleted file mode 100644 index 407a919ed..000000000 --- a/checkers/testdata/hexLiterals/positive_tests.go +++ /dev/null @@ -1,15 +0,0 @@ -package checker_test - -func someTest() { - /*! Should be 0x12 */ - _ = 0X12 - - /*! Should be 0xff or 0xFF */ - _ = 0xfF - - /*! Should be 0xEE */ - _ = 0XEE - - /*! Should be 0xaa */ - _ = 0Xaa -}