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
|
package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha1"
|
"crypto/sha1"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
"golang.org/x/tools/internal/lsp/debug"
|
"golang.org/x/tools/internal/lsp/debug"
|
||||||
"golang.org/x/tools/internal/lsp/source"
|
"golang.org/x/tools/internal/lsp/source"
|
||||||
"golang.org/x/tools/internal/lsp/xlog"
|
"golang.org/x/tools/internal/lsp/xlog"
|
||||||
|
"golang.org/x/tools/internal/memoize"
|
||||||
"golang.org/x/tools/internal/span"
|
"golang.org/x/tools/internal/span"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,10 +34,42 @@ type cache struct {
|
||||||
fs source.FileSystem
|
fs source.FileSystem
|
||||||
id string
|
id string
|
||||||
fset *token.FileSet
|
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 {
|
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 {
|
func (c *cache) NewSession(log xlog.Logger) source.Session {
|
||||||
|
@ -55,6 +89,23 @@ func (c *cache) FileSet() *token.FileSet {
|
||||||
return c.fset
|
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 {
|
func hashContents(contents []byte) string {
|
||||||
// TODO: consider whether sha1 is the best choice here
|
// TODO: consider whether sha1 is the best choice here
|
||||||
// This hash is used for internal identity detection only
|
// 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) {
|
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())
|
data, err := ioutil.ReadFile(h.identity.URI.Filename())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
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.
|
// including any position and type information that depends on it.
|
||||||
func (f *goFile) invalidateContent() {
|
func (f *goFile) invalidateContent() {
|
||||||
f.view.pcache.mu.Lock()
|
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.ast = nil
|
||||||
f.token = nil
|
f.token = nil
|
||||||
|
|
Loading…
Reference in New Issue