// findQueryPos searches fset for filename and translates the // specified file-relative byte offsets into token.Pos form. It // returns an error if the file was not found or the offsets were out // of bounds. // func findQueryPos(fset *token.FileSet, filename string, startOffset, endOffset int) (start, end token.Pos, err error) { var file *token.File fset.Iterate(func(f *token.File) bool { if sameFile(filename, f.Name()) { // (f.Name() is absolute) file = f return false // done } return true // continue }) if file == nil { err = fmt.Errorf("couldn't find file containing position") return } // Range check [start..end], inclusive of both end-points. if 0 <= startOffset && startOffset <= file.Size() { start = file.Pos(int(startOffset)) } else { err = fmt.Errorf("start position is beyond end of file") return } if 0 <= endOffset && endOffset <= file.Size() { end = file.Pos(int(endOffset)) } else { err = fmt.Errorf("end position is beyond end of file") return } return }
// parseQueryPos parses a string of the form "file:pos" or // file:start,end" where pos, start, end match #%d and represent byte // offsets, and returns the extent to which it refers. // // (Numbers without a '#' prefix are reserved for future use, // e.g. to indicate line/column positions.) // func parseQueryPos(fset *token.FileSet, queryPos string) (start, end token.Pos, err error) { if queryPos == "" { err = fmt.Errorf("no source position specified (-pos flag)") return } colon := strings.LastIndex(queryPos, ":") if colon < 0 { err = fmt.Errorf("invalid source position -pos=%q", queryPos) return } filename, offset := queryPos[:colon], queryPos[colon+1:] startOffset := -1 endOffset := -1 if hyphen := strings.Index(offset, ","); hyphen < 0 { // e.g. "foo.go:#123" startOffset = parseOctothorpDecimal(offset) endOffset = startOffset } else { // e.g. "foo.go:#123,#456" startOffset = parseOctothorpDecimal(offset[:hyphen]) endOffset = parseOctothorpDecimal(offset[hyphen+1:]) } if startOffset < 0 || endOffset < 0 { err = fmt.Errorf("invalid -pos offset %q", offset) return } var file *token.File fset.Iterate(func(f *token.File) bool { if sameFile(filename, f.Name()) { // (f.Name() is absolute) file = f return false // done } return true // continue }) if file == nil { err = fmt.Errorf("couldn't find file containing position -pos=%q", queryPos) return } // Range check [start..end], inclusive of both end-points. if 0 <= startOffset && startOffset <= file.Size() { start = file.Pos(int(startOffset)) } else { err = fmt.Errorf("start position is beyond end of file -pos=%q", queryPos) return } if 0 <= endOffset && endOffset <= file.Size() { end = file.Pos(int(endOffset)) } else { err = fmt.Errorf("end position is beyond end of file -pos=%q", queryPos) return } return }
func GetLines(f *token.File) []int { lines := make([]int, 0, 20) l := -1 for i := f.Base(); i < f.Base()+f.Size(); i++ { if f.Line(token.Pos(i)) > l { l = f.Line(token.Pos(i)) lines = append(lines, f.Offset(token.Pos(i))) } } return lines }
// fileOffsetToPos translates the specified file-relative byte offsets // into token.Pos form. It returns an error if the file was not found // or the offsets were out of bounds. // func fileOffsetToPos(file *token.File, startOffset, endOffset int) (start, end token.Pos, err error) { // Range check [start..end], inclusive of both end-points. if 0 <= startOffset && startOffset <= file.Size() { start = file.Pos(int(startOffset)) } else { err = fmt.Errorf("start position is beyond end of file") return } if 0 <= endOffset && endOffset <= file.Size() { end = file.Pos(int(endOffset)) } else { err = fmt.Errorf("end position is beyond end of file") return } return }
// Init prepares the scanner s to tokenize the text src by setting the // scanner at the beginning of src. The scanner uses the file set file // for position information and it adds line information for each line. // It is ok to re-use the same file when re-scanning the same file as // line information which is already present is ignored. Init causes a // panic if the file size does not match the src size. // // Calls to Scan will invoke the error handler err if they encounter a // syntax error and err is not nil. Also, for each error encountered, // the Scanner field ErrorCount is incremented by one. The mode parameter // determines how comments are handled. // // Note that Init may call err if there is an error in the first character // of the file. // func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) { // Explicitly initialize all fields since a scanner may be reused. if file.Size() != len(src) { panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src))) } s.file = file s.dir, _ = filepath.Split(file.Name()) s.src = src s.err = err s.mode = mode s.ch = ' ' s.offset = 0 s.rdOffset = 0 s.lineOffset = 0 s.insertSemi = false s.ErrorCount = 0 s.next() }
// Init prepares the scanner S to tokenize the text src by setting the // scanner at the beginning of src. The scanner uses the file set file // for position information and it adds line information for each line. // It is ok to re-use the same file when re-scanning the same file as // line information which is already present is ignored. Init causes a // panic if the file size does not match the src size. // // Calls to Scan will use the error handler err if they encounter a // syntax error and err is not nil. Also, for each error encountered, // the Scanner field ErrorCount is incremented by one. The mode parameter // determines how comments, illegal characters, and semicolons are handled. // // Note that Init may call err if there is an error in the first character // of the file. // func (S *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode uint) { // Explicitly initialize all fields since a scanner may be reused. if file.Size() != len(src) { panic("file size does not match src len") } S.file = file S.dir, _ = filepath.Split(file.Name()) S.src = src S.err = err S.mode = mode S.ch = ' ' S.offset = 0 S.rdOffset = 0 S.lineOffset = 0 S.insertSemi = false S.ErrorCount = 0 S.next() }
func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) { if file.Size() != len(src) { panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src))) } s.tokScanner = scan.Scanner{Matcher: getTokenMatcher()} s.errScanner = scan.Scanner{Matcher: getErrorMatcher()} s.src = skipBOM(src) s.tokScanner.SetSource(s.src) s.errScanner.SetSource(s.src) s.file = file s.fileBase = s.file.Base() s.dir, _ = filepath.Split(file.Name()) s.err = err s.mode = mode s.ErrorCount = 0 s.preSemi = false s.semiPos = 0 }
func (s *Scanner) Init(file *token.File, src []byte, err ErrorHandler, mode Mode) { //fmt.Println("Init src", strconv.Quote(string(src)), mode) if file.Size() != len(src) { panic(fmt.Sprintf("file size (%d) does not match src len (%d)", file.Size(), len(src))) } s.gombiScanner = newGombiScanner() s.SetSource(skipBOM(src)) s.file = file s.dir, _ = filepath.Split(file.Name()) s.err = err s.mode = mode s.ErrorCount = 0 s.lastIsPreSemi = false s.commentAfterPreSemi = false s.endOfLinePos = 0 s.endOfLine = 0 s.commentQueue.reset() }
// TODO(adonovan): make this a method: func (*token.File) Contains(token.Pos) func tokenFileContainsPos(f *token.File, pos token.Pos) bool { p := int(pos) base := f.Base() return base <= p && p < base+f.Size() }