github.com/Johnny2210/revive@v1.0.8-0.20210625134200-febf37ccd0f5/rule/unexported-naming.go (about) 1 package rule 2 3 import ( 4 "fmt" 5 "go/ast" 6 "go/token" 7 8 "github.com/mgechev/revive/lint" 9 ) 10 11 // UnexportedNamingRule lints wrongly named unexported symbols. 12 type UnexportedNamingRule struct{} 13 14 // Apply applies the rule to given file. 15 func (r *UnexportedNamingRule) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { 16 var failures []lint.Failure 17 onFailure := func(failure lint.Failure) { 18 failures = append(failures, failure) 19 } 20 21 ba := &unexportablenamingLinter{onFailure} 22 ast.Walk(ba, file.AST) 23 24 return failures 25 } 26 27 // Name returns the rule name. 28 func (r *UnexportedNamingRule) Name() string { 29 return "unexported-naming" 30 } 31 32 type unexportablenamingLinter struct { 33 onFailure func(lint.Failure) 34 } 35 36 func (unl unexportablenamingLinter) Visit(node ast.Node) ast.Visitor { 37 switch n := node.(type) { 38 case *ast.FuncDecl: 39 unl.lintFunction(n.Type, n.Body) 40 return nil 41 case *ast.FuncLit: 42 unl.lintFunction(n.Type, n.Body) 43 44 return nil 45 case *ast.AssignStmt: 46 if n.Tok != token.DEFINE { 47 return nil 48 } 49 50 ids := []*ast.Ident{} 51 for _, e := range n.Lhs { 52 id, ok := e.(*ast.Ident) 53 if !ok { 54 continue 55 } 56 ids = append(ids, id) 57 } 58 59 unl.lintIDs(ids) 60 61 case *ast.DeclStmt: 62 gd, ok := n.Decl.(*ast.GenDecl) 63 if !ok { 64 return nil 65 } 66 67 if len(gd.Specs) < 1 { 68 return nil 69 } 70 71 vs, ok := gd.Specs[0].(*ast.ValueSpec) 72 if !ok { 73 return nil 74 } 75 76 unl.lintIDs(vs.Names) 77 } 78 79 return unl 80 } 81 82 func (unl unexportablenamingLinter) lintFunction(ft *ast.FuncType, body *ast.BlockStmt) { 83 unl.lintFields(ft.Params) 84 unl.lintFields(ft.Results) 85 86 if body != nil { 87 ast.Walk(unl, body) 88 } 89 } 90 91 func (unl unexportablenamingLinter) lintFields(fields *ast.FieldList) { 92 if fields == nil { 93 return 94 } 95 96 ids := []*ast.Ident{} 97 for _, field := range fields.List { 98 ids = append(ids, field.Names...) 99 } 100 101 unl.lintIDs(ids) 102 } 103 104 func (unl unexportablenamingLinter) lintIDs(ids []*ast.Ident) { 105 for _, id := range ids { 106 if id.IsExported() { 107 unl.onFailure(lint.Failure{ 108 Node: id, 109 Confidence: 1, 110 Category: "naming", 111 Failure: fmt.Sprintf("the symbol %s is local, its name should start with a lowercase letter", id.String()), 112 }) 113 } 114 } 115 }