Skip to content

Commit a1e4860

Browse files
committed
Port staticcheck to the go/analysis framework
This change ports all static analysis checks to the go/analysis framework and turns cmd/staticcheck into a sophisticated runner for analyses. Since our previous framework was built around the idea of having all data in memory at once, some changes had to be made to accomodate the modular go/analysis framework. All information about dependencies have to be serialized as facts. This includes information such as which objects are deprecated and which functions are pure. We have thus converted the 'functions' package to act as analyses instead of generating a global set of information. SSA packages are built per package under analysis no single SSA program exists. This also means that nodes in the SSA graph aren't canonical; the same function in a dependency may be represented by many different objects. We no longer store anything SSA related across analyses. go/analysis is designed around the idea of enabling caching of facts, and thus cmd/staticcheck was designed to utilize caching. We rely on the Go build cache to avoid loading packages from source, and we implement our own cache of facts to avoid reanalyzing packages that haven't changed. This combination can greatly reduce memory use as well as runtime. For smaller packages, it even allows real-time checking in something like a language server. We've replaced our own testing utilities with go/analysis/analysistest, primarily for the sake of consistency with other analyses. Reimplementing 'unused' in the new framework required extra work, and special knowledge in the runner. Unused cannot analyze packages in isolation, since files may be shared between test variants and identifiers may only be used in some variations of a package. Unused still exposes an entry-point matching the go/analysis framework, but it doesn't compute any facts nor report any diagnostics. Instead, it incrementally builds a view of all packages it sees. After all packages have been analyzed, the result can be queried and processed. While all other analyses can be reused by other runners directly, using unused will require special code in the runner. We've deleted the gosimple, unused and megacheck binaries. They had already been deprecated and there was little point in porting them to the new framework. With the removal of the unused binary there is currently no way to use its whole program mode. This will be rectified in a follow-up commit which adds said mode as its own check in staticcheck.
1 parent ea95bdf commit a1e4860

File tree

202 files changed

+5828
-3357
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

202 files changed

+5828
-3357
lines changed

cmd/gosimple/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

cmd/gosimple/gosimple.go

Lines changed: 0 additions & 20 deletions
This file was deleted.

cmd/megacheck/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

cmd/megacheck/megacheck.go

Lines changed: 0 additions & 93 deletions
This file was deleted.

cmd/staticcheck/staticcheck.go

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package main // import "honnef.co/go/tools/cmd/staticcheck"
44
import (
55
"os"
66

7+
"golang.org/x/tools/go/analysis"
78
"honnef.co/go/tools/lint"
89
"honnef.co/go/tools/lint/lintutil"
910
"honnef.co/go/tools/simple"
@@ -16,12 +17,18 @@ func main() {
1617
fs := lintutil.FlagSet("staticcheck")
1718
fs.Parse(os.Args[1:])
1819

19-
checkers := []lint.Checker{
20-
simple.NewChecker(),
21-
staticcheck.NewChecker(),
22-
stylecheck.NewChecker(),
23-
&unused.Checker{},
20+
var cs []*analysis.Analyzer
21+
for _, v := range simple.Analyzers {
22+
cs = append(cs, v)
2423
}
24+
for _, v := range staticcheck.Analyzers {
25+
cs = append(cs, v)
26+
}
27+
for _, v := range stylecheck.Analyzers {
28+
cs = append(cs, v)
29+
}
30+
31+
cums := []lint.CumulativeChecker{unused.NewChecker()}
2532

26-
lintutil.ProcessFlagSet(checkers, fs)
33+
lintutil.ProcessFlagSet(cs, cums, fs)
2734
}

cmd/unused/README.md

Lines changed: 0 additions & 1 deletion
This file was deleted.

cmd/unused/main.go

Lines changed: 0 additions & 57 deletions
This file was deleted.

config/config.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,34 @@ package config
33
import (
44
"os"
55
"path/filepath"
6+
"reflect"
67

78
"github.com/BurntSushi/toml"
9+
"golang.org/x/tools/go/analysis"
810
)
911

12+
var Analyzer = &analysis.Analyzer{
13+
Name: "config",
14+
Doc: "loads configuration for the current package tree",
15+
Run: func(pass *analysis.Pass) (interface{}, error) {
16+
if len(pass.Files) == 0 {
17+
cfg := DefaultConfig
18+
return &cfg, nil
19+
}
20+
// FIXME(dh): this may yield the wrong path for generated files in the build cache
21+
path := pass.Fset.PositionFor(pass.Files[0].Pos(), true).Filename
22+
dir := filepath.Dir(path)
23+
cfg, err := Load(dir)
24+
return &cfg, err
25+
},
26+
RunDespiteErrors: true,
27+
ResultType: reflect.TypeOf((*Config)(nil)),
28+
}
29+
30+
func For(pass *analysis.Pass) *Config {
31+
return pass.ResultOf[Analyzer].(*Config)
32+
}
33+
1034
func mergeLists(a, b []string) []string {
1135
out := make([]string, 0, len(a)+len(b))
1236
for _, el := range b {
@@ -73,7 +97,7 @@ type Config struct {
7397
HTTPStatusCodeWhitelist []string `toml:"http_status_code_whitelist"`
7498
}
7599

76-
var defaultConfig = Config{
100+
var DefaultConfig = Config{
77101
Checks: []string{"all", "-ST1000", "-ST1003", "-ST1016"},
78102
Initialisms: []string{
79103
"ACL", "API", "ASCII", "CPU", "CSS", "DNS",
@@ -120,7 +144,7 @@ func parseConfigs(dir string) ([]Config, error) {
120144
}
121145
dir = ndir
122146
}
123-
out = append(out, defaultConfig)
147+
out = append(out, DefaultConfig)
124148
if len(out) < 2 {
125149
return out, nil
126150
}

functions/concrete.go

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)