Skip to content

Commit 99e8fee

Browse files
adonovangopherbot
authored andcommitted
x/tools: fset.File(file.Pos()) -> fset.File(file.FileStart)
This CL fixes a bug (#70149) in gopls/internal/golang/pkgdoc.go in which a call to fset.File(file.Pos()) would return nil because when file points to an empty ast.File, Pos() returns NoPos. Instead, we should use file.FileStart, which is (in principle) always valid even for an empty file. However, there is a separate bug in go1.23 (#70162) that means FileStart is invalid whenever Pos() is. So, this fix only works with go1.24, and there's no real workaround short of the additional logic this CL adds to parsego.Parse, which at least covers all of gopls. Also, we audit all of x/tools for similar faulty uses of Pos() and replace them with FileStart. In future, we should use File.Pos only for its specific meaning related to the package decl. Fixes golang/go#70149 Updates golang/go#70162 Change-Id: Ic8cedfe912e44a0b4eb6e5e6874a6266d4be9076 Reviewed-on: https://go-review.googlesource.com/c/tools/+/624437 Reviewed-by: Robert Findley <[email protected]> Auto-Submit: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 5cd08e2 commit 99e8fee

File tree

33 files changed

+78
-54
lines changed

33 files changed

+78
-54
lines changed

go/analysis/passes/cgocall/cgocall.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ func typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*a
179179
for _, raw := range files {
180180
// If f is a cgo-generated file, Position reports
181181
// the original file, honoring //line directives.
182-
filename := fset.Position(raw.Pos()).Filename
182+
filename := fset.Position(raw.Pos()).Filename // sic: Pos, not FileStart
183183
f, err := parser.ParseFile(fset, filename, nil, parser.SkipObjectResolution)
184184
if err != nil {
185185
return nil, nil, fmt.Errorf("can't parse raw cgo file: %v", err)

go/analysis/passes/tests/tests.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ var acceptedFuzzTypes = []types.Type{
4848

4949
func run(pass *analysis.Pass) (interface{}, error) {
5050
for _, f := range pass.Files {
51-
if !strings.HasSuffix(pass.Fset.File(f.Pos()).Name(), "_test.go") {
51+
if !strings.HasSuffix(pass.Fset.File(f.FileStart).Name(), "_test.go") {
5252
continue
5353
}
5454
for _, decl := range f.Decls {

go/ast/inspector/inspector.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,9 @@ func (in *Inspector) WithStack(types []ast.Node, f func(n ast.Node, push bool, s
180180
// traverse builds the table of events representing a traversal.
181181
func traverse(files []*ast.File) []event {
182182
// Preallocate approximate number of events
183-
// based on source file extent.
183+
// based on source file extent of the declarations.
184+
// (We use End-Pos not FileStart-FileEnd to neglect
185+
// the effect of long doc comments.)
184186
// This makes traverse faster by 4x (!).
185187
var extent int
186188
for _, f := range files {

go/callgraph/rta/rta_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func TestRTA(t *testing.T) {
100100
//
101101
// Functions are notated as if by ssa.Function.String.
102102
func check(t *testing.T, f *ast.File, pkg *ssa.Package, res *rta.Result) {
103-
tokFile := pkg.Prog.Fset.File(f.Pos())
103+
tokFile := pkg.Prog.Fset.File(f.FileStart)
104104

105105
// Find the WANT comment.
106106
expectation := func(f *ast.File) (string, int) {

go/loader/loader.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -340,13 +340,12 @@ func (conf *Config) addImport(path string, tests bool) {
340340
func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
341341
for _, info := range prog.AllPackages {
342342
for _, f := range info.Files {
343-
if f.Pos() == token.NoPos {
344-
// This can happen if the parser saw
345-
// too many errors and bailed out.
346-
// (Use parser.AllErrors to prevent that.)
343+
if f.FileStart == token.NoPos {
344+
// Workaround for #70162 (undefined FileStart).
345+
// TODO(adonovan): delete once go1.24 is assured.
347346
continue
348347
}
349-
if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
348+
if !tokenFileContainsPos(prog.Fset.File(f.FileStart), start) {
350349
continue
351350
}
352351
if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {

go/packages/packages_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2684,7 +2684,7 @@ func testIssue48226(t *testing.T, exporter packagestest.Exporter) {
26842684
t.Fatalf("package has errors: %v", pkg.Errors)
26852685
}
26862686

2687-
fname := pkg.Fset.File(pkg.Syntax[0].Pos()).Name()
2687+
fname := pkg.Fset.File(pkg.Syntax[0].FileStart).Name()
26882688
if filepath.Base(fname) != "syntax.go" {
26892689
t.Errorf("expected the package declaration position "+
26902690
"to resolve to \"syntax.go\", got %q instead", fname)

go/types/internal/play/play.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func handleSelectJSON(w http.ResponseWriter, req *http.Request) {
113113

114114
fset := pkg.Fset
115115
file := pkg.Syntax[0]
116-
tokFile := fset.File(file.Pos())
116+
tokFile := fset.File(file.FileStart)
117117
startPos := tokFile.Pos(startOffset)
118118
endPos := tokFile.Pos(endOffset)
119119

godoc/index.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -649,7 +649,7 @@ func (x *Indexer) addFile(f vfs.ReadSeekCloser, filename string, goFile bool) (f
649649
if goFile {
650650
// parse the file and in the process add it to the file set
651651
if ast, err = parser.ParseFile(x.fset, filename, src, parser.ParseComments); err == nil {
652-
file = x.fset.File(ast.Pos()) // ast.Pos() is inside the file
652+
file = x.fset.File(ast.FileStart) // ast.FileStart is inside the file
653653
return
654654
}
655655
// file has parse errors, and the AST may be incorrect -

gopls/doc/generate/generate.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ func lowerFirst(x string) string {
533533
func fileForPos(pkg *packages.Package, pos token.Pos) (*ast.File, error) {
534534
fset := pkg.Fset
535535
for _, f := range pkg.Syntax {
536-
if safetoken.StartPosition(fset, f.Pos()).Filename == safetoken.StartPosition(fset, pos).Filename {
536+
if safetoken.StartPosition(fset, f.FileStart).Filename == safetoken.StartPosition(fset, pos).Filename {
537537
return f, nil
538538
}
539539
}

gopls/internal/analysis/fillreturns/fillreturns.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ outer:
4545
}
4646
var file *ast.File
4747
for _, f := range pass.Files {
48-
if f.Pos() <= typeErr.Pos && typeErr.Pos <= f.End() {
48+
if f.FileStart <= typeErr.Pos && typeErr.Pos <= f.FileEnd {
4949
file = f
5050
break
5151
}

gopls/internal/analysis/nonewvars/nonewvars.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
4747

4848
var file *ast.File
4949
for _, f := range pass.Files {
50-
if f.Pos() <= assignStmt.Pos() && assignStmt.Pos() < f.End() {
50+
if f.FileStart <= assignStmt.Pos() && assignStmt.Pos() < f.FileEnd {
5151
file = f
5252
break
5353
}

gopls/internal/analysis/noresultvalues/noresultvalues.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
4242

4343
var file *ast.File
4444
for _, f := range pass.Files {
45-
if f.Pos() <= retStmt.Pos() && retStmt.Pos() < f.End() {
45+
if f.FileStart <= retStmt.Pos() && retStmt.Pos() < f.FileEnd {
4646
file = f
4747
break
4848
}

gopls/internal/analysis/simplifycompositelit/simplifycompositelit.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
3838
generated := make(map[*token.File]bool)
3939
for _, file := range pass.Files {
4040
if ast.IsGenerated(file) {
41-
generated[pass.Fset.File(file.Pos())] = true
41+
generated[pass.Fset.File(file.FileStart)] = true
4242
}
4343
}
4444

gopls/internal/analysis/simplifyrange/simplifyrange.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
3333
generated := make(map[*token.File]bool)
3434
for _, file := range pass.Files {
3535
if ast.IsGenerated(file) {
36-
generated[pass.Fset.File(file.Pos())] = true
36+
generated[pass.Fset.File(file.FileStart)] = true
3737
}
3838
}
3939

gopls/internal/analysis/simplifyslice/simplifyslice.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
4242
generated := make(map[*token.File]bool)
4343
for _, file := range pass.Files {
4444
if ast.IsGenerated(file) {
45-
generated[pass.Fset.File(file.Pos())] = true
45+
generated[pass.Fset.File(file.FileStart)] = true
4646
}
4747
}
4848

gopls/internal/analysis/undeclaredname/undeclared.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ func runForError(pass *analysis.Pass, err types.Error) {
5959
// Find file enclosing error.
6060
var file *ast.File
6161
for _, f := range pass.Files {
62-
if f.Pos() <= err.Pos && err.Pos < f.End() {
62+
if f.FileStart <= err.Pos && err.Pos < f.FileEnd {
6363
file = f
6464
break
6565
}

gopls/internal/analysis/unusedvariable/unusedvariable.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ func run(pass *analysis.Pass) (interface{}, error) {
6060
func runForError(pass *analysis.Pass, err types.Error, name string) error {
6161
var file *ast.File
6262
for _, f := range pass.Files {
63-
if f.Pos() <= err.Pos && err.Pos < f.End() {
63+
if f.FileStart <= err.Pos && err.Pos < f.FileEnd {
6464
file = f
6565
break
6666
}

gopls/internal/cache/parse.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,6 @@ func parseGoImpl(ctx context.Context, fset *token.FileSet, fh file.Handle, mode
4040
if ctx.Err() != nil {
4141
return nil, ctx.Err()
4242
}
43-
pgf, _ := parsego.Parse(ctx, fset, fh.URI(), content, mode, purgeFuncBodies)
43+
pgf, _ := parsego.Parse(ctx, fset, fh.URI(), content, mode, purgeFuncBodies) // ignore 'fixes'
4444
return pgf, nil
4545
}

gopls/internal/cache/parsego/file.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,11 @@ type File struct {
2020
URI protocol.DocumentURI
2121
Mode parser.Mode
2222

23-
// File is the file resulting from parsing. Clients must not access the AST's
24-
// legacy ast.Object-related fields without first ensuring that
25-
// [File.Resolve] was already called.
23+
// File is the file resulting from parsing. It is always non-nil.
24+
//
25+
// Clients must not access the AST's legacy ast.Object-related
26+
// fields without first ensuring that [File.Resolve] was
27+
// already called.
2628
File *ast.File
2729
Tok *token.File
2830
// Source code used to build the AST. It may be different from the

gopls/internal/cache/parsego/parse.go

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,36 @@ func Parse(ctx context.Context, fset *token.FileSet, uri protocol.DocumentURI, s
5959
// We passed a byte slice, so the only possible error is a parse error.
6060
parseErr = err.(scanner.ErrorList)
6161
}
62+
// Inv: file != nil.
6263

63-
tok := fset.File(file.Pos())
64-
if tok == nil {
65-
// file.Pos is the location of the package declaration (issue #53202). If there was
66-
// none, we can't find the token.File that ParseFile created, and we
67-
// have no choice but to recreate it.
68-
tok = fset.AddFile(uri.Path(), -1, len(src))
69-
tok.SetLinesForContent(src)
64+
// Workaround for #70162 (missing File{Start,End} when
65+
// parsing empty file) with go1.23.
66+
//
67+
// When parsing an empty file, or one without a valid
68+
// package declaration, the go1.23 parser bails out before
69+
// setting FileStart and End.
70+
//
71+
// This leaves us no way to find the original
72+
// token.File that ParseFile created, so as a
73+
// workaround, we recreate the token.File, and
74+
// populate the FileStart and FileEnd fields.
75+
//
76+
// See also #53202.
77+
tokenFile := func(file *ast.File) *token.File {
78+
tok := fset.File(file.FileStart)
79+
if tok == nil {
80+
tok = fset.AddFile(uri.Path(), -1, len(src))
81+
tok.SetLinesForContent(src)
82+
if file.FileStart.IsValid() {
83+
file.FileStart = token.Pos(tok.Base())
84+
file.FileEnd = token.Pos(tok.Base() + tok.Size())
85+
}
86+
}
87+
return tok
7088
}
7189

90+
tok := tokenFile(file)
91+
7292
fixedSrc := false
7393
fixedAST := false
7494
// If there were parse errors, attempt to fix them up.
@@ -96,15 +116,13 @@ func Parse(ctx context.Context, fset *token.FileSet, uri protocol.DocumentURI, s
96116
}
97117

98118
newFile, newErr := parser.ParseFile(fset, uri.Path(), newSrc, mode)
99-
if newFile == nil {
100-
break // no progress
101-
}
119+
assert(newFile != nil, "ParseFile returned nil") // I/O error can't happen
102120

103121
// Maintain the original parseError so we don't try formatting the
104122
// doctored file.
105123
file = newFile
106124
src = newSrc
107-
tok = fset.File(file.Pos())
125+
tok = tokenFile(file)
108126

109127
// Only now that we accept the fix do we record the src fix from above.
110128
fixes = append(fixes, srcFix)
@@ -122,6 +140,7 @@ func Parse(ctx context.Context, fset *token.FileSet, uri protocol.DocumentURI, s
122140
}
123141
}
124142
}
143+
assert(file != nil, "nil *ast.File")
125144

126145
return &File{
127146
URI: uri,

gopls/internal/golang/extract.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
)
2525

2626
func extractVariable(fset *token.FileSet, start, end token.Pos, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*token.FileSet, *analysis.SuggestedFix, error) {
27-
tokFile := fset.File(file.Pos())
27+
tokFile := fset.File(file.FileStart)
2828
expr, path, ok, err := canExtractVariable(start, end, file)
2929
if !ok {
3030
return nil, nil, fmt.Errorf("extractVariable: cannot extract %s: %v", safetoken.StartPosition(fset, start), err)
@@ -214,7 +214,7 @@ func extractFunctionMethod(fset *token.FileSet, start, end token.Pos, src []byte
214214
errorPrefix = "extractMethod"
215215
}
216216

217-
tok := fset.File(file.Pos())
217+
tok := fset.File(file.FileStart)
218218
if tok == nil {
219219
return nil, nil, bug.Errorf("no file for position")
220220
}
@@ -821,7 +821,7 @@ func collectFreeVars(info *types.Info, file *ast.File, fileScope, pkgScope *type
821821
if _, ok := obj.(*types.PkgName); ok {
822822
return nil, false // imported package
823823
}
824-
if !(file.Pos() <= obj.Pos() && obj.Pos() <= file.End()) {
824+
if !(file.FileStart <= obj.Pos() && obj.Pos() <= file.FileEnd) {
825825
return nil, false // not defined in this file
826826
}
827827
scope := obj.Parent()

gopls/internal/golang/format.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ func importPrefix(src []byte) (string, error) {
215215
if err != nil { // This can happen if 'package' is misspelled
216216
return "", fmt.Errorf("importPrefix: failed to parse: %s", err)
217217
}
218-
tok := fset.File(f.Pos())
218+
tok := fset.File(f.FileStart)
219219
var importEnd int
220220
for _, d := range f.Decls {
221221
if x, ok := d.(*ast.GenDecl); ok && x.Tok == token.IMPORT {

gopls/internal/golang/inlay_hint.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,9 @@ func InlayHint(ctx context.Context, snapshot *cache.Snapshot, fh file.Handle, pR
5151
q := typesutil.FileQualifier(pgf.File, pkg.Types(), info)
5252

5353
// Set the range to the full file if the range is not valid.
54-
start, end := pgf.File.Pos(), pgf.File.End()
54+
start, end := pgf.File.FileStart, pgf.File.FileEnd
55+
56+
// TODO(adonovan): this condition looks completely wrong!
5557
if pRng.Start.Line < pRng.End.Line || pRng.Start.Character < pRng.End.Character {
5658
// Adjust start and end for the specified range.
5759
var err error

gopls/internal/golang/pkgdoc.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ func PackageDocHTML(viewID string, pkg *cache.Package, web Web) ([]byte, error)
282282
// TODO(adonovan): simulate that too.
283283
fileMap := make(map[string]*ast.File)
284284
for _, f := range pkg.Syntax() {
285-
fileMap[pkg.FileSet().File(f.Pos()).Name()] = f
285+
fileMap[pkg.FileSet().File(f.FileStart).Name()] = f
286286
}
287287
astpkg := &ast.Package{
288288
Name: pkg.Types().Name(),

gopls/internal/golang/rename.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1420,7 +1420,7 @@ func parsePackageNameDecl(ctx context.Context, snapshot *cache.Snapshot, fh file
14201420
// enclosingFile returns the CompiledGoFile of pkg that contains the specified position.
14211421
func enclosingFile(pkg *cache.Package, pos token.Pos) (*parsego.File, bool) {
14221422
for _, pgf := range pkg.CompiledGoFiles() {
1423-
if pgf.File.Pos() <= pos && pos <= pgf.File.End() {
1423+
if pgf.File.FileStart <= pos && pos <= pgf.File.FileEnd {
14241424
return pgf, true
14251425
}
14261426
}

gopls/internal/protocol/command/commandmeta/meta.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func findField(pkg *packages.Package, pos token.Pos) (*ast.Field, error) {
248248
fset := pkg.Fset
249249
var file *ast.File
250250
for _, f := range pkg.Syntax {
251-
if fset.File(f.Pos()).Name() == fset.File(pos).Name() {
251+
if fset.File(f.FileStart).Name() == fset.File(pos).Name() {
252252
file = f
253253
break
254254
}

gopls/internal/util/safetoken/safetoken_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func TestWorkaroundIssue57490(t *testing.T) {
2424
src := `package p; func f() { var x struct`
2525
fset := token.NewFileSet()
2626
file, _ := parser.ParseFile(fset, "a.go", src, parser.SkipObjectResolution)
27-
tf := fset.File(file.Pos())
27+
tf := fset.File(file.FileStart)
2828

2929
// Add another file to the FileSet.
3030
file2, _ := parser.ParseFile(fset, "b.go", "package q", parser.SkipObjectResolution)

internal/analysisinternal/addimport_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ func _() {
202202
if err != nil {
203203
t.Log(err)
204204
}
205-
pos := fset.File(f.Pos()).Pos(len(before))
205+
pos := fset.File(f.FileStart).Pos(len(before))
206206

207207
// type-check
208208
info := &types.Info{

internal/imports/imports.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, e
114114
// formatted file, and returns the postpocessed result.
115115
func formatFile(fset *token.FileSet, file *ast.File, src []byte, adjust func(orig []byte, src []byte) []byte, opt *Options) ([]byte, error) {
116116
mergeImports(file)
117-
sortImports(opt.LocalPrefix, fset.File(file.Pos()), file)
117+
sortImports(opt.LocalPrefix, fset.File(file.FileStart), file)
118118
var spacesBefore []string // import paths we need spaces before
119119
for _, impSection := range astutil.Imports(fset, file) {
120120
// Within each block of contiguous imports, see if any

internal/refactor/inline/inline_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func TestData(t *testing.T) {
8686
for _, pkg := range pkgs {
8787
for _, file := range pkg.Syntax {
8888
// Read file content (for @inline regexp, and inliner).
89-
content, err := os.ReadFile(pkg.Fset.File(file.Pos()).Name())
89+
content, err := os.ReadFile(pkg.Fset.File(file.FileStart).Name())
9090
if err != nil {
9191
t.Error(err)
9292
continue
@@ -95,7 +95,7 @@ func TestData(t *testing.T) {
9595
// Read and process @inline notes.
9696
notes, err := expect.ExtractGo(pkg.Fset, file)
9797
if err != nil {
98-
t.Errorf("parsing notes in %q: %v", pkg.Fset.File(file.Pos()).Name(), err)
98+
t.Errorf("parsing notes in %q: %v", pkg.Fset.File(file.FileStart).Name(), err)
9999
continue
100100
}
101101
for _, note := range notes {
@@ -157,7 +157,7 @@ func doInlineNote(logf func(string, ...any), pkg *packages.Package, file *ast.Fi
157157
// Find extent of pattern match within commented line.
158158
var startPos, endPos token.Pos
159159
{
160-
tokFile := pkg.Fset.File(file.Pos())
160+
tokFile := pkg.Fset.File(file.FileStart)
161161
lineStartOffset := int(tokFile.LineStart(posn.Line)) - tokFile.Base()
162162
line := content[lineStartOffset:]
163163
if i := bytes.IndexByte(line, '\n'); i >= 0 {

refactor/rename/mvpkg.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ func (m *mover) move() error {
321321
log.Printf("failed to pretty-print syntax tree: %v", err)
322322
continue
323323
}
324-
tokenFile := m.iprog.Fset.File(f.Pos())
324+
tokenFile := m.iprog.Fset.File(f.FileStart)
325325
writeFile(tokenFile.Name(), buf.Bytes())
326326
}
327327

0 commit comments

Comments
 (0)