Skip to content

Commit 72990fb

Browse files
committed
feat: plugin example
0 parents  commit 72990fb

File tree

9 files changed

+868
-0
lines changed

9 files changed

+868
-0
lines changed

.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
/.idea/
2+
/.vscode/
3+
/dist/
4+
.DS_Store
5+
/*.pprof
6+
/*.txt
7+
/golangci-lint
8+
/golangci-lint.exe
9+
/example.so

.golangci.example.yml

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
linters-settings:
2+
custom:
3+
example:
4+
type: module
5+
# Description is optional
6+
description: The description of the linter. This is optional, but shows up when running `golangci-lint linters`.
7+
# Original-url is optional, and is only used for documentation purposes.
8+
original-url: github.com/golangci/example-plugin-module-linter
9+
settings:
10+
one: Foo
11+
two:
12+
- name: Bar
13+
three:
14+
name: Bar
15+
16+
linters:
17+
disable-all: true
18+
enable:
19+
- example

LICENSE

+674
Large diffs are not rendered by default.

example.go

+75
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package linters
2+
3+
import (
4+
"go/ast"
5+
"strings"
6+
7+
"github.com/golangci/plugin-module-register/register"
8+
"golang.org/x/tools/go/analysis"
9+
)
10+
11+
func init() {
12+
register.Plugin("example", New)
13+
}
14+
15+
type MySettings struct {
16+
One string `json:"one"`
17+
Two []Element `json:"two"`
18+
Three Element `json:"three"`
19+
}
20+
21+
type Element struct {
22+
Name string `json:"name"`
23+
}
24+
25+
type PluginExample struct {
26+
settings MySettings
27+
}
28+
29+
func New(settings any) (register.LinterPlugin, error) {
30+
// The configuration type will be map[string]any or []interface, it depends on your configuration.
31+
// You can use https://github.com/go-viper/mapstructure to convert map to struct.
32+
33+
s, err := register.DecodeSettings[MySettings](settings)
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
return &PluginExample{settings: s}, nil
39+
}
40+
41+
func (f *PluginExample) BuildAnalyzers() ([]*analysis.Analyzer, error) {
42+
return []*analysis.Analyzer{
43+
{
44+
Name: "todo",
45+
Doc: "finds todos without author",
46+
Run: f.run,
47+
},
48+
}, nil
49+
}
50+
51+
func (f *PluginExample) GetLoadMode() string {
52+
return register.LoadModeSyntax
53+
}
54+
55+
func (f *PluginExample) run(pass *analysis.Pass) (interface{}, error) {
56+
for _, file := range pass.Files {
57+
ast.Inspect(file, func(n ast.Node) bool {
58+
if comment, ok := n.(*ast.Comment); ok {
59+
if strings.HasPrefix(comment.Text, "// TODO:") || strings.HasPrefix(comment.Text, "// TODO():") {
60+
pass.Report(analysis.Diagnostic{
61+
Pos: comment.Pos(),
62+
End: 0,
63+
Category: "todo",
64+
Message: "TODO comment has no author",
65+
SuggestedFixes: nil,
66+
})
67+
}
68+
}
69+
70+
return true
71+
})
72+
}
73+
74+
return nil, nil
75+
}

example_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package linters
2+
3+
import (
4+
"path/filepath"
5+
"runtime"
6+
"testing"
7+
8+
"github.com/golangci/plugin-module-register/register"
9+
"github.com/stretchr/testify/require"
10+
"golang.org/x/tools/go/analysis/analysistest"
11+
)
12+
13+
func TestPluginExample(t *testing.T) {
14+
newPlugin, err := register.GetPlugin("example")
15+
require.NoError(t, err)
16+
17+
plugin, err := newPlugin(nil)
18+
require.NoError(t, err)
19+
20+
analyzers, err := plugin.BuildAnalyzers()
21+
require.NoError(t, err)
22+
23+
analysistest.Run(t, testdataDir(t), analyzers[0], "testlintdata/todo")
24+
}
25+
26+
func testdataDir(t *testing.T) string {
27+
t.Helper()
28+
29+
_, testFilename, _, ok := runtime.Caller(1)
30+
if !ok {
31+
require.Fail(t, "unable to get current test filename")
32+
}
33+
34+
return filepath.Join(filepath.Dir(testFilename), "testdata")
35+
}

go.mod

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
module github.com/golangci/example-plugin-module-linter
2+
3+
go 1.21
4+
5+
require (
6+
github.com/golangci/plugin-module-register v0.0.0-20240305222101-f76272ec86ee
7+
github.com/stretchr/testify v1.9.0
8+
golang.org/x/tools v0.19.0
9+
)
10+
11+
require (
12+
github.com/davecgh/go-spew v1.1.1 // indirect
13+
github.com/pmezard/go-difflib v1.0.0 // indirect
14+
golang.org/x/mod v0.16.0 // indirect
15+
gopkg.in/yaml.v3 v3.0.1 // indirect
16+
)

go.sum

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
3+
github.com/golangci/plugin-module-register v0.0.0-20240305222101-f76272ec86ee h1:nl5nPZ5b2O2dj5+LizmFQ8gNq0r65OfALkp0M8EWJ8E=
4+
github.com/golangci/plugin-module-register v0.0.0-20240305222101-f76272ec86ee/go.mod h1:mGTAkB/NoZMvAGMkiv4+pmmwVO+Gp+zeV77nggByWCc=
5+
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
6+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
7+
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
8+
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
9+
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
10+
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
11+
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
12+
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
13+
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
14+
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
15+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
16+
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
17+
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
18+
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

readme.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
This is an example linter that can be used as a plugin for `golangci-lint`.
+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package todo
2+
3+
// comment without a to do
4+
func SomeFunc1() {
5+
_ = 1 + 1
6+
}
7+
8+
// TODO: do something // want "TODO comment has no author"
9+
func SomeFunc2() {
10+
_ = 1 + 2
11+
}
12+
13+
// TODO(): do something // want "TODO comment has no author"
14+
func SomeFunc3() {
15+
_ = 1 + 3
16+
}
17+
18+
// TODO(dbraley): Do something with the value
19+
func SomeFunc4() {
20+
_ = 1 + 4
21+
}

0 commit comments

Comments
 (0)