internal/lsp: remove the GetToken and GetAST functions

Change-Id: Iddbdde5f47a31da9baab6539cd2b5bd858e7f811
Reviewed-on: https://go-review.googlesource.com/c/tools/+/194057
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
This commit is contained in:
Rebecca Stambler 2019-09-06 23:58:07 -04:00
parent 27d1b4e4f3
commit cdebb59945
12 changed files with 84 additions and 73 deletions

View File

@ -7,7 +7,6 @@ package cache
import (
"context"
"go/ast"
"go/token"
"sync"
"golang.org/x/tools/internal/lsp/source"
@ -49,36 +48,6 @@ func (f *goFile) metadata() []*metadata {
return result
}
func (f *goFile) GetToken(ctx context.Context) (*token.File, error) {
file, err := f.GetAST(ctx, source.ParseFull)
if file == nil {
return nil, err
}
tok := f.view.session.cache.fset.File(file.Pos())
if tok == nil {
return nil, errors.Errorf("no token.File for %s", f.URI())
}
return tok, nil
}
func (f *goFile) GetAST(ctx context.Context, mode source.ParseMode) (*ast.File, error) {
ctx = telemetry.File.With(ctx, f.URI())
fh := f.Handle(ctx)
if f.isDirty(ctx, fh) || f.wrongParseMode(ctx, fh, mode) {
if err := f.view.loadParseTypecheck(ctx, f, fh); err != nil {
return nil, err
}
}
// Check for a cached AST first, in case getting a trimmed version would actually cause a re-parse.
cached, err := f.view.session.cache.cachedAST(fh, mode)
if cached != nil || err != nil {
return cached, err
}
ph := f.view.session.cache.ParseGoHandle(fh, mode)
return ph.Parse(ctx)
}
func (cache *cache) cachedAST(fh source.FileHandle, mode source.ParseMode) (*ast.File, error) {
for _, m := range []source.ParseMode{
source.ParseHeader,
@ -175,6 +144,24 @@ func (f *goFile) GetCachedPackage(ctx context.Context) (source.Package, error) {
return cph.Cached(ctx)
}
func (f *goFile) GetCachedPackages(ctx context.Context) ([]source.Package, error) {
f.mu.Lock()
defer f.mu.Unlock()
var pkgs []source.Package
for _, cph := range f.pkgs {
pkg, err := cph.Cached(ctx)
if err != nil {
return nil, err
}
pkgs = append(pkgs, pkg)
}
if len(pkgs) == 0 {
return nil, errors.Errorf("no CheckPackageHandles for %s", f.URI())
}
return pkgs, nil
}
// bestCheckPackageHandle picks the "narrowest" package for a given file.
//
// By "narrowest" package, we mean the package with the fewest number of files

View File

@ -27,16 +27,17 @@ func (s *Server) documentLink(ctx context.Context, params *protocol.DocumentLink
if err != nil {
return nil, err
}
data, _, err := f.Handle(ctx).Read(ctx)
fh := f.Handle(ctx)
data, _, err := fh.Read(ctx)
if err != nil {
return nil, err
}
file, err := f.GetAST(ctx, source.ParseFull)
file, err := view.Session().Cache().ParseGoHandle(fh, source.ParseFull).Parse(ctx)
if file == nil {
return nil, err
}
tok := view.Session().Cache().FileSet().File(file.Pos())
m := protocol.NewColumnMapper(f.URI(), f.URI().Filename(), f.FileSet(), tok, data)
m := protocol.NewColumnMapper(f.URI(), f.URI().Filename(), view.Session().Cache().FileSet(), tok, data)
var links []protocol.DocumentLink
ast.Inspect(file, func(node ast.Node) bool {

View File

@ -26,7 +26,7 @@ func (s *Server) references(ctx context.Context, params *protocol.ReferenceParam
if err != nil {
return nil, err
}
references, err := ident.References(ctx, view)
references, err := ident.References(ctx)
if err != nil {
log.Error(ctx, "no references", err, tag.Of("Identifier", ident.Name))
}

View File

@ -19,15 +19,16 @@ type FoldingRangeInfo struct {
func FoldingRange(ctx context.Context, view View, f GoFile, lineFoldingOnly bool) (ranges []*FoldingRangeInfo, err error) {
// TODO(suzmue): consider limiting the number of folding ranges returned, and
// implement a way to prioritize folding ranges in that case.
fset := f.FileSet()
file, err := f.GetAST(ctx, ParseFull)
fh := f.Handle(ctx)
file, err := view.Session().Cache().ParseGoHandle(fh, ParseFull).Parse(ctx)
if err != nil {
return nil, err
}
data, _, err := f.Handle(ctx).Read(ctx)
data, _, err := fh.Read(ctx)
if err != nil {
return nil, err
}
fset := view.Session().Cache().FileSet()
m := protocol.NewColumnMapper(f.URI(), f.URI().Filename(), fset, fset.File(file.Pos()), data)
// Get folding ranges for comments separately as they are not walked by ast.Inspect.

View File

@ -8,6 +8,7 @@ package source
import (
"bytes"
"context"
"go/ast"
"go/format"
"go/token"
@ -29,14 +30,19 @@ func Format(ctx context.Context, view View, f File) ([]protocol.TextEdit, error)
if !ok {
return nil, errors.Errorf("formatting is not supported for non-Go files")
}
file, err := gof.GetAST(ctx, ParseFull)
if file == nil {
return nil, err
}
pkg, err := gof.GetPackage(ctx)
if err != nil {
return nil, err
}
var file *ast.File
for _, ph := range pkg.GetHandles() {
if ph.File().Identity().URI == f.URI() {
file, err = ph.Cached(ctx)
}
}
if file == nil {
return nil, err
}
if hasListErrors(pkg.GetErrors()) || hasParseErrors(pkg, f.URI()) {
// Even if this package has list or parse errors, this file may not
// have any parse errors and can still be formatted. Using format.Node
@ -49,7 +55,7 @@ func Format(ctx context.Context, view View, f File) ([]protocol.TextEdit, error)
return computeTextEdits(ctx, view.Session().Cache().FileSet(), f, string(formatted))
}
fset := f.FileSet()
fset := view.Session().Cache().FileSet()
buf := &bytes.Buffer{}
// format.Node changes slightly from one release to another, so the version

View File

@ -46,7 +46,7 @@ func (i *IdentifierInfo) Hover(ctx context.Context) (*HoverInformation, error) {
switch x := h.source.(type) {
case ast.Node:
var b strings.Builder
if err := format.Node(&b, i.File.FileSet(), x); err != nil {
if err := format.Node(&b, i.View.Session().Cache().FileSet(), x); err != nil {
return nil, err
}
h.Signature = b.String()

View File

@ -21,8 +21,9 @@ import (
// IdentifierInfo holds information about an identifier in Go source.
type IdentifierInfo struct {
Name string
mappedRange
View View
File GoFile
mappedRange
Type struct {
mappedRange
@ -69,11 +70,11 @@ func findIdentifier(ctx context.Context, view View, f GoFile, pkg Package, file
// If the position is not an identifier but immediately follows
// an identifier or selector period (as is common when
// requesting a completion), use the path to the preceding node.
result, err := identifier(ctx, view, f, pkg, file, pos-1)
if result == nil && err == nil {
err = errors.Errorf("no identifier found for %s", f.FileSet().Position(pos))
ident, err := identifier(ctx, view, f, pkg, file, pos-1)
if ident == nil && err == nil {
err = errors.New("no identifier found")
}
return result, err
return ident, err
}
// identifier checks a single position for a potential identifier.
@ -92,6 +93,7 @@ func identifier(ctx context.Context, view View, f GoFile, pkg Package, file *ast
return nil, errors.Errorf("can't find node enclosing position")
}
result := &IdentifierInfo{
View: view,
File: f,
qf: qualifier(file, pkg.GetTypes(), pkg.GetTypesInfo()),
pkg: pkg,
@ -168,7 +170,7 @@ func identifier(ctx context.Context, view View, f GoFile, pkg Package, file *ast
if result.Declaration.mappedRange, err = objToMappedRange(ctx, view, result.Declaration.obj); err != nil {
return nil, err
}
if result.Declaration.node, err = objToNode(ctx, f.View(), pkg.GetTypes(), result.Declaration.obj, result.Declaration.mappedRange.spanRange); err != nil {
if result.Declaration.node, err = objToNode(ctx, view, pkg.GetTypes(), result.Declaration.obj, result.Declaration.mappedRange.spanRange); err != nil {
return nil, err
}
typ := pkg.GetTypesInfo().TypeOf(result.ident)
@ -268,6 +270,7 @@ func importSpec(ctx context.Context, view View, f GoFile, fAST *ast.File, pkg Pa
return nil, errors.Errorf("import path not quoted: %s (%v)", imp.Path.Value, err)
}
result := &IdentifierInfo{
View: view,
File: f,
Name: importPath,
pkg: pkg,

View File

@ -25,7 +25,7 @@ type ReferenceInfo struct {
// References returns a list of references for a given identifier within the packages
// containing i.File. Declarations appear first in the result.
func (i *IdentifierInfo) References(ctx context.Context, view View) ([]*ReferenceInfo, error) {
func (i *IdentifierInfo) References(ctx context.Context) ([]*ReferenceInfo, error) {
ctx, done := trace.StartSpan(ctx, "source.References")
defer done()
var references []*ReferenceInfo
@ -34,8 +34,7 @@ func (i *IdentifierInfo) References(ctx context.Context, view View) ([]*Referenc
if i.Declaration.obj == nil {
return nil, errors.Errorf("no references for an import spec")
}
pkgs, err := i.File.GetPackages(ctx)
pkgs, err := i.File.GetCachedPackages(ctx)
if err != nil {
return nil, err
}
@ -61,7 +60,7 @@ func (i *IdentifierInfo) References(ctx context.Context, view View) ([]*Referenc
if obj == nil || !sameObj(obj, i.Declaration.obj) {
continue
}
rng, err := posToRange(ctx, view, ident.Pos(), ident.End())
rng, err := posToRange(ctx, i.View, ident.Pos(), ident.End())
if err != nil {
return nil, err
}
@ -79,7 +78,7 @@ func (i *IdentifierInfo) References(ctx context.Context, view View) ([]*Referenc
if obj == nil || !sameObj(obj, i.Declaration.obj) {
continue
}
rng, err := posToRange(ctx, view, ident.Pos(), ident.End())
rng, err := posToRange(ctx, i.View, ident.Pos(), ident.End())
if err != nil {
return nil, err
}

View File

@ -110,14 +110,14 @@ func (i *IdentifierInfo) Rename(ctx context.Context, view View, newName string)
return nil, errors.Errorf("failed to rename because %q is declared in package %q", i.Name, i.Declaration.obj.Pkg().Name())
}
refs, err := i.References(ctx, view)
refs, err := i.References(ctx)
if err != nil {
return nil, err
}
r := renamer{
ctx: ctx,
fset: i.File.FileSet(),
fset: view.Session().Cache().FileSet(),
refs: refs,
objsToUpdate: make(map[types.Object]bool),
from: i.Name,
@ -164,8 +164,16 @@ func (i *IdentifierInfo) Rename(ctx context.Context, view View, newName string)
// getPkgName gets the pkg name associated with an identifer representing
// the import path in an import spec.
func (i *IdentifierInfo) getPkgName(ctx context.Context) (*IdentifierInfo, error) {
file, err := i.File.GetAST(ctx, ParseHeader)
if err != nil {
var (
file *ast.File
err error
)
for _, ph := range i.pkg.GetHandles() {
if ph.File().Identity().URI == i.File.URI() {
file, err = ph.Cached(ctx)
}
}
if file == nil {
return nil, err
}
var namePos token.Pos
@ -211,6 +219,7 @@ func getPkgNameIdentifier(ctx context.Context, ident *IdentifierInfo, pkgName *t
}
return &IdentifierInfo{
Name: pkgName.Name(),
View: ident.View,
mappedRange: decl.mappedRange,
File: ident.File,
Declaration: decl,

View File

@ -461,11 +461,12 @@ func (r *runner) Import(t *testing.T, data tests.Imports) {
if err != nil {
t.Fatalf("failed for %v: %v", spn, err)
}
tok, err := f.(source.GoFile).GetToken(ctx)
fh := f.Handle(ctx)
tok, err := r.view.Session().Cache().TokenHandle(fh).Token(ctx)
if err != nil {
t.Fatalf("failed to get token for %s: %v", spn.URI(), err)
t.Fatal(err)
}
rng, err := spn.Range(span.NewTokenConverter(f.FileSet(), tok))
rng, err := spn.Range(span.NewTokenConverter(r.data.Exported.ExpectFileSet, tok))
if err != nil {
t.Fatalf("failed for %v: %v", spn, err)
}
@ -476,7 +477,7 @@ func (r *runner) Import(t *testing.T, data tests.Imports) {
}
continue
}
data, _, err := f.Handle(ctx).Read(ctx)
data, _, err := fh.Read(ctx)
if err != nil {
t.Error(err)
continue
@ -596,7 +597,7 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
want[pos] = true
}
refs, err := ident.References(ctx, r.view)
refs, err := ident.References(ctx)
if err != nil {
t.Fatalf("failed for %v: %v", src, err)
}

View File

@ -18,14 +18,20 @@ func DocumentSymbols(ctx context.Context, view View, f GoFile) ([]protocol.Docum
ctx, done := trace.StartSpan(ctx, "source.DocumentSymbols")
defer done()
file, err := f.GetAST(ctx, ParseFull)
if file == nil {
return nil, err
}
pkg, err := f.GetPackage(ctx)
if err != nil {
return nil, err
}
var file *ast.File
for _, ph := range pkg.GetHandles() {
if ph.File().Identity().URI == f.URI() {
file, err = ph.Cached(ctx)
}
}
if file == nil {
return nil, err
}
info := pkg.GetTypesInfo()
q := qualifier(file, pkg.GetTypes(), info)

View File

@ -259,8 +259,6 @@ type File interface {
URI() span.URI
View() View
Handle(ctx context.Context) FileHandle
FileSet() *token.FileSet
GetToken(ctx context.Context) (*token.File, error)
}
// GoFile represents a Go source file that has been type-checked.
@ -269,12 +267,12 @@ type GoFile interface {
Builtin() (*ast.File, bool)
// GetAST returns the AST for the file, at or above the given mode.
GetAST(ctx context.Context, mode ParseMode) (*ast.File, error)
// GetCachedPackage returns the cached package for the file, if any.
GetCachedPackage(ctx context.Context) (Package, error)
// GetCachedPackage returns the cached package for the file, if any.
GetCachedPackages(ctx context.Context) ([]Package, error)
// GetPackage returns the CheckPackageHandle for the package that this file belongs to.
GetCheckPackageHandle(ctx context.Context) (CheckPackageHandle, error)