From b58bbdf4c247b22947223b157a1d36ecc856c652 Mon Sep 17 00:00:00 2001 From: Abirdcfly Date: Tue, 30 Aug 2022 21:20:10 +0800 Subject: [PATCH] go/analysis/internal/checker: make applyFixes work from the first character Make sure modifying the first character of the file takes effect. Fixes golang/go#54774 --- go/analysis/internal/checker/checker.go | 2 + go/analysis/internal/checker/start_test.go | 85 ++++++++++++++++++++++ 2 files changed, 87 insertions(+) create mode 100644 go/analysis/internal/checker/start_test.go diff --git a/go/analysis/internal/checker/checker.go b/go/analysis/internal/checker/checker.go index b5148ff26db..ca77a764ce8 100644 --- a/go/analysis/internal/checker/checker.go +++ b/go/analysis/internal/checker/checker.go @@ -408,6 +408,8 @@ func applyFixes(roots []*action) { if edit.start > cur { out.Write(contents[cur:edit.start]) out.Write(edit.newText) + } else if cur == 0 && edit.start == 0 { // edit starts at first character? + out.Write(edit.newText) } cur = edit.end diff --git a/go/analysis/internal/checker/start_test.go b/go/analysis/internal/checker/start_test.go new file mode 100644 index 00000000000..ede21159bc8 --- /dev/null +++ b/go/analysis/internal/checker/start_test.go @@ -0,0 +1,85 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package checker_test + +import ( + "go/ast" + "io/ioutil" + "path/filepath" + "testing" + + "golang.org/x/tools/go/analysis" + "golang.org/x/tools/go/analysis/analysistest" + "golang.org/x/tools/go/analysis/internal/checker" + "golang.org/x/tools/go/analysis/passes/inspect" + "golang.org/x/tools/go/ast/inspector" + "golang.org/x/tools/internal/testenv" +) + +// TestStartFixes make sure modifying the first character +// of the file takes effect. +func TestStartFixes(t *testing.T) { + testenv.NeedsGoPackages(t) + + files := map[string]string{ + "comment/doc.go": `/* Package comment */ +package comment +`} + + want := `// Package comment +package comment +` + + testdata, cleanup, err := analysistest.WriteFiles(files) + if err != nil { + t.Fatal(err) + } + path := filepath.Join(testdata, "src/comment/doc.go") + checker.Fix = true + checker.Run([]string{"file=" + path}, []*analysis.Analyzer{commentAnalyzer}) + + contents, err := ioutil.ReadFile(path) + if err != nil { + t.Fatal(err) + } + + got := string(contents) + if got != want { + t.Errorf("contents of rewritten file\ngot: %s\nwant: %s", got, want) + } + + defer cleanup() +} + +var commentAnalyzer = &analysis.Analyzer{ + Name: "comment", + Requires: []*analysis.Analyzer{inspect.Analyzer}, + Run: commentRun, +} + +func commentRun(pass *analysis.Pass) (interface{}, error) { + const ( + from = "/* Package comment */" + to = "// Package comment" + ) + inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) + inspect.Preorder(nil, func(n ast.Node) { + if n, ok := n.(*ast.Comment); ok && n.Text == from { + pass.Report(analysis.Diagnostic{ + Pos: n.Pos(), + End: n.End(), + SuggestedFixes: []analysis.SuggestedFix{{ + TextEdits: []analysis.TextEdit{{ + Pos: n.Pos(), + End: n.End(), + NewText: []byte(to), + }}, + }}, + }) + } + }) + + return nil, nil +}