GoPLS Viewer

Home|gopls/go/analysis/passes/usesgenerics/usesgenerics.go
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.
7package usesgenerics
8
9import (
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
18var Analyzer = &analysis.Analyzer{
19    Name:       "usesgenerics",
20    Doc:        Doc,
21    Requires:   []*analysis.Analyzer{inspect.Analyzer},
22    Run:        run,
23    ResultTypereflect.TypeOf((*Result)(nil)),
24    FactTypes:  []analysis.Fact{new(featuresFact)},
25}
26
27const Doc = `detect whether a package uses generics features
28
29The usesgenerics analysis reports whether a package directly or transitively
30uses certain features associated with generic programming in Go.`
31
32type Features = genericfeatures.Features
33
34const (
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.
46type Result struct {
47    DirectTransitive Features
48}
49
50type featuresFact struct {
51    Features Features
52}
53
54func (f *featuresFactAFact()         {}
55func (f *featuresFactString() string { return f.Features.String() }
56
57func run(pass *analysis.Pass) (interface{}, error) {
58    inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
59
60    direct := genericfeatures.ForPackage(inspectpass.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        Transitivetransitive,
70    }, nil
71}
72
73// importedTransitiveFeatures computes features that are used transitively via
74// imports.
75func importedTransitiveFeatures(pass *analysis.PassFeatures {
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}
85
MembersX
GenericFuncDecls
TypeInstantiation
FuncInstantiation
reflect
featuresFact
featuresFact.Features
genericfeatures
featuresFact.String
run
importedTransitiveFeatures.RangeStmt_2342.imp
featuresFact.AFact.f
Features
Result
Result.Direct
importedTransitiveFeatures.feats
inspector
EmbeddedTypeSets
featuresFact.AFact
importedTransitiveFeatures
importedTransitiveFeatures.RangeStmt_2342.BlockStmt.importedFact
inspect
importedTransitiveFeatures.pass
Doc
analysis
Result.Transitive
featuresFact.String.f
run.pass
run.direct
GenericTypeDecls
Members
X