mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile/internal/syntax: permit /*line file:line:col*/ directives
R=go1.11 This implements parsing of /*line file:line*/ and /*line file:line:col*/ directives and also extends the optional column format to regular //line directives, per #22662. For a line directive to be recognized, its comment text must start with the prefix "line " which is followed by one of the following: :line :line:col filename:line filename:line:col with at least one : present. The line and col values must be unsigned decimal integers; everything before is considered part of the filename. Valid line directives are: //line :123 //line :123:8 //line foo.go:123 //line C:foo.go:123 (filename is "C:foo.go") //line C:foo.go:123:8 (filename is "C:foo.go") /*line ::123*/ (filename is ":") No matter the comment format, at the moment all directives act as if they were in //line comments, and column information is ignored. To be addressed in subsequent CLs. For #22662. Change-Id: I1a2dc54bacc94bc6cdedc5229ee13278971f314e Reviewed-on: https://go-review.googlesource.com/86037 Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
e87f2a1b70
commit
ac45cb9aa0
4 changed files with 170 additions and 37 deletions
|
|
@ -47,8 +47,9 @@ func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh P
|
|||
p.error_at(p.pos_at(line, col), msg)
|
||||
},
|
||||
func(line, col uint, text string) {
|
||||
if strings.HasPrefix(text, "line ") {
|
||||
p.updateBase(line, col+5, text[5:])
|
||||
const prefix = "line "
|
||||
if strings.HasPrefix(text, prefix) {
|
||||
p.updateBase(line, col+uint(len(prefix)), text[len(prefix):])
|
||||
return
|
||||
}
|
||||
if pragh != nil {
|
||||
|
|
@ -69,23 +70,54 @@ func (p *parser) init(base *src.PosBase, r io.Reader, errh ErrorHandler, pragh P
|
|||
const lineMax = 1<<24 - 1 // TODO(gri) this limit is defined for src.Pos - fix
|
||||
|
||||
func (p *parser) updateBase(line, col uint, text string) {
|
||||
// Want to use LastIndexByte below but it's not defined in Go1.4 and bootstrap fails.
|
||||
i := strings.LastIndex(text, ":") // look from right (Windows filenames may contain ':')
|
||||
if i < 0 {
|
||||
i, n, ok := trailingDigits(text)
|
||||
if i == 0 {
|
||||
return // ignore (not a line directive)
|
||||
}
|
||||
nstr := text[i+1:]
|
||||
n, err := strconv.Atoi(nstr)
|
||||
if err != nil || n <= 0 || n > lineMax {
|
||||
p.error_at(p.pos_at(line, col+uint(i+1)), "invalid line number: "+nstr)
|
||||
// i > 0
|
||||
|
||||
if !ok {
|
||||
// text has a suffix :xxx but xxx is not a number
|
||||
p.error_at(p.pos_at(line, col+i), "invalid line number: "+text[i:])
|
||||
return
|
||||
}
|
||||
filename := text[:i]
|
||||
|
||||
i2, n2, ok2 := trailingDigits(text[:i-1])
|
||||
if ok2 {
|
||||
//line filename:line:col
|
||||
i, i2 = i2, i
|
||||
n, n2 = n2, n
|
||||
if n2 == 0 {
|
||||
p.error_at(p.pos_at(line, col+i2), "invalid column number: "+text[i2:])
|
||||
return
|
||||
}
|
||||
text = text[:i2-1] // lop off :col
|
||||
}
|
||||
|
||||
if n == 0 || n > lineMax {
|
||||
p.error_at(p.pos_at(line, col+i), "invalid line number: "+text[i:])
|
||||
return
|
||||
}
|
||||
|
||||
filename := text[:i-1] // lop off :line
|
||||
absFilename := filename
|
||||
if p.fileh != nil {
|
||||
absFilename = p.fileh(filename)
|
||||
}
|
||||
p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), filename, absFilename, uint(n))
|
||||
|
||||
// TODO(gri) pass column n2 to NewLinePragmaBase
|
||||
p.base = src.NewLinePragmaBase(src.MakePos(p.base.Pos().Base(), line, col), filename, absFilename, uint(n) /*uint(n2)*/)
|
||||
}
|
||||
|
||||
func trailingDigits(text string) (uint, uint, bool) {
|
||||
// Want to use LastIndexByte below but it's not defined in Go1.4 and bootstrap fails.
|
||||
i := strings.LastIndex(text, ":") // look from right (Windows filenames may contain ':')
|
||||
if i < 0 {
|
||||
return 0, 0, false // no ":"
|
||||
}
|
||||
// i >= 0
|
||||
n, err := strconv.ParseUint(text[i+1:], 10, 0)
|
||||
return uint(i + 1), uint(n), err == nil
|
||||
}
|
||||
|
||||
func (p *parser) got(tok token) bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue