How to define fix action for Go checker using go/analysis?

Viewed 160

I have recently written a Go checker using golang.org/x/tools/go/analysis and golang.org/x/tools/go/analysis/singlechecker and I've managed to write my own custom file manipulation mechanism (keeping track of file offsets etc.) but I felt that I was fighting the system.

There seems to be a Fix flag defined in https://pkg.go.dev/golang.org/x/tools/go/analysis/internal/checker but I have no idea how to use it or hook into the system that uses it.

It's also available to be defined

-fix
        apply all suggested fixes

when checker is compiled with singlechecker:

import (
    "golang.org/x/tools/go/analysis/singlechecker"
)

var (
    Analyzer = &analysis.Analyzer{
        Name: "name",
        Run: run,
    }

    // Can't define a "fix" flag because golang.org/x/tools/go/analysis/internal/checker
    // defines it and flags cannot be redefined.
    // Fix = flag.Bool("autofix", false, "apply fixes automatically")
    Fix bool
)

func main() {
    // NOTE:
    // Don't do this at home. This should be properly integrated with
    // "golang.org/x/tools/go/analysis/internal/checker" flags (specifically -fix
    // flag) but I have no idea how to do that and the documentation is non existent.
    if len(os.Args) > 1 {
        for _, arg := range os.Args[1:] {
            if arg == "-fix" {
                Fix = true
                break
            }
        }
    }

    singlechecker.Main(Analyzer)
}

I couldn't find any documentation about it either. The code that's supposed to be run when Fix flag is enabled it here: https://github.com/golang/tools/blob/268ba720d32c891185aa340e8851e215f23173db/go/analysis/internal/checker/checker.go#L265

Any clues how to use it?

2 Answers

could be done like this:

    pass.Report(
    analysis.Diagnostic{
        Pos:     be.Pos(),
        Message: fmt.Sprintf("do not compare errors directly, use errors.Is() instead: %q", oldExpr),
        SuggestedFixes: []analysis.SuggestedFix{
            {
                Message: fmt.Sprintf("should replace %q with %q", oldExpr, newExpr),
                TextEdits: []analysis.TextEdit{
                    {
                        Pos:     be.Pos(),
                        End:     be.End(),
                        NewText: []byte(newExpr),
                    },
                },
            },
        },
    },

good place to start reading is https://godoc.org/golang.org/x/tools/go/analysis#Diagnostic

Related