gostatic-analysislinter

Creating analyzer in golang.org/x/tools that runs for all the packages, not one time per package


I want to create an analysis.Analyzer and define a run function on it that runs once per all the codebase, and not once per package. If I check the documentation of the Run field, I see:

// Run applies the analyzer to a package.

but in my case I want that it runs once, not once per package. I declared my Analyzer as:

a := &analysis.Analyzer{
        Name:     "mylinter",
        Doc:      "my documentation.",
        Run:      run,
        Requires: []*analysis.Analyzer{inspect.Analyzer},
    }
...

func run(pass *analysis.Pass) (any, error) {
 ...
 // here I need all the structs declared in the whole codebase
 // because I want to do some checks when those structs are instantiated in other packages.
}

One thing I have tried, it's to keep the state after every call to run. In my case I need to keep all the stuct declarations, so on each call to run I am storing the structs declared in that package, and then performing the lint operations. But this is not working, because the results depends on what packages are processed first. So, ideally, I need to get all the structs declaration (node ast.TypeSpec), and then check the struct instantiation with all the info of the struct declaration.


Solution

  • The Analyzer just statically describes an analysis function to a driver, it does not run on anything.

    What you are concerned with is that the analysis driver runs a single unit of work per package, a Pass.

    If you want to communicate over packages, you need to use Facts, see also the documentation of Analyzer:

    FactTypes establishes a "vertical" dependency between analysis passes (same analyzer, different packages).