func (f *File) AddLineColumnInfo(offset int, filename string, line, column int) {
	f.mutex.Lock()
	if i := len(f.infos); i == 0 || f.infos[i-1].Offset < offset && offset < f.size {
		f.infos = append(f.infos, lineInfo{offset, filename, line, column})
	}
	f.mutex.Unlock()
}
AddLineColumnInfo adds alternative file, line, and column number
information for a given file offset. The offset must be larger
than the offset for the previously added alternative line info
and smaller than the file size; otherwise the information is
ignored.

AddLineColumnInfo is typically used to register alternative position
information for line directives such as //line filename:line:column.
package syntax
import (
	"fmt"
	"sort"
	"sync"
)
type Position struct {
	Filename string  
	Offset   int     
	Line     int     
	Column   int     
}
func (pos *Position) IsValid() bool { return pos.Line > 0 }
func (pos Position) String() string {
	s := pos.Filename
	if pos.IsValid() {
		if s != "" {
			s += ":"
		}
		s += fmt.Sprintf("%d", pos.Line)
		if pos.Column != 0 {
			s += fmt.Sprintf(":%d", pos.Column)
		}
	}
	if s == "" {
		s = "-"
	}
	return s
}
type Pos int
const NoPos Pos = 0
func (p Pos) IsValid() bool {
	return p != NoPos
}
type File struct {
	set  *FileSet
	name string  
	base int     
	size int     
	mutex sync.Mutex
	lines []int  
	infos []lineInfo
}
func (f *File) Name() string {
	return f.name
}
func (f *File) Base() int {
	return f.base
}
func (f *File) Size() int {
	return f.size
}
func (f *File) LineCount() int {
	f.mutex.Lock()
	n := len(f.lines)
	f.mutex.Unlock()
	return n
}
func (f *File) AddLine(offset int) {
	f.mutex.Lock()
	if i := len(f.lines); (i == 0 || f.lines[i-1] < offset) && offset < f.size {
		f.lines = append(f.lines, offset)
	}
	f.mutex.Unlock()
}
func (f *File) MergeLine(line int) {
	if line <= 0 {
		panic("illegal line number (line numbering starts at 1)")
	}
	f.mutex.Lock()
	defer f.mutex.Unlock()
	if line >= len(f.lines) {
		panic("illegal line number")
	}
	copy(f.lines[line:], f.lines[line+1:])
	f.lines = f.lines[:len(f.lines)-1]
}
func (f *File) SetLines(lines []int) bool {
	size := f.size
	for i, offset := range lines {
		if i > 0 && offset <= lines[i-1] || size <= offset {
			return false
		}
	}
	f.mutex.Lock()
	f.lines = lines
	f.mutex.Unlock()
	return true
}
func (f *File) SetLinesForContent(content []byte) {
	var lines []int
	line := 0
	for offset, b := range content {
		if line >= 0 {
			lines = append(lines, line)
		}
		line = -1
		if b == '\n' {
			line = offset + 1
		}
	}
	f.mutex.Lock()
	f.lines = lines
	f.mutex.Unlock()
}
type lineInfo struct {
	Offset       int
	Filename     string
	Line, Column int
}
func (f *File) AddLineInfo(offset int, filename string, line int) {
	f.AddLineColumnInfo(offset, filename, line, 1)
}