1
0
mirror of https://github.com/golang/go synced 2024-10-01 13:08:32 -06:00
go/internal/lsp/cache/token.go
Jan Steinke be5259f298 internal/lsp: use x/xerrors to create new errors
This relates to https://github.com/golang/go/issues/31374 and should switch all instances within `gopls` to use `x/errors` instead of `fmt` to create new errors.

Change-Id: I18339b75d12418d852e0dcc2ba0ed6c2970783b3
GitHub-Last-Rev: f4a55d9b79e7458ef1f1e06cb5eabbabd884f321
GitHub-Pull-Request: golang/tools#108
Reviewed-on: https://go-review.googlesource.com/c/tools/+/179880
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2019-08-06 19:46:56 +00:00

95 lines
1.9 KiB
Go

// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package cache
import (
"context"
"go/token"
"golang.org/x/tools/internal/lsp/source"
"golang.org/x/tools/internal/memoize"
errors "golang.org/x/xerrors"
)
type tokenKey struct {
file source.FileIdentity
}
type tokenHandle struct {
handle *memoize.Handle
file source.FileHandle
}
type tokenData struct {
memoize.NoCopy
tok *token.File
err error
}
func (c *cache) TokenHandle(fh source.FileHandle) source.TokenHandle {
key := tokenKey{
file: fh.Identity(),
}
h := c.store.Bind(key, func(ctx context.Context) interface{} {
data := &tokenData{}
data.tok, data.err = tokenFile(ctx, c, fh)
return data
})
return &tokenHandle{
handle: h,
file: fh,
}
}
func (h *tokenHandle) File() source.FileHandle {
return h.file
}
func (h *tokenHandle) Token(ctx context.Context) (*token.File, error) {
v := h.handle.Get(ctx)
if v == nil {
return nil, ctx.Err()
}
data := v.(*tokenData)
return data.tok, data.err
}
func tokenFile(ctx context.Context, c *cache, fh source.FileHandle) (*token.File, error) {
// First, check if we already have a parsed AST for this file's handle.
for _, mode := range []source.ParseMode{
source.ParseHeader,
source.ParseExported,
source.ParseFull,
} {
pk := parseKey{
file: fh.Identity(),
mode: mode,
}
pd, ok := c.store.Cached(pk).(*parseGoData)
if !ok {
continue
}
if pd.ast == nil {
continue
}
if !pd.ast.Pos().IsValid() {
continue
}
return c.FileSet().File(pd.ast.Pos()), nil
}
// We have not yet parsed this file.
buf, _, err := fh.Read(ctx)
if err != nil {
return nil, err
}
tok := c.FileSet().AddFile(fh.Identity().URI.Filename(), -1, len(buf))
if tok == nil {
return nil, errors.Errorf("no token.File for %s", fh.Identity().URI)
}
tok.SetLinesForContent(buf)
return tok, nil
}