Skip to content

Commit c61f43f

Browse files
manuelarteldez
andauthored
feat: add embeddedstructfieldcheck linter (#5761)
Co-authored-by: Fernandez Ludovic <ldez@users.noreply.github.com>
1 parent b24761d commit c61f43f

14 files changed

+252
-0
lines changed

.golangci.next.reference.yml

+2
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ linters:
3333
- dupl
3434
- dupword
3535
- durationcheck
36+
- embeddedstructfieldcheck
3637
- err113
3738
- errcheck
3839
- errchkjson
@@ -142,6 +143,7 @@ linters:
142143
- dupl
143144
- dupword
144145
- durationcheck
146+
- embeddedstructfieldcheck
145147
- err113
146148
- errcheck
147149
- errchkjson

go.mod

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ require (
7474
github.com/ldez/usetesting v0.4.3
7575
github.com/leonklingele/grouper v1.1.2
7676
github.com/macabu/inamedparam v0.2.0
77+
github.com/manuelarte/embeddedstructfieldcheck v0.2.1
7778
github.com/manuelarte/funcorder v0.5.0
7879
github.com/maratori/testableexamples v1.0.0
7980
github.com/maratori/testpackage v1.1.1

go.sum

+2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

jsonschema/golangci.next.jsonschema.json

+1
Original file line numberDiff line numberDiff line change
@@ -734,6 +734,7 @@
734734
"dupl",
735735
"dupword",
736736
"durationcheck",
737+
"embeddedstructfieldcheck",
737738
"errcheck",
738739
"errchkjson",
739740
"errname",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package embeddedstructfieldcheck
2+
3+
import (
4+
"github.com/manuelarte/embeddedstructfieldcheck/analyzer"
5+
"golang.org/x/tools/go/analysis"
6+
7+
"github.com/golangci/golangci-lint/v2/pkg/goanalysis"
8+
)
9+
10+
func New() *goanalysis.Linter {
11+
a := analyzer.NewAnalyzer()
12+
13+
return goanalysis.NewLinter(
14+
a.Name,
15+
a.Doc,
16+
[]*analysis.Analyzer{a},
17+
nil,
18+
).WithLoadMode(goanalysis.LoadModeSyntax)
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package embeddedstructfieldcheck
2+
3+
import (
4+
"testing"
5+
6+
"github.com/golangci/golangci-lint/v2/test/testshared/integration"
7+
)
8+
9+
func TestFromTestdata(t *testing.T) {
10+
integration.RunTestdata(t)
11+
}
12+
13+
func TestFix(t *testing.T) {
14+
integration.RunFix(t)
15+
}
16+
17+
func TestFixPathPrefix(t *testing.T) {
18+
integration.RunFixPathPrefix(t)
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
package simple
3+
4+
import "time"
5+
6+
type ValidStructWithSingleLineComments struct {
7+
// time.Time Single line comment
8+
time.Time
9+
10+
// version Single line comment
11+
version int
12+
}
13+
14+
type StructWithSingleLineComments struct {
15+
// time.Time Single line comment
16+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
17+
// version Single line comment
18+
version int
19+
}
20+
21+
type StructWithMultiLineComments struct {
22+
// time.Time Single line comment
23+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
24+
// version Single line comment
25+
// very long comment
26+
version int
27+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
package simple
3+
4+
import (
5+
"context"
6+
"time"
7+
)
8+
9+
type ValidStruct struct {
10+
time.Time
11+
12+
version int
13+
}
14+
15+
type NoSpaceStruct struct {
16+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
17+
version int
18+
}
19+
20+
type NotSortedStruct struct {
21+
version int
22+
23+
time.Time // want `embedded fields should be listed before regular fields`
24+
}
25+
26+
type MixedEmbeddedAndNotEmbedded struct {
27+
context.Context
28+
29+
name string
30+
31+
time.Time // want `embedded fields should be listed before regular fields`
32+
33+
age int
34+
}
35+
36+
type EmbeddedWithPointers struct {
37+
*time.Time // want `there must be an empty line separating embedded fields from regular fields`
38+
version int
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
package simple
3+
4+
import "time"
5+
6+
func myFunction() {
7+
type myType struct {
8+
version int
9+
time.Time // want `embedded fields should be listed before regular fields`
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
//golangcitest:expected_exitcode 0
3+
package testdata
4+
5+
import "time"
6+
7+
type ValidStructWithSingleLineComments struct {
8+
// time.Time Single line comment
9+
time.Time
10+
11+
// version Single line comment
12+
version int
13+
}
14+
15+
type StructWithSingleLineComments struct {
16+
// time.Time Single line comment
17+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
18+
19+
// version Single line comment
20+
version int
21+
}
22+
23+
type StructWithMultiLineComments struct {
24+
// time.Time Single line comment
25+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
26+
27+
// version Single line comment
28+
// very long comment
29+
version int
30+
}
31+
32+
type A struct {
33+
// comment
34+
ValidStructWithSingleLineComments
35+
// C is foo
36+
StructWithSingleLineComments // want `there must be an empty line separating embedded fields from regular fields`
37+
38+
D string
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
//golangcitest:expected_exitcode 0
3+
package testdata
4+
5+
import (
6+
"time"
7+
)
8+
9+
type ValidStruct struct {
10+
time.Time
11+
12+
version int
13+
}
14+
15+
type NoSpaceStruct struct {
16+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
17+
version int
18+
}
19+
20+
type EmbeddedWithPointers struct {
21+
*time.Time // want `there must be an empty line separating embedded fields from regular fields`
22+
version int
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
//golangcitest:expected_exitcode 0
3+
package testdata
4+
5+
import "time"
6+
7+
type ValidStructWithSingleLineComments struct {
8+
// time.Time Single line comment
9+
time.Time
10+
11+
// version Single line comment
12+
version int
13+
}
14+
15+
type StructWithSingleLineComments struct {
16+
// time.Time Single line comment
17+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
18+
19+
// version Single line comment
20+
version int
21+
}
22+
23+
type StructWithMultiLineComments struct {
24+
// time.Time Single line comment
25+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
26+
27+
// version Single line comment
28+
// very long comment
29+
version int
30+
}
31+
32+
type A struct {
33+
// comment
34+
ValidStructWithSingleLineComments
35+
// C is foo
36+
StructWithSingleLineComments // want `there must be an empty line separating embedded fields from regular fields`
37+
38+
D string
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//golangcitest:args -Eembeddedstructfieldcheck
2+
//golangcitest:expected_exitcode 0
3+
package testdata
4+
5+
import (
6+
"time"
7+
)
8+
9+
type ValidStruct struct {
10+
time.Time
11+
12+
version int
13+
}
14+
15+
type NoSpaceStruct struct {
16+
time.Time // want `there must be an empty line separating embedded fields from regular fields`
17+
18+
version int
19+
}
20+
21+
type EmbeddedWithPointers struct {
22+
*time.Time // want `there must be an empty line separating embedded fields from regular fields`
23+
24+
version int
25+
}

pkg/lint/lintersdb/builder_linter.go

+5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/golangci/golangci-lint/v2/pkg/golinters/dupl"
2020
"github.com/golangci/golangci-lint/v2/pkg/golinters/dupword"
2121
"github.com/golangci/golangci-lint/v2/pkg/golinters/durationcheck"
22+
"github.com/golangci/golangci-lint/v2/pkg/golinters/embeddedstructfieldcheck"
2223
"github.com/golangci/golangci-lint/v2/pkg/golinters/err113"
2324
"github.com/golangci/golangci-lint/v2/pkg/golinters/errcheck"
2425
"github.com/golangci/golangci-lint/v2/pkg/golinters/errchkjson"
@@ -212,6 +213,10 @@ func (LinterBuilder) Build(cfg *config.Config) ([]*linter.Config, error) {
212213
WithLoadForGoAnalysis().
213214
WithURL("https://github.com/charithe/durationcheck"),
214215

216+
linter.NewConfig(embeddedstructfieldcheck.New()).
217+
WithSince("v2.2.0").
218+
WithURL("https://github.com/manuelarte/embeddedstructfieldcheck"),
219+
215220
linter.NewConfig(errcheck.New(&cfg.Linters.Settings.Errcheck)).
216221
WithGroups(config.GroupStandard).
217222
WithSince("v1.0.0").

0 commit comments

Comments
 (0)