1
0
mirror of https://github.com/mgechev/revive.git synced 2025-03-21 21:17:06 +02:00

String of int (#342)

* string-of-int: working version

* adds doc of string-to-int
This commit is contained in:
SalvadorC 2020-02-18 18:38:01 +01:00 committed by GitHub
parent 9c5528e4f7
commit a24e8e7b81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 145 additions and 0 deletions

View File

@ -347,6 +347,7 @@ List of all available rules. The rules ported from `golint` are left unchanged a
| [`unused-receiver`](./RULES_DESCRIPTIONS.md#unused-receiver) | n/a | Suggests to rename or remove unused method receivers | no | no |
| [`unhandled-error`](./RULES_DESCRIPTIONS.md#unhandled-error) | []string | Warns on unhandled errors returned by funcion calls | no | yes |
| [`cognitive-complexity`](./RULES_DESCRIPTIONS.md#cognitive-complexity) | int | Sets restriction for maximum Cognitive complexity. | no | no |
| [`string-of-int`](./RULES_DESCRIPTIONS.md#string-of-int) | n/a | Warns on suspicious casts from int to string | no | yes |
## Configurable rules

View File

@ -46,6 +46,7 @@ List of all available rules.
- [range-val-in-closure](#range-val-in-closure)
- [receiver-naming](#receiver-naming)
- [redefines-builtin-id](#redefines-builtin-id)
- [string-of-int](#string-of-int)
- [struct-tag](#struct-tag)
- [superfluous-else](#superfluous-else)
- [time-naming](#time-naming)
@ -406,6 +407,11 @@ Even if possible, redefining these built in names can lead to bugs very difficul
_Configuration_: N/A
## string-of-int
_Description_: explicit type conversion `string(i)` where `i` has an integer type other than `rune` might behave not as expected by the developer (e.g. `string(42)` is not `"42"`). This rule spot that kind of suspicious conversions.
_Configuration_: N/A
## struct-tag
_Description_: Struct tags are not checked at compile time.

View File

@ -81,6 +81,7 @@ var allRules = append([]lint.Rule{
&rule.UnusedReceiverRule{},
&rule.UnhandledErrorRule{},
&rule.CognitiveComplexityRule{},
&rule.StringOfIntRule{},
}, defaultRules...)
var allFormatters = []lint.Formatter{

30
fixtures/string-of-int.go Normal file
View File

@ -0,0 +1,30 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package fixtures
type A string
type B = string
type C int
type D = uintptr
func StringTest() {
var (
i int
j rune
k byte
l C
m D
n = []int{0, 1, 2}
o struct{ x int }
)
const p = 0
_ = string(i) // MATCH /dubious convertion of an integer into a string, use strconv.Itoa/
_ = string(j)
_ = string(k)
_ = string(p) // MATCH /dubious convertion of an integer into a string, use strconv.Itoa/
_ = A(l) // MATCH /dubious convertion of an integer into a string, use strconv.Itoa/
_ = B(m) // MATCH /dubious convertion of an integer into a string, use strconv.Itoa/
_ = string(n[1]) // MATCH /dubious convertion of an integer into a string, use strconv.Itoa/
_ = string(o.x) // MATCH /dubious convertion of an integer into a string, use strconv.Itoa/
}

95
rule/string-of-int.go Normal file
View File

@ -0,0 +1,95 @@
package rule
import (
"go/ast"
"go/types"
"github.com/mgechev/revive/lint"
)
// StringOfIntRule warns when logic expressions contains Boolean literals.
type StringOfIntRule struct{}
// Apply applies the rule to given file.
func (r *StringOfIntRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure {
var failures []lint.Failure
onFailure := func(failure lint.Failure) {
failures = append(failures, failure)
}
astFile := file.AST
file.Pkg.TypeCheck()
w := &lintStringInt{file, onFailure}
ast.Walk(w, astFile)
return failures
}
// Name returns the rule name.
func (r *StringOfIntRule) Name() string {
return "string-of-int"
}
type lintStringInt struct {
file *lint.File
onFailure func(lint.Failure)
}
func (w *lintStringInt) Visit(node ast.Node) ast.Visitor {
ce, ok := node.(*ast.CallExpr)
if !ok {
return w
}
if !w.isCallStringCast(ce.Fun) {
return w
}
if !w.isIntExpression(ce.Args) {
return w
}
w.onFailure(lint.Failure{
Confidence: 1,
Node: ce,
Failure: "dubious convertion of an integer into a string, use strconv.Itoa",
})
return w
}
func (w *lintStringInt) isCallStringCast(e ast.Expr) bool {
t := w.file.Pkg.TypeOf(e)
if t == nil {
return false
}
tb, _ := t.Underlying().(*types.Basic)
return tb != nil && tb.Kind() == types.String
}
func (w *lintStringInt) isIntExpression(es []ast.Expr) bool {
if len(es) != 1 {
return false
}
t := w.file.Pkg.TypeOf(es[0])
if t == nil {
return false
}
ut, _ := t.Underlying().(*types.Basic)
if ut == nil || ut.Info()&types.IsInteger == 0 {
return false
}
switch ut.Kind() {
case types.Byte, types.Rune, types.UntypedRune:
return false
}
return true
}

12
test/string-of-int.go Normal file
View File

@ -0,0 +1,12 @@
package test
import (
"testing"
"github.com/mgechev/revive/rule"
)
// String-of-int rule.
func TestStringOfInt(t *testing.T) {
testRule(t, "string-of-int", &rule.StringOfIntRule{})
}