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:
parent
3a85b8da38
commit
2dff1e88eb
@ -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])
|
||||
}
|
||||
|
8
oracle/testdata/src/referrers/main.go
vendored
8
oracle/testdata/src/referrers/main.go
vendored
@ -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
|
||||
|
4
oracle/testdata/src/referrers/main.golden
vendored
4
oracle/testdata/src/referrers/main.golden
vendored
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user