github.com/cockroachdb/tools@v0.0.0-20230222021103-a6d27438930d/go/analysis/passes/usesgenerics/usesgenerics.go (about) 1 // Copyright 2021 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package usesgenerics defines an Analyzer that checks for usage of generic 6 // features added in Go 1.18. 7 package usesgenerics 8 9 import ( 10 "reflect" 11 12 "golang.org/x/tools/go/analysis" 13 "golang.org/x/tools/go/analysis/passes/inspect" 14 "golang.org/x/tools/go/ast/inspector" 15 "golang.org/x/tools/internal/typeparams/genericfeatures" 16 ) 17 18 var Analyzer = &analysis.Analyzer{ 19 Name: "usesgenerics", 20 Doc: Doc, 21 Requires: []*analysis.Analyzer{inspect.Analyzer}, 22 Run: run, 23 ResultType: reflect.TypeOf((*Result)(nil)), 24 FactTypes: []analysis.Fact{new(featuresFact)}, 25 } 26 27 const Doc = `detect whether a package uses generics features 28 29 The usesgenerics analysis reports whether a package directly or transitively 30 uses certain features associated with generic programming in Go.` 31 32 type Features = genericfeatures.Features 33 34 const ( 35 GenericTypeDecls = genericfeatures.GenericTypeDecls 36 GenericFuncDecls = genericfeatures.GenericFuncDecls 37 EmbeddedTypeSets = genericfeatures.EmbeddedTypeSets 38 TypeInstantiation = genericfeatures.TypeInstantiation 39 FuncInstantiation = genericfeatures.FuncInstantiation 40 ) 41 42 // Result is the usesgenerics analyzer result type. The Direct field records 43 // features used directly by the package being analyzed (i.e. contained in the 44 // package source code). The Transitive field records any features used by the 45 // package or any of its transitive imports. 46 type Result struct { 47 Direct, Transitive Features 48 } 49 50 type featuresFact struct { 51 Features Features 52 } 53 54 func (f *featuresFact) AFact() {} 55 func (f *featuresFact) String() string { return f.Features.String() } 56 57 func run(pass *analysis.Pass) (interface{}, error) { 58 inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) 59 60 direct := genericfeatures.ForPackage(inspect, pass.TypesInfo) 61 62 transitive := direct | importedTransitiveFeatures(pass) 63 if transitive != 0 { 64 pass.ExportPackageFact(&featuresFact{transitive}) 65 } 66 67 return &Result{ 68 Direct: direct, 69 Transitive: transitive, 70 }, nil 71 } 72 73 // importedTransitiveFeatures computes features that are used transitively via 74 // imports. 75 func importedTransitiveFeatures(pass *analysis.Pass) Features { 76 var feats Features 77 for _, imp := range pass.Pkg.Imports() { 78 var importedFact featuresFact 79 if pass.ImportPackageFact(imp, &importedFact) { 80 feats |= importedFact.Features 81 } 82 } 83 return feats 84 }