gvisor.dev/gvisor@v0.0.0-20240520182842-f9d4d51c7e0f/tools/nogo/check/analyzers.go (about) 1 // Copyright 2019 The gVisor Authors. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package check 16 17 import ( 18 "encoding/gob" 19 "io" 20 "reflect" 21 22 "golang.org/x/tools/go/analysis" 23 "golang.org/x/tools/go/analysis/passes/asmdecl" 24 "golang.org/x/tools/go/analysis/passes/assign" 25 "golang.org/x/tools/go/analysis/passes/atomic" 26 "golang.org/x/tools/go/analysis/passes/bools" 27 "golang.org/x/tools/go/analysis/passes/buildtag" 28 "golang.org/x/tools/go/analysis/passes/cgocall" 29 "golang.org/x/tools/go/analysis/passes/composite" 30 "golang.org/x/tools/go/analysis/passes/copylock" 31 "golang.org/x/tools/go/analysis/passes/errorsas" 32 "golang.org/x/tools/go/analysis/passes/httpresponse" 33 "golang.org/x/tools/go/analysis/passes/loopclosure" 34 "golang.org/x/tools/go/analysis/passes/lostcancel" 35 "golang.org/x/tools/go/analysis/passes/nilfunc" 36 "golang.org/x/tools/go/analysis/passes/nilness" 37 "golang.org/x/tools/go/analysis/passes/printf" 38 "golang.org/x/tools/go/analysis/passes/shadow" 39 "golang.org/x/tools/go/analysis/passes/shift" 40 "golang.org/x/tools/go/analysis/passes/stdmethods" 41 "golang.org/x/tools/go/analysis/passes/stringintconv" 42 "golang.org/x/tools/go/analysis/passes/structtag" 43 "golang.org/x/tools/go/analysis/passes/tests" 44 "golang.org/x/tools/go/analysis/passes/unmarshal" 45 "golang.org/x/tools/go/analysis/passes/unreachable" 46 "golang.org/x/tools/go/analysis/passes/unsafeptr" 47 "golang.org/x/tools/go/analysis/passes/unusedresult" 48 "honnef.co/go/tools/staticcheck" 49 "honnef.co/go/tools/stylecheck" 50 51 "gvisor.dev/gvisor/tools/checkaligned" 52 "gvisor.dev/gvisor/tools/checkconst" 53 "gvisor.dev/gvisor/tools/checkescape" 54 "gvisor.dev/gvisor/tools/checklinkname" 55 "gvisor.dev/gvisor/tools/checklocks" 56 "gvisor.dev/gvisor/tools/checkunsafe" 57 ) 58 59 // binaryAnalyzer is a special class of analyzer which supports an additional 60 // operation to run an analyzer with the object binary data. 61 type binaryAnalyzer interface { 62 // Run runs the analyzer with the given binary data. 63 Run(*analysis.Pass, io.Reader) (any, error) 64 } 65 66 // analyzer is a simple analysis.Analyzer interface. 67 // 68 // This is implemented by plainAnalyzer, and is used to allow calls to 69 // non-standard analyzers (e.g. checkescape, which requires the objdump output 70 // in addition to the existing pass information). 71 type analyzer interface { 72 Legacy() *analysis.Analyzer 73 } 74 75 // plainAnalyzer implements analyzer. 76 type plainAnalyzer struct { 77 *analysis.Analyzer 78 } 79 80 // Legacy implements analyzer.Legacy. 81 func (pa *plainAnalyzer) Legacy() *analysis.Analyzer { 82 return pa.Analyzer 83 } 84 85 var ( 86 // allAnalyzers is a list of all available analyzers. 87 // 88 // This is guaranteed to be complete closure around the dependency 89 // graph of all analyzers (via the "Requires" attribute, below). 90 // Therefore, to map an *analysis.Analyzer to a runner, you may safely 91 // use "findAnalyzer". 92 allAnalyzers = make(map[*analysis.Analyzer]analyzer) 93 94 // allFactTypes is a list of all fact types, useful as a filter. 95 allFactTypes = make(map[reflect.Type]bool) 96 ) 97 98 // findAnalyzer maps orig to an analyzer instance. 99 // 100 // This is guaranteed to work provided allAnalyzers is made into a transitive 101 // closure of all known analyzers (see init). 102 func findAnalyzer(orig *analysis.Analyzer) analyzer { 103 return allAnalyzers[orig] 104 } 105 106 // registerFactType registers an analysis.Fact. 107 func registerFactType(f analysis.Fact) { 108 // Already registered? 109 t := reflect.TypeOf(f) 110 if _, ok := allFactTypes[t]; ok { 111 return 112 } 113 114 // Register the type. 115 gob.Register(f) 116 allFactTypes[t] = true 117 } 118 119 // register recursively registers an analyzer. 120 func register(a analyzer) { 121 // Already registered? 122 if _, ok := allAnalyzers[a.Legacy()]; ok { 123 return 124 } 125 126 // Register all fact types. 127 for _, f := range a.Legacy().FactTypes { 128 registerFactType(f) 129 } 130 131 // Register dependencies. 132 for _, orig := range a.Legacy().Requires { 133 if findAnalyzer(orig) == nil { 134 register(&plainAnalyzer{orig}) 135 } 136 } 137 138 // Save the analyzer. 139 allAnalyzers[a.Legacy()] = a 140 } 141 142 func init() { 143 // Standard & internal analyzers. 144 register(&plainAnalyzer{asmdecl.Analyzer}) 145 register(&plainAnalyzer{assign.Analyzer}) 146 register(&plainAnalyzer{atomic.Analyzer}) 147 register(&plainAnalyzer{bools.Analyzer}) 148 register(&plainAnalyzer{buildtag.Analyzer}) 149 register(&plainAnalyzer{cgocall.Analyzer}) 150 register(&plainAnalyzer{composite.Analyzer}) 151 register(&plainAnalyzer{copylock.Analyzer}) 152 register(&plainAnalyzer{errorsas.Analyzer}) 153 register(&plainAnalyzer{httpresponse.Analyzer}) 154 register(&plainAnalyzer{loopclosure.Analyzer}) 155 register(&plainAnalyzer{lostcancel.Analyzer}) 156 register(&plainAnalyzer{nilfunc.Analyzer}) 157 register(&plainAnalyzer{nilness.Analyzer}) 158 register(&plainAnalyzer{printf.Analyzer}) 159 register(&plainAnalyzer{shift.Analyzer}) 160 register(&plainAnalyzer{stdmethods.Analyzer}) 161 register(&plainAnalyzer{stringintconv.Analyzer}) 162 register(&plainAnalyzer{shadow.Analyzer}) 163 register(&plainAnalyzer{structtag.Analyzer}) 164 register(&plainAnalyzer{tests.Analyzer}) 165 register(&plainAnalyzer{unmarshal.Analyzer}) 166 register(&plainAnalyzer{unreachable.Analyzer}) 167 register(&plainAnalyzer{unsafeptr.Analyzer}) 168 register(&plainAnalyzer{unusedresult.Analyzer}) 169 register(checkescape.Analyzer) 170 register(&plainAnalyzer{checkconst.Analyzer}) 171 register(&plainAnalyzer{checkunsafe.Analyzer}) 172 register(&plainAnalyzer{checklinkname.Analyzer}) 173 register(&plainAnalyzer{checklocks.Analyzer}) 174 register(&plainAnalyzer{checkaligned.Analyzer}) 175 176 // Add all staticcheck analyzers. 177 for _, a := range staticcheck.Analyzers { 178 register(&plainAnalyzer{a.Analyzer}) 179 } 180 181 // Add all stylecheck analyzers. 182 for _, a := range stylecheck.Analyzers { 183 register(&plainAnalyzer{a.Analyzer}) 184 } 185 }