internal/lsp: using memoize for all file contents
Change-Id: I7293bbcfea33c0df90f7b6df8e991aae9a03f2ab Reviewed-on: https://go-review.googlesource.com/c/tools/+/180846 Run-TryBot: Ian Cottrell <iancottrell@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
5b939d657d
commit
ce2cddb08b
|
@ -5,6 +5,7 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
"go/token"
|
||||
|
@ -14,6 +15,7 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/debug"
|
||||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/lsp/xlog"
|
||||
"golang.org/x/tools/internal/memoize"
|
||||
"golang.org/x/tools/internal/span"
|
||||
)
|
||||
|
||||
|
@ -32,10 +34,42 @@ type cache struct {
|
|||
fs source.FileSystem
|
||||
id string
|
||||
fset *token.FileSet
|
||||
|
||||
store memoize.Store
|
||||
}
|
||||
|
||||
type fileKey struct {
|
||||
identity source.FileIdentity
|
||||
}
|
||||
|
||||
type fileHandle struct {
|
||||
cache *cache
|
||||
underlying source.FileHandle
|
||||
handle *memoize.Handle
|
||||
}
|
||||
|
||||
type fileData struct {
|
||||
memoize.NoCopy
|
||||
bytes []byte
|
||||
hash string
|
||||
err error
|
||||
}
|
||||
|
||||
func (c *cache) GetFile(uri span.URI) source.FileHandle {
|
||||
return c.fs.GetFile(uri)
|
||||
underlying := c.fs.GetFile(uri)
|
||||
key := fileKey{
|
||||
identity: underlying.Identity(),
|
||||
}
|
||||
h := c.store.Bind(key, func(ctx context.Context) interface{} {
|
||||
data := &fileData{}
|
||||
data.bytes, data.hash, data.err = underlying.Read(ctx)
|
||||
return data
|
||||
})
|
||||
return &fileHandle{
|
||||
cache: c,
|
||||
underlying: underlying,
|
||||
handle: h,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) NewSession(log xlog.Logger) source.Session {
|
||||
|
@ -55,6 +89,23 @@ func (c *cache) FileSet() *token.FileSet {
|
|||
return c.fset
|
||||
}
|
||||
|
||||
func (h *fileHandle) FileSystem() source.FileSystem {
|
||||
return h.cache
|
||||
}
|
||||
|
||||
func (h *fileHandle) Identity() source.FileIdentity {
|
||||
return h.underlying.Identity()
|
||||
}
|
||||
|
||||
func (h *fileHandle) Read(ctx context.Context) ([]byte, string, error) {
|
||||
v := h.handle.Get(ctx)
|
||||
if v == nil {
|
||||
return nil, "", ctx.Err()
|
||||
}
|
||||
data := v.(*fileData)
|
||||
return data.bytes, data.hash, data.err
|
||||
}
|
||||
|
||||
func hashContents(contents []byte) string {
|
||||
// TODO: consider whether sha1 is the best choice here
|
||||
// This hash is used for internal identity detection only
|
||||
|
|
|
@ -42,6 +42,7 @@ func (h *nativeFileHandle) Identity() source.FileIdentity {
|
|||
}
|
||||
|
||||
func (h *nativeFileHandle) Read(ctx context.Context) ([]byte, string, error) {
|
||||
//TODO: this should fail if the version is not the same as the handle
|
||||
data, err := ioutil.ReadFile(h.identity.URI.Filename())
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
|
|
|
@ -225,7 +225,11 @@ func (v *view) SetContent(ctx context.Context, uri span.URI, content []byte) err
|
|||
// including any position and type information that depends on it.
|
||||
func (f *goFile) invalidateContent() {
|
||||
f.view.pcache.mu.Lock()
|
||||
defer f.view.pcache.mu.Unlock()
|
||||
f.handleMu.Lock()
|
||||
defer func() {
|
||||
f.handleMu.Unlock()
|
||||
f.view.pcache.mu.Unlock()
|
||||
}()
|
||||
|
||||
f.ast = nil
|
||||
f.token = nil
|
||||
|
|
Loading…
Reference in New Issue