From 81d85b505d4d3be2f67cb8d163f6999123dec056 Mon Sep 17 00:00:00 2001 From: chavacava Date: Tue, 16 May 2023 10:31:25 +0200 Subject: [PATCH] fix #824 (#829) --- rule/nested-structs.go | 70 ++++++++++++++++++-------------------- testdata/nested-structs.go | 17 +++++++++ 2 files changed, 51 insertions(+), 36 deletions(-) diff --git a/rule/nested-structs.go b/rule/nested-structs.go index fd1226991..147bd482b 100644 --- a/rule/nested-structs.go +++ b/rule/nested-structs.go @@ -14,7 +14,6 @@ func (*NestedStructs) Apply(file *lint.File, _ lint.Arguments) []lint.Failure { var failures []lint.Failure walker := &lintNestedStructs{ - fileAST: file.AST, onFailure: func(failure lint.Failure) { failures = append(failures, failure) }, @@ -31,47 +30,46 @@ func (*NestedStructs) Name() string { } type lintNestedStructs struct { - fileAST *ast.File onFailure func(lint.Failure) } func (l *lintNestedStructs) Visit(n ast.Node) ast.Visitor { - switch v := n.(type) { - case *ast.TypeSpec: - _, isInterface := v.Type.(*ast.InterfaceType) - if isInterface { - return nil // do not analyze interface declarations - } - case *ast.FuncDecl: - if v.Body != nil { - ast.Walk(l, v.Body) - } - return nil - case *ast.Field: - _, isChannelField := v.Type.(*ast.ChanType) - if isChannelField { - return nil - } + if v, ok := n.(*ast.StructType); ok { + ls := &lintStruct{l.onFailure} + ast.Walk(ls, v.Fields) + } - filter := func(n ast.Node) bool { - switch n.(type) { - case *ast.StructType: - return true - default: - return false - } - } - structs := pick(v, filter, nil) - for _, s := range structs { - l.onFailure(lint.Failure{ - Failure: "no nested structs are allowed", - Category: "style", - Node: s, - Confidence: 1, - }) + return l +} + +type lintStruct struct { + onFailure func(lint.Failure) +} + +func (l *lintStruct) Visit(n ast.Node) ast.Visitor { + switch s := n.(type) { + case *ast.StructType: + l.fail(s) + return nil + case *ast.ArrayType: + if _, ok := s.Elt.(*ast.StructType); ok { + l.fail(s) } - return nil // no need to visit (again) the field + return nil + case *ast.ChanType: + return nil + case *ast.MapType: + return nil + default: + return l } +} - return l +func (l *lintStruct) fail(n ast.Node) { + l.onFailure(lint.Failure{ + Failure: "no nested structs are allowed", + Category: "style", + Node: n, + Confidence: 1, + }) } diff --git a/testdata/nested-structs.go b/testdata/nested-structs.go index b1e1102b8..18f5e2d3a 100644 --- a/testdata/nested-structs.go +++ b/testdata/nested-structs.go @@ -18,6 +18,17 @@ type Quux struct { type Quuz struct { } +type Quiz struct { + s struct{} // MATCH /no nested structs are allowed/ +} + +type nestedStructInChan struct { + c chan struct { + a int + b struct{ c int } // MATCH /no nested structs are allowed/ + } +} + func waldo() (s struct{ b bool }) { return s } func fred() interface{} { @@ -45,3 +56,9 @@ type issue744 struct { type mySetInterface interface { GetSet() map[string]struct{} } + +// issue 824 +type test struct { + foo []chan struct{} // Must not match + bar map[string]struct{} // Must not match +}