oracle: referrers: fix crash when loading nonexistent files
Files with //line directives may not exist. Print a helpful error instead of panicking when a file fails to load. + Test. Fixes issue #13459 Change-Id: I305d1380e66e64d20ea84a27c284f53c019fe5e6 Reviewed-on: https://go-review.googlesource.com/18209 Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
parent
3a85b8da38
commit
2dff1e88eb
|
@ -169,28 +169,32 @@ func (r *referrersResult) display(printf printfFunc) {
|
||||||
type fileinfo struct {
|
type fileinfo struct {
|
||||||
refs []*ast.Ident
|
refs []*ast.Ident
|
||||||
linenums []int // line number of refs[i]
|
linenums []int // line number of refs[i]
|
||||||
data chan []byte // file contents
|
data chan interface{} // file contents or error
|
||||||
}
|
}
|
||||||
var fileinfos []*fileinfo
|
var fileinfos []*fileinfo
|
||||||
fileinfosByName := make(map[string]*fileinfo)
|
fileinfosByName := make(map[string]*fileinfo)
|
||||||
|
|
||||||
// First pass: start the file reads concurrently.
|
// First pass: start the file reads concurrently.
|
||||||
|
sema := make(chan struct{}, 20) // counting semaphore to limit I/O concurrency
|
||||||
for _, ref := range r.refs {
|
for _, ref := range r.refs {
|
||||||
posn := r.qpos.fset.Position(ref.Pos())
|
posn := r.qpos.fset.Position(ref.Pos())
|
||||||
fi := fileinfosByName[posn.Filename]
|
fi := fileinfosByName[posn.Filename]
|
||||||
if fi == nil {
|
if fi == nil {
|
||||||
fi = &fileinfo{data: make(chan []byte)}
|
fi = &fileinfo{data: make(chan interface{})}
|
||||||
fileinfosByName[posn.Filename] = fi
|
fileinfosByName[posn.Filename] = fi
|
||||||
fileinfos = append(fileinfos, fi)
|
fileinfos = append(fileinfos, fi)
|
||||||
|
|
||||||
// First request for this file:
|
// First request for this file:
|
||||||
// start asynchronous read.
|
// start asynchronous read.
|
||||||
go func() {
|
go func() {
|
||||||
|
sema <- struct{}{} // acquire token
|
||||||
content, err := ioutil.ReadFile(posn.Filename)
|
content, err := ioutil.ReadFile(posn.Filename)
|
||||||
|
<-sema // release token
|
||||||
if err != nil {
|
if err != nil {
|
||||||
content = []byte(fmt.Sprintf("error: %v", err))
|
fi.data <- err
|
||||||
}
|
} else {
|
||||||
fi.data <- content
|
fi.data <- content
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
fi.refs = append(fi.refs, ref)
|
fi.refs = append(fi.refs, ref)
|
||||||
|
@ -200,8 +204,20 @@ func (r *referrersResult) display(printf printfFunc) {
|
||||||
// Second pass: print refs in original order.
|
// Second pass: print refs in original order.
|
||||||
// One line may have several refs at different columns.
|
// One line may have several refs at different columns.
|
||||||
for _, fi := range fileinfos {
|
for _, fi := range fileinfos {
|
||||||
content := <-fi.data // wait for I/O completion
|
v := <-fi.data // wait for I/O completion
|
||||||
lines := bytes.Split(content, []byte("\n"))
|
|
||||||
|
// Print one item for all refs in a file that could not
|
||||||
|
// be loaded (perhaps due to //line directives).
|
||||||
|
if err, ok := v.(error); ok {
|
||||||
|
var suffix string
|
||||||
|
if more := len(fi.refs) - 1; more > 0 {
|
||||||
|
suffix = fmt.Sprintf(" (+ %d more refs in this file)", more)
|
||||||
|
}
|
||||||
|
printf(fi.refs[0], "%v%s", err, suffix)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
lines := bytes.Split(v.([]byte), []byte("\n"))
|
||||||
for i, ref := range fi.refs {
|
for i, ref := range fi.refs {
|
||||||
printf(ref, "%s", lines[fi.linenums[i]-1])
|
printf(ref, "%s", lines[fi.linenums[i]-1])
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,3 +24,11 @@ func main() {
|
||||||
var s2 s
|
var s2 s
|
||||||
s2.f = 1
|
s2.f = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test //line directives:
|
||||||
|
|
||||||
|
type U int // @referrers ref-type-U "U"
|
||||||
|
|
||||||
|
//line nosuchfile.y:123
|
||||||
|
var u1 U
|
||||||
|
var u2 U
|
||||||
|
|
|
@ -36,3 +36,7 @@
|
||||||
_ = s{}.f // @referrers ref-field "f"
|
_ = s{}.f // @referrers ref-field "f"
|
||||||
s2.f = 1
|
s2.f = 1
|
||||||
|
|
||||||
|
-------- @referrers ref-type-U --------
|
||||||
|
2 references to type U int
|
||||||
|
open testdata/src/referrers/nosuchfile.y: no such file or directory (+ 1 more refs in this file)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue