Skip to content

Commit 9d8009b

Browse files
zhangyunhao116timothy-king
authored andcommitted
go/analysis: validate report if analyzer.Run is empty
The Run function is necessary for an analyzer, if left a nil Run, the runner will panic in run-time(singlechecker.Main, etc). Change-Id: Ibbeea2d8c740f73e6c083647df6ded445036e272 Reviewed-on: https://go-review.googlesource.com/c/tools/+/329451 Trust: Carlos Amedee <[email protected]> Reviewed-by: Tim King <[email protected]> Run-TryBot: Tim King <[email protected]> gopls-CI: kokoro <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 761e51f commit 9d8009b

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

go/analysis/validate.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import (
1414
// Validate reports an error if any of the analyzers are misconfigured.
1515
// Checks include:
1616
// that the name is a valid identifier;
17+
// that the Doc is not empty;
18+
// that the Run is non-nil;
1719
// that the Requires graph is acyclic;
1820
// that analyzer fact types are unique;
1921
// that each fact type is a pointer.
@@ -46,6 +48,9 @@ func Validate(analyzers []*Analyzer) error {
4648
return fmt.Errorf("analyzer %q is undocumented", a)
4749
}
4850

51+
if a.Run == nil {
52+
return fmt.Errorf("analyzer %q has nil Run", a)
53+
}
4954
// fact types
5055
for _, f := range a.FactTypes {
5156
if f == nil {

go/analysis/validate_test.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,43 @@ import (
1111

1212
func TestValidate(t *testing.T) {
1313
var (
14+
run = func(p *Pass) (interface{}, error) {
15+
return nil, nil
16+
}
1417
dependsOnSelf = &Analyzer{
1518
Name: "dependsOnSelf",
1619
Doc: "this analyzer depends on itself",
20+
Run: run,
1721
}
1822
inCycleA = &Analyzer{
1923
Name: "inCycleA",
2024
Doc: "this analyzer depends on inCycleB",
25+
Run: run,
2126
}
2227
inCycleB = &Analyzer{
2328
Name: "inCycleB",
2429
Doc: "this analyzer depends on inCycleA and notInCycleA",
30+
Run: run,
2531
}
2632
pointsToCycle = &Analyzer{
2733
Name: "pointsToCycle",
2834
Doc: "this analyzer depends on inCycleA",
35+
Run: run,
2936
}
3037
notInCycleA = &Analyzer{
3138
Name: "notInCycleA",
3239
Doc: "this analyzer depends on notInCycleB and notInCycleC",
40+
Run: run,
3341
}
3442
notInCycleB = &Analyzer{
3543
Name: "notInCycleB",
3644
Doc: "this analyzer depends on notInCycleC",
45+
Run: run,
3746
}
3847
notInCycleC = &Analyzer{
3948
Name: "notInCycleC",
4049
Doc: "this analyzer has no dependencies",
50+
Run: run,
4151
}
4252
)
4353

@@ -116,3 +126,27 @@ func TestCycleInRequiresGraphErrorMessage(t *testing.T) {
116126
t.Errorf("error string %s does not contain expected substring %q", errMsg, wantSubstring)
117127
}
118128
}
129+
130+
func TestValidateEmptyDoc(t *testing.T) {
131+
withoutDoc := &Analyzer{
132+
Name: "withoutDoc",
133+
Run: func(p *Pass) (interface{}, error) {
134+
return nil, nil
135+
},
136+
}
137+
err := Validate([]*Analyzer{withoutDoc})
138+
if err == nil || !strings.Contains(err.Error(), "is undocumented") {
139+
t.Errorf("got unexpected error while validating analyzers withoutDoc: %v", err)
140+
}
141+
}
142+
143+
func TestValidateNoRun(t *testing.T) {
144+
withoutRun := &Analyzer{
145+
Name: "withoutRun",
146+
Doc: "this analyzer has no Run",
147+
}
148+
err := Validate([]*Analyzer{withoutRun})
149+
if err == nil || !strings.Contains(err.Error(), "has nil Run") {
150+
t.Errorf("got unexpected error while validating analyzers withoutRun: %v", err)
151+
}
152+
}

0 commit comments

Comments
 (0)