Codebase list golint / 6747134
Merge tag 'upstream/0.0+git20161013.3390df4' into debian/sid New upstream snapshot. Martín Ferrari 7 years ago
9 changed file(s) with 176 addition(s) and 110 deletion(s). Raw diff Collapse all Expand all
00 language: go
11 go:
2 - 1.5
32 - 1.6
3 - 1.7
44
55 install:
66 - go get -t -v ./...
33
44 ## Installation
55
6 Golint requires Go 1.5 or later.
6 Golint requires Go 1.6 or later.
77
88 go get -u github.com/golang/lint/golint
99
182182 f.lintErrorStrings()
183183 f.lintReceiverNames()
184184 f.lintIncDec()
185 f.lintMake()
186185 f.lintErrorReturn()
187186 f.lintUnexportedReturn()
188187 f.lintTimeNames()
188 f.lintContextKeyTypes()
189 f.lintContextArgs()
189190 }
190191
191192 type link string
235236
236237 var gcImporter = gcimporter.Import
237238
238 // importer implements go/types.Importer.
239 // It also implements go/types.ImporterFrom, which was new in Go 1.6,
240 // so vendoring will work.
239 // importer implements go/types.Importer{,From}.
241240 type importer struct {
242241 impFn func(packages map[string]*types.Package, path, srcDir string) (*types.Package, error)
243242 packages map[string]*types.Package
247246 return i.impFn(i.packages, path, "")
248247 }
249248
250 // (importer).ImportFrom is in lint16.go.
249 func (i importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
250 return i.impFn(i.packages, path, srcDir)
251 }
251252
252253 func (p *pkg) typeCheck() error {
253254 config := &types.Config{
727728 // Only add entries that are highly unlikely to be non-initialisms.
728729 // For instance, "ID" is fine (Freudian code is rare), but "AND" is not.
729730 var commonInitialisms = map[string]bool{
731 "ACL": true,
730732 "API": true,
731733 "ASCII": true,
732734 "CPU": true,
761763 "UTF8": true,
762764 "VM": true,
763765 "XML": true,
766 "XMPP": true,
764767 "XSRF": true,
765768 "XSS": true,
766769 }
933936 "0i": true,
934937 }
935938
936 // knownWeakerTypes is a set of types that are commonly used to weaken var declarations.
937 // A common form of var declarations that legitimately mentions an explicit LHS type
938 // is where the LHS type is "weaker" than the exact RHS type, where "weaker" means an
939 // interface compared to a concrete type, or an interface compared to a superset interface.
940 // A canonical example is `var out io.Writer = os.Stdout`.
941 // This is only used when type checking fails to determine the exact types.
942 var knownWeakerTypes = map[string]bool{
943 "io.Reader": true,
944 "io.Writer": true,
945 "proto.Message": true,
946 }
947
948939 // lintVarDecls examines variable declarations. It complains about declarations with
949940 // redundant LHS types that can be inferred from the RHS.
950941 func (f *file) lintVarDecls() {
984975 }
985976 lhsTyp := f.pkg.typeOf(v.Type)
986977 rhsTyp := f.pkg.typeOf(rhs)
987 if lhsTyp != nil && rhsTyp != nil && !types.Identical(lhsTyp, rhsTyp) {
978
979 if !validType(lhsTyp) || !validType(rhsTyp) {
980 // Type checking failed (often due to missing imports).
981 return false
982 }
983
984 if !types.Identical(lhsTyp, rhsTyp) {
988985 // Assignment to a different type is not redundant.
989986 return false
990987 }
10031000 if defType, ok := f.isUntypedConst(rhs); ok && !isIdent(v.Type, defType) {
10041001 return false
10051002 }
1006 // If the LHS is a known weaker type, and we couldn't type check both sides,
1007 // don't warn.
1008 if lhsTyp == nil || rhsTyp == nil {
1009 if knownWeakerTypes[f.render(v.Type)] {
1010 return false
1011 }
1012 }
10131003
10141004 f.errorf(v.Type, 0.8, category("type-inference"), "should omit type %s from declaration of var %s; it will be inferred from the right-hand side", f.render(v.Type), v.Names[0])
10151005 return false
10161006 }
10171007 return true
10181008 })
1009 }
1010
1011 func validType(T types.Type) bool {
1012 return T != nil &&
1013 T != types.Typ[types.Invalid] &&
1014 !strings.Contains(T.String(), "invalid type") // good but not foolproof
10191015 }
10201016
10211017 // lintElses examines else blocks. It complains about any else block whose if block ends in a return.
12161212 })
12171213 }
12181214
1219 var badReceiverNames = map[string]bool{
1220 "me": true,
1221 "this": true,
1222 "self": true,
1223 }
1224
12251215 // lintReceiverNames examines receiver names. It complains about inconsistent
12261216 // names used for the same type and names such as "this".
12271217 func (f *file) lintReceiverNames() {
12411231 f.errorf(n, 1, link(ref), category("naming"), `receiver name should not be an underscore`)
12421232 return true
12431233 }
1244 if badReceiverNames[name] {
1245 f.errorf(n, 1, link(ref), category("naming"), `receiver name should be a reflection of its identity; don't use generic names such as "me", "this", or "self"`)
1234 if name == "this" || name == "self" {
1235 f.errorf(n, 1, link(ref), category("naming"), `receiver name should be a reflection of its identity; don't use generic names such as "this" or "self"`)
12461236 return true
12471237 }
12481238 recv := receiverType(fn)
12791269 return true
12801270 }
12811271 f.errorf(as, 0.8, category("unary-op"), "should replace %s with %s%s", f.render(as), f.render(as.Lhs[0]), suffix)
1282 return true
1283 })
1284 }
1285
1286 // lintMake examines statements that declare and initialize a variable with make.
1287 // It complains if they are constructing a zero element slice.
1288 func (f *file) lintMake() {
1289 f.walk(func(n ast.Node) bool {
1290 as, ok := n.(*ast.AssignStmt)
1291 if !ok {
1292 return true
1293 }
1294 // Only want single var := assignment statements.
1295 if len(as.Lhs) != 1 || as.Tok != token.DEFINE {
1296 return true
1297 }
1298 ce, ok := as.Rhs[0].(*ast.CallExpr)
1299 if !ok {
1300 return true
1301 }
1302 // Check if ce is make([]T, 0).
1303 if !isIdent(ce.Fun, "make") || len(ce.Args) != 2 || !isZero(ce.Args[1]) {
1304 return true
1305 }
1306 at, ok := ce.Args[0].(*ast.ArrayType)
1307 if !ok || at.Len != nil {
1308 return true
1309 }
1310 f.errorf(as, 0.8, category("slice"), `can probably use "var %s %s" instead`, f.render(as.Lhs[0]), f.render(at))
13111272 return true
13121273 })
13131274 }
14351396 })
14361397 }
14371398
1399 // lintContextKeyTypes checks for call expressions to context.WithValue with
1400 // basic types used for the key argument.
1401 // See: https://golang.org/issue/17293
1402 func (f *file) lintContextKeyTypes() {
1403 f.walk(func(node ast.Node) bool {
1404 switch node := node.(type) {
1405 case *ast.CallExpr:
1406 f.checkContextKeyType(node)
1407 }
1408
1409 return true
1410 })
1411 }
1412
1413 // checkContextKeyType reports an error if the call expression calls
1414 // context.WithValue with a key argument of basic type.
1415 func (f *file) checkContextKeyType(x *ast.CallExpr) {
1416 sel, ok := x.Fun.(*ast.SelectorExpr)
1417 if !ok {
1418 return
1419 }
1420 pkg, ok := sel.X.(*ast.Ident)
1421 if !ok || pkg.Name != "context" {
1422 return
1423 }
1424 if sel.Sel.Name != "WithValue" {
1425 return
1426 }
1427
1428 // key is second argument to context.WithValue
1429 if len(x.Args) != 3 {
1430 return
1431 }
1432 key := f.pkg.typesInfo.Types[x.Args[1]]
1433
1434 if _, ok := key.Type.(*types.Basic); ok {
1435 f.errorf(x, 1.0, category("context"), fmt.Sprintf("should not use basic type %s as key in context.WithValue", key.Type))
1436 }
1437 }
1438
1439 // lintContextArgs examines function declarations that contain an
1440 // argument with a type of context.Context
1441 // It complains if that argument isn't the first parameter.
1442 func (f *file) lintContextArgs() {
1443 f.walk(func(n ast.Node) bool {
1444 fn, ok := n.(*ast.FuncDecl)
1445 if !ok || len(fn.Type.Params.List) <= 1 {
1446 return true
1447 }
1448 // A context.Context should be the first parameter of a function.
1449 // Flag any that show up after the first.
1450 for _, arg := range fn.Type.Params.List[1:] {
1451 if isPkgDot(arg.Type, "context", "Context") {
1452 f.errorf(fn, 0.9, link("https://golang.org/pkg/context/"), category("arg-order"), "context.Context should be the first parameter of a function")
1453 break // only flag one
1454 }
1455 }
1456 return true
1457 })
1458 }
1459
1460 // receiverType returns the named type of the method receiver, sans "*",
1461 // or "invalid-type" if fn.Recv is ill formed.
14381462 func receiverType(fn *ast.FuncDecl) string {
14391463 switch e := fn.Recv.List[0].Type.(type) {
14401464 case *ast.Ident:
14411465 return e.Name
14421466 case *ast.StarExpr:
1443 return e.X.(*ast.Ident).Name
1444 }
1445 panic(fmt.Sprintf("unknown method receiver AST node type %T", fn.Recv.List[0].Type))
1467 if id, ok := e.X.(*ast.Ident); ok {
1468 return id.Name
1469 }
1470 }
1471 // The parser accepts much more than just the legal forms.
1472 return "invalid-type"
14461473 }
14471474
14481475 func (f *file) walk(fn func(ast.Node) bool) {
+0
-17
lint16.go less more
0 // Copyright (c) 2016 The Go Authors. All rights reserved.
1 //
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file or at
4 // https://developers.google.com/open-source/licenses/bsd.
5
6 // +build go1.6
7
8 package lint
9
10 import "go/types"
11
12 // This is in its own file so it can be ignored under Go 1.5.
13
14 func (i importer) ImportFrom(path, srcDir string, mode types.ImportMode) (*types.Package, error) {
15 return i.impFn(i.packages, path, srcDir)
16 }
0 // Test that context.Context is the first arg to a function.
1
2 // Package foo ...
3 package foo
4
5 import (
6 "context"
7 )
8
9 // A proper context.Context location
10 func x(ctx context.Context) { // ok
11 }
12
13 // A proper context.Context location
14 func x(ctx context.Context, s string) { // ok
15 }
16
17 // An invalid context.Context location
18 func y(s string, ctx context.Context) { // MATCH /context.Context should be the first parameter.*/
19 }
20
21 // An invalid context.Context location with more than 2 args
22 func y(s string, r int, ctx context.Context, x int) { // MATCH /context.Context should be the first parameter.*/
23 }
0 // Package contextkeytypes verifies that correct types are used as keys in
1 // calls to context.WithValue.
2 package contextkeytypes
3
4 import (
5 "context"
6 "fmt"
7 )
8
9 type ctxKey struct{}
10
11 func contextKeyTypeTests() {
12 fmt.Println() // not in package context
13 context.TODO() // wrong function
14 c := context.Background() // wrong function
15 context.WithValue(c, "foo", "bar") // MATCH /should not use basic type( untyped|)? string as key in context.WithValue/
16 context.WithValue(c, true, "bar") // MATCH /should not use basic type( untyped|)? bool as key in context.WithValue/
17 context.WithValue(c, 1, "bar") // MATCH /should not use basic type( untyped|)? int as key in context.WithValue/
18 context.WithValue(c, int8(1), "bar") // MATCH /should not use basic type int8 as key in context.WithValue/
19 context.WithValue(c, int16(1), "bar") // MATCH /should not use basic type int16 as key in context.WithValue/
20 context.WithValue(c, int32(1), "bar") // MATCH /should not use basic type int32 as key in context.WithValue/
21 context.WithValue(c, rune(1), "bar") // MATCH /should not use basic type rune as key in context.WithValue/
22 context.WithValue(c, int64(1), "bar") // MATCH /should not use basic type int64 as key in context.WithValue/
23 context.WithValue(c, uint(1), "bar") // MATCH /should not use basic type uint as key in context.WithValue/
24 context.WithValue(c, uint8(1), "bar") // MATCH /should not use basic type uint8 as key in context.WithValue/
25 context.WithValue(c, byte(1), "bar") // MATCH /should not use basic type byte as key in context.WithValue/
26 context.WithValue(c, uint16(1), "bar") // MATCH /should not use basic type uint16 as key in context.WithValue/
27 context.WithValue(c, uint32(1), "bar") // MATCH /should not use basic type uint32 as key in context.WithValue/
28 context.WithValue(c, uint64(1), "bar") // MATCH /should not use basic type uint64 as key in context.WithValue/
29 context.WithValue(c, uintptr(1), "bar") // MATCH /should not use basic type uintptr as key in context.WithValue/
30 context.WithValue(c, float32(1.0), "bar") // MATCH /should not use basic type float32 as key in context.WithValue/
31 context.WithValue(c, float64(1.0), "bar") // MATCH /should not use basic type float64 as key in context.WithValue/
32 context.WithValue(c, complex64(1i), "bar") // MATCH /should not use basic type complex64 as key in context.WithValue/
33 context.WithValue(c, complex128(1i), "bar") // MATCH /should not use basic type complex128 as key in context.WithValue/
34 context.WithValue(c, ctxKey{}, "bar") // ok
35 context.WithValue(c, &ctxKey{}, "bar") // ok
36 }
+0
-19
testdata/make.go less more
0 // Test for pointless make() calls.
1
2 // Package pkg ...
3 package pkg
4
5 import "net/http"
6
7 // T is a test type.
8 type T int
9
10 var z []T
11
12 func f() {
13 x := make([]T, 0) // MATCH /var x \[\]T/
14 y := make([]http.Request, 0) // MATCH /var y \[\]http\.Request/
15 z = make([]T, 0) // ok, because we don't know where z is declared
16
17 _, _ = x, y
18 }
3838
3939 func (_ *bar) f7() { // MATCH /receiver name should not be an underscore/
4040 }
41
42 type multiError struct{}
43
44 func (me multiError) f8() {
45 }
46
47 // Regression test for a panic caused by ill-formed receiver type.
48 func (recv []*x.y) f()
22 // Package foo ...
33 package foo
44
5 import "fmt"
6 import "net/http"
5 import (
6 "fmt"
7 "io"
8 "net/http"
9 "nosuchpkg" // export data unavailable
10 "os"
11 )
712
813 // Q is a test type.
914 type Q bool
6267 // LHS is a different type than the RHS.
6368 var myStringer fmt.Stringer = q(0)
6469
65 // We don't figure out the true types of LHS and RHS here,
66 // but io.Writer is a known weaker type for many common uses,
67 // so the suggestion should be suppressed here.
70 // LHS is a different type than the RHS.
6871 var out io.Writer = os.Stdout
6972
70 // This next one, however, should be type checked.
71 var out2 io.Writer = newWriter() // MATCH /should.*io\.Writer/
73 var out2 io.Writer = newWriter() // MATCH /should omit.*io\.Writer/
7274
7375 func newWriter() io.Writer { return nil }
76
77 // We don't figure out the true types of LHS and RHS here,
78 // so we suppress the check.
79 var ni nosuchpkg.Interface = nosuchpkg.NewConcrete()
7480
7581 var y string = q(1).String() // MATCH /should.*string/
7682