go/token: add (*File).End method

Also, use it in a number of places.

+ test, api, relnote

Fixes #75849

Change-Id: I44acf5b8190b964fd3975009aa407d7c82cee19b
Reviewed-on: https://go-review.googlesource.com/c/go/+/720061
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
Alan Donovan 2025-11-12 18:17:35 -05:00
parent 65c09eafdf
commit 1297fae708
8 changed files with 22 additions and 7 deletions

1
api/next/75849.txt Normal file
View file

@ -0,0 +1 @@
pkg go/token, method (*File) End() Pos #75849

View file

@ -0,0 +1 @@
The new [File.End] convenience method returns the file's end position.

View file

@ -30,10 +30,10 @@ func TestIssue33649(t *testing.T) {
tf = f
return true
})
tfEnd := tf.Base() + tf.Size()
tfEnd := tf.End()
fd := f.Decls[len(f.Decls)-1].(*ast.FuncDecl)
fdEnd := int(fd.End())
fdEnd := fd.End()
if fdEnd != tfEnd {
t.Errorf("%q: got fdEnd = %d; want %d (base = %d, size = %d)", src, fdEnd, tfEnd, tf.Base(), tf.Size())

View file

@ -120,7 +120,7 @@ func ParseFile(fset *token.FileSet, filename string, src any, mode Mode) (f *ast
// Ensure the start/end are consistent,
// whether parsing succeeded or not.
f.FileStart = token.Pos(file.Base())
f.FileEnd = token.Pos(file.Base() + file.Size())
f.FileEnd = file.End()
p.errors.Sort()
err = p.errors.Err()

View file

@ -127,6 +127,11 @@ func (f *File) Size() int {
return f.size
}
// End returns the end position of file f as registered with AddFile.
func (f *File) End() Pos {
return Pos(f.base + f.size)
}
// LineCount returns the number of lines in file f.
func (f *File) LineCount() int {
f.mutex.Lock()

View file

@ -572,7 +572,7 @@ func fsetString(fset *FileSet) string {
buf.WriteRune('{')
sep := ""
fset.Iterate(func(f *File) bool {
fmt.Fprintf(&buf, "%s%s:%d-%d", sep, f.Name(), f.Base(), f.Base()+f.Size())
fmt.Fprintf(&buf, "%s%s:%d-%d", sep, f.Name(), f.Base(), f.End())
sep = " "
return true
})
@ -643,3 +643,11 @@ func TestRemovedFileFileReturnsNil(t *testing.T) {
}
}
}
func TestFile_End(t *testing.T) {
f := NewFileSet().AddFile("a.go", 100, 42)
got := fmt.Sprintf("%d, %d", f.Base(), f.End())
if want := "100, 142"; got != want {
t.Errorf("Base, End = %s, want %s", got, want)
}
}

View file

@ -313,8 +313,8 @@ func (t *tree) add(file *File) {
}
if prev := (*pos).file; prev != file {
panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)",
prev.Name(), prev.Base(), prev.Base()+prev.Size(),
file.Name(), file.Base(), file.Base()+file.Size()))
prev.Name(), prev.Base(), prev.End(),
file.Name(), file.Base(), file.End()))
}
}

View file

@ -247,7 +247,7 @@ func (check *Checker) collectObjects() {
// Be conservative and use the *ast.File extent if we don't have a *token.File.
pos, end := file.Pos(), file.End()
if f := check.fset.File(file.Pos()); f != nil {
pos, end = token.Pos(f.Base()), token.Pos(f.Base()+f.Size())
pos, end = token.Pos(f.Base()), f.End()
}
fileScope := NewScope(pkg.scope, pos, end, check.filename(fileNo))
fileScopes[fileNo] = fileScope