From 1612b8734a7c76ae462f243f29d54760a417a867 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 7 Dec 2010 21:50:08 -0800 Subject: [PATCH] token/position.go: provide FileSet.File(), minor optimizations R=rsc CC=golang-dev https://golang.org/cl/3399042 --- src/pkg/go/token/position.go | 46 +++++++++++++++++++++---------- src/pkg/go/token/position_test.go | 3 ++ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/pkg/go/token/position.go b/src/pkg/go/token/position.go index 64a89c2814e..10ec0e39b79 100644 --- a/src/pkg/go/token/position.go +++ b/src/pkg/go/token/position.go @@ -25,14 +25,6 @@ type Position struct { } -// TODO(gri): Remove Pos() below once all code is switched to using token.Pos. - -// Pos is an accessor method for anonymous Position fields. -// It returns its receiver. -// -func (pos *Position) Pos() Position { return *pos } - - // IsValid returns true if the position is valid. func (pos *Position) IsValid() bool { return pos.Line > 0 } @@ -113,6 +105,28 @@ func (s *FileSet) file(p Pos) *File { } +// File returns the file which contains the position p. +// If no such file is found (for instance for p == NoPos), +// the result is nil. +// +func (s *FileSet) File(p Pos) (f *File) { + if p != NoPos { + s.mutex.RLock() + f = s.file(p) + s.mutex.RUnlock() + } + return +} + + +func (f *File) position(p Pos) (pos Position) { + offset := int(p) - f.base + pos.Offset = offset + pos.Filename, pos.Line, pos.Column = f.info(offset) + return +} + + // Position converts a Pos in the fileset into a general Position. func (s *FileSet) Position(p Pos) (pos Position) { if p != NoPos { @@ -122,9 +136,7 @@ func (s *FileSet) Position(p Pos) (pos Position) { // of search s.mutex.RLock() if f := s.file(p); f != nil { - offset := int(p) - f.base - pos.Offset = offset - pos.Filename, pos.Line, pos.Column = f.info(offset) + pos = f.position(p) } s.mutex.RUnlock() } @@ -274,8 +286,7 @@ func (f *File) Position(p Pos) (pos Position) { if int(p) < f.base || int(p) > f.base+f.size { panic("illegal Pos value") } - // TODO(gri) compute Position directly instead of going via the fset! - pos = f.set.Position(p) + pos = f.position(p) } return } @@ -309,6 +320,9 @@ func (f *File) info(offset int) (filename string, line, column int) { // A FileSet represents a set of source files. +// Methods of file sets are synchronized; multiple goroutines +// may invoke them concurrently. +// type FileSet struct { mutex sync.RWMutex // protects the file set base int // base offset for the next file @@ -330,7 +344,11 @@ func NewFileSet() *FileSet { // AddFile when adding the next file. // func (s *FileSet) Base() int { - return s.base + s.mutex.RLock() + b := s.base + s.mutex.RUnlock() + return b + } diff --git a/src/pkg/go/token/position_test.go b/src/pkg/go/token/position_test.go index 7e5f3d3dfad..bc10ef6c0ae 100644 --- a/src/pkg/go/token/position_test.go +++ b/src/pkg/go/token/position_test.go @@ -89,6 +89,9 @@ func TestPositions(t *testing.T) { if f.Size() != test.size { t.Errorf("%s: expected file size %d; got %d", f.Name(), test.size, f.Size()) } + if fset.File(f.Pos(0)) != f { + t.Errorf("%s: f.Pos(0) was not found in f", f.Name()) + } // add lines individually and verify all positions for i, offset := range test.lines {