Skip to content

Commit b965649

Browse files
authored
feat: allow excluding checkers with directive comment (#185)
Some checkers don't report issues in code. Rather, they form the basis for other checkers to run. For example, a checker may generate the scope graph for the entire source code (or a single file), and other checkers may use the results of such "meta" checkers. We need to exclude such "meta" checkers from being run like other normal checkers. Hence, introducing the directive `//globstar:registry-exclude`.
1 parent 2df359e commit b965649

File tree

7 files changed

+83
-23
lines changed

7 files changed

+83
-23
lines changed

checkers/discover/discover.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,37 @@ import (
55
"go/ast"
66
"go/parser"
77
"go/token"
8+
"strings"
89
)
910

1011
func DiscoverGoCheckers(dir string) ([]string, error) {
1112
goCheckers := []string{}
1213
fset := token.NewFileSet()
13-
pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors&parser.SkipObjectResolution)
14+
pkgs, err := parser.ParseDir(fset, dir, nil, parser.AllErrors&parser.SkipObjectResolution|parser.ParseComments)
1415
if err != nil {
1516
return goCheckers, err
1617
}
1718

1819
for _, pkg := range pkgs {
1920
for _, file := range pkg.Files {
21+
isExcluded := false
22+
if len(file.Comments) > 0 {
23+
firstCommentGroup := file.Comments[0]
24+
for _, comment := range firstCommentGroup.List {
25+
if strings.TrimSpace(comment.Text) == "//globstar:registry-exclude" {
26+
isExcluded = true
27+
break
28+
}
29+
}
30+
}
31+
32+
// skip this checker since exclude directive comment exists
33+
if isExcluded {
34+
continue
35+
}
2036
globstarPkgName := ""
2137
for _, imp := range file.Imports {
38+
// check for registry exclude comment in checker file
2239
if imp.Path.Value == `"globstar.dev/analysis"` {
2340
if imp.Name == nil {
2441
globstarPkgName = "analysis"

checkers/discover/discover_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,16 @@ func TestDiscoverGoCheckers(t *testing.T) {
5050
err: fmt.Errorf("open fixtures/invalid: no such file or directory"),
5151
},
5252
},
53+
{
54+
dir: filepath.Join(cwd, "fixtures", "exclude"),
55+
want: struct {
56+
goCheckers []string
57+
err error
58+
}{
59+
goCheckers: []string{},
60+
err: nil,
61+
},
62+
},
5363
}
5464

5565
for _, tt := range tests {
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//globstar:registry-exclude
2+
package checkers
3+
4+
import (
5+
sitter "github.com/smacker/go-tree-sitter"
6+
"globstar.dev/analysis"
7+
)
8+
9+
var NoAssert *analysis.Analyzer = &analysis.Analyzer{
10+
Name: "no-assert",
11+
Language: analysis.LangPy,
12+
Description: "This checker checks for the usage of `assert` statement in Python code. It is risky as they are removed when Python is run optimized mode",
13+
Category: analysis.CategoryBugRisk,
14+
Severity: analysis.SeverityWarning,
15+
Run: checkNoAssert,
16+
}
17+
18+
func checkNoAssert(pass *analysis.Pass) (interface{}, error) {
19+
analysis.Preorder(pass, func(node *sitter.Node) {
20+
if node.Type() == "assert_statement" {
21+
pass.Report(pass, node, "Do not use assert statement to enforce constraints. They are removed in optimized bytecode")
22+
}
23+
})
24+
25+
return nil, nil
26+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
//globstar:registry-exclude
2+
package exclude
3+
4+
import (
5+
sitter "github.com/smacker/go-tree-sitter"
6+
"globstar.dev/analysis"
7+
)
8+
9+
var NoAssert *analysis.Analyzer = &analysis.Analyzer{
10+
Name: "no-assert",
11+
Language: analysis.LangPy,
12+
Description: "This checker checks for the usage of `assert` statement in Python code. It is risky as they are removed when Python is run optimized mode",
13+
Category: analysis.CategoryBugRisk,
14+
Severity: analysis.SeverityWarning,
15+
Run: checkNoAssert,
16+
}
17+
18+
func checkNoAssert(pass *analysis.Pass) (interface{}, error) {
19+
analysis.Preorder(pass, func(node *sitter.Node) {
20+
if node.Type() == "assert_statement" {
21+
pass.Report(pass, node, "Do not use assert statement to enforce constraints. They are removed in optimized bytecode")
22+
}
23+
})
24+
25+
return nil, nil
26+
}

checkers/discover/generate_test.go

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,6 @@ import (
6464
goAnalysis "globstar.dev/analysis"
6565
)
6666
67-
type Analyzer struct {
68-
TestDir string
69-
Analyzers []*goAnalysis.Analyzer
70-
}
71-
7267
var AnalyzerRegistry = []Analyzer{
7368
{
7469
TestDir: "checkers/javascript/testdata", // relative to the repository root
@@ -101,11 +96,6 @@ import (
10196
goAnalysis "globstar.dev/analysis"
10297
)
10398
104-
type Analyzer struct {
105-
TestDir string
106-
Analyzers []*goAnalysis.Analyzer
107-
}
108-
10999
var AnalyzerRegistry = []Analyzer{
110100
{
111101
TestDir: "checkers/javascript/testdata", // relative to the repository root
@@ -141,11 +131,6 @@ import (
141131
goAnalysis "globstar.dev/analysis"
142132
)
143133
144-
type Analyzer struct {
145-
TestDir string
146-
Analyzers []*goAnalysis.Analyzer
147-
}
148-
149134
var AnalyzerRegistry = []Analyzer{
150135
{
151136
TestDir: "checkers/javascript/testdata", // relative to the repository root
@@ -186,11 +171,6 @@ import (
186171
goAnalysis "globstar.dev/analysis"
187172
)
188173
189-
type Analyzer struct {
190-
TestDir string
191-
Analyzers []*goAnalysis.Analyzer
192-
}
193-
194174
var AnalyzerRegistry = []Analyzer{
195175
{
196176
TestDir: "checkers/javascript/testdata", // relative to the repository root
@@ -201,7 +181,7 @@ var AnalyzerRegistry = []Analyzer{
201181
},
202182
},
203183
{
204-
TestDir: "checkers/python/testdata",
184+
TestDir: "checkers/python/testdata", // relative to the repository root
205185
Analyzers: []*goAnalysis.Analyzer{
206186
python.DjangoSQLInjection,
207187
python.DjangoCSVWriterInjection,

checkers/go/cgi_import.test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package golang
22

33
import (
4-
// <expect-error> usage of cgi package
54
"fmt"
65
"net/http"
6+
// <expect-error> usage of cgi package
77
"net/http/cgi"
88
)
99

checkers/javascript/scope.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//globstar:registry-exclude
12
// scope resolution implementation for JS and TS files
23
package javascript
34

0 commit comments

Comments
 (0)