1
0
mirror of https://github.com/golang/go synced 2024-10-01 03:18:33 -06:00

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:
Alan Donovan 2015-12-29 19:06:21 -05:00
parent 3a85b8da38
commit 2dff1e88eb
3 changed files with 35 additions and 7 deletions

View File

@ -168,29 +168,33 @@ func (r *referrersResult) display(printf printfFunc) {
// Show referring lines, like grep.
type fileinfo struct {
refs []*ast.Ident
linenums []int // line number of refs[i]
data chan []byte // file contents
linenums []int // line number of refs[i]
data chan interface{} // file contents or error
}
var fileinfos []*fileinfo
fileinfosByName := make(map[string]*fileinfo)
// First pass: start the file reads concurrently.
sema := make(chan struct{}, 20) // counting semaphore to limit I/O concurrency
for _, ref := range r.refs {
posn := r.qpos.fset.Position(ref.Pos())
fi := fileinfosByName[posn.Filename]
if fi == nil {
fi = &fileinfo{data: make(chan []byte)}
fi = &fileinfo{data: make(chan interface{})}
fileinfosByName[posn.Filename] = fi
fileinfos = append(fileinfos, fi)
// First request for this file:
// start asynchronous read.
go func() {
sema <- struct{}{} // acquire token
content, err := ioutil.ReadFile(posn.Filename)
<-sema // release token
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)
@ -200,8 +204,20 @@ func (r *referrersResult) display(printf printfFunc) {
// Second pass: print refs in original order.
// One line may have several refs at different columns.
for _, fi := range fileinfos {
content := <-fi.data // wait for I/O completion
lines := bytes.Split(content, []byte("\n"))
v := <-fi.data // wait for I/O completion
// 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 {
printf(ref, "%s", lines[fi.linenums[i]-1])
}

View File

@ -24,3 +24,11 @@ func main() {
var s2 s
s2.f = 1
}
// Test //line directives:
type U int // @referrers ref-type-U "U"
//line nosuchfile.y:123
var u1 U
var u2 U

View File

@ -36,3 +36,7 @@
_ = s{}.f // @referrers ref-field "f"
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)