internal/lsp: remove the pkg.view field, in preparation for CL 204079

This change encompasses the refactorings needed to correctly implement
CL 204079. The goal of this CL is to make the actual relevant diffs more
clear.

Change-Id: I38acfd436e2380be790910e01b6e37d8280e9100
Reviewed-on: https://go-review.googlesource.com/c/tools/+/204139
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
Reviewed-by: Ian Cottrell <iancottrell@google.com>
diff --git a/internal/lsp/cache/analysis.go b/internal/lsp/cache/analysis.go
index e707f73..f66388f 100644
--- a/internal/lsp/cache/analysis.go
+++ b/internal/lsp/cache/analysis.go
@@ -262,7 +262,7 @@
 
 	var errors []*source.Error
 	for _, diag := range diagnostics {
-		srcErr, err := sourceError(ctx, act.pkg, diag)
+		srcErr, err := sourceError(ctx, fset, act.pkg, diag)
 		if err != nil {
 			return nil, nil, err
 		}
diff --git a/internal/lsp/cache/check.go b/internal/lsp/cache/check.go
index ff0f412..3af794f 100644
--- a/internal/lsp/cache/check.go
+++ b/internal/lsp/cache/check.go
@@ -9,6 +9,7 @@
 	"context"
 	"fmt"
 	"go/ast"
+	"go/token"
 	"go/types"
 	"sort"
 	"sync"
@@ -69,6 +70,7 @@
 	if err != nil {
 		return nil, err
 	}
+	fset := s.View().Session().Cache().FileSet()
 	h := s.view.session.cache.store.Bind(string(cph.key), func(ctx context.Context) interface{} {
 		// Begin loading the direct dependencies, in parallel.
 		for _, impID := range cph.imports {
@@ -81,7 +83,7 @@
 			}(dep)
 		}
 		data := &checkPackageData{}
-		data.pkg, data.err = s.typeCheck(ctx, cph)
+		data.pkg, data.err = s.typeCheck(ctx, fset, cph)
 		return data
 	})
 	cph.handle = h
@@ -211,7 +213,7 @@
 	return phs, nil
 }
 
-func (s *snapshot) typeCheck(ctx context.Context, cph *checkPackageHandle) (*pkg, error) {
+func (s *snapshot) typeCheck(ctx context.Context, fset *token.FileSet, cph *checkPackageHandle) (*pkg, error) {
 	ctx, done := trace.StartSpan(ctx, "cache.importer.typeCheck", telemetry.Package.Of(cph.m.id))
 	defer done()
 
@@ -221,7 +223,6 @@
 	}
 
 	pkg := &pkg{
-		view:       s.view,
 		id:         cph.m.id,
 		mode:       cph.mode,
 		pkgPath:    cph.m.pkgPath,
@@ -305,7 +306,7 @@
 	// We don't care about a package's errors unless we have parsed it in full.
 	if cph.mode == source.ParseFull {
 		for _, e := range rawErrors {
-			srcErr, err := sourceError(ctx, pkg, e)
+			srcErr, err := sourceError(ctx, fset, pkg, e)
 			if err != nil {
 				return nil, err
 			}
diff --git a/internal/lsp/cache/errors.go b/internal/lsp/cache/errors.go
index 4a569f2..315f157 100644
--- a/internal/lsp/cache/errors.go
+++ b/internal/lsp/cache/errors.go
@@ -18,7 +18,7 @@
 	errors "golang.org/x/xerrors"
 )
 
-func sourceError(ctx context.Context, pkg *pkg, e interface{}) (*source.Error, error) {
+func sourceError(ctx context.Context, fset *token.FileSet, pkg *pkg, e interface{}) (*source.Error, error) {
 	var (
 		spn           span.Span
 		err           error
@@ -27,7 +27,6 @@
 		fixes         []source.SuggestedFix
 		related       []source.RelatedInformation
 	)
-	fset := pkg.view.session.cache.fset
 	switch e := e.(type) {
 	case packages.Error:
 		if e.Pos == "" {
@@ -163,7 +162,7 @@
 		return span.Span{}, err
 	}
 	posn := fset.Position(pos)
-	ph, _, err := pkg.FindFile(ctx, span.FileURI(posn.Filename))
+	ph, _, err := findFileInPackage(ctx, span.FileURI(posn.Filename), pkg)
 	if err != nil {
 		return spn, nil // ignore errors
 	}
@@ -196,7 +195,7 @@
 }
 
 func scannerErrorRange(ctx context.Context, fset *token.FileSet, pkg *pkg, posn token.Position) (span.Span, error) {
-	ph, _, err := pkg.FindFile(ctx, span.FileURI(posn.Filename))
+	ph, _, err := findFileInPackage(ctx, span.FileURI(posn.Filename), pkg)
 	if err != nil {
 		return span.Span{}, err
 	}
@@ -224,7 +223,7 @@
 // spanToRange converts a span.Span to a protocol.Range,
 // assuming that the span belongs to the package whose diagnostics are being computed.
 func spanToRange(ctx context.Context, pkg *pkg, spn span.Span) (protocol.Range, error) {
-	ph, _, err := pkg.FindFile(ctx, spn.URI())
+	ph, _, err := findFileInPackage(ctx, spn.URI(), pkg)
 	if err != nil {
 		return protocol.Range{}, err
 	}
diff --git a/internal/lsp/cache/pkg.go b/internal/lsp/cache/pkg.go
index 6d8099a..613f809 100644
--- a/internal/lsp/cache/pkg.go
+++ b/internal/lsp/cache/pkg.go
@@ -17,8 +17,6 @@
 
 // pkg contains the type information needed by the source package.
 type pkg struct {
-	view *view
-
 	// ID and package path have their own types to avoid being used interchangeably.
 	id      packageID
 	pkgPath packagePath
@@ -38,10 +36,6 @@
 type packageID string
 type packagePath string
 
-func (p *pkg) View() source.View {
-	return p.view
-}
-
 func (p *pkg) ID() string {
 	return string(p.id)
 }
@@ -94,7 +88,7 @@
 	return p.types == nil || p.typesInfo == nil || p.typesSizes == nil
 }
 
-func (p *pkg) GetImport(ctx context.Context, pkgPath string) (source.Package, error) {
+func (p *pkg) GetImport(pkgPath string) (source.Package, error) {
 	if imp := p.imports[packagePath(pkgPath)]; imp != nil {
 		return imp, nil
 	}
@@ -102,6 +96,14 @@
 	return nil, errors.Errorf("no imported package for %s", pkgPath)
 }
 
+func (p *pkg) Imports() []source.Package {
+	var result []source.Package
+	for _, imp := range p.imports {
+		result = append(result, imp)
+	}
+	return result
+}
+
 func (s *snapshot) FindAnalysisError(ctx context.Context, id string, diag protocol.Diagnostic) (*source.Error, error) {
 	acts := s.getActionHandles(packageID(id), source.ParseFull)
 	for _, act := range acts {
@@ -125,13 +127,8 @@
 	return nil, errors.Errorf("no matching diagnostic for %v", diag)
 }
 
-func (p *pkg) FindFile(ctx context.Context, uri span.URI) (source.ParseGoHandle, source.Package, error) {
-	// Special case for ignored files.
-	if p.view.Ignore(uri) {
-		return p.view.findIgnoredFile(ctx, uri)
-	}
-
-	queue := []*pkg{p}
+func findFileInPackage(ctx context.Context, uri span.URI, pkg source.Package) (source.ParseGoHandle, source.Package, error) {
+	queue := []source.Package{pkg}
 	seen := make(map[string]bool)
 
 	for len(queue) > 0 {
@@ -139,12 +136,12 @@
 		queue = queue[1:]
 		seen[pkg.ID()] = true
 
-		for _, ph := range pkg.files {
+		for _, ph := range pkg.Files() {
 			if ph.File().Identity().URI == uri {
 				return ph, pkg, nil
 			}
 		}
-		for _, dep := range pkg.imports {
+		for _, dep := range pkg.Imports() {
 			if !seen[dep.ID()] {
 				queue = append(queue, dep)
 			}
diff --git a/internal/lsp/cache/view.go b/internal/lsp/cache/view.go
index 2271660..2a5c45e 100644
--- a/internal/lsp/cache/view.go
+++ b/internal/lsp/cache/view.go
@@ -418,6 +418,14 @@
 	return results
 }
 
+func (v *view) FindFileInPackage(ctx context.Context, uri span.URI, pkg source.Package) (source.ParseGoHandle, source.Package, error) {
+	// Special case for ignored files.
+	if v.Ignore(uri) {
+		return v.findIgnoredFile(ctx, uri)
+	}
+	return findFileInPackage(ctx, uri, pkg)
+}
+
 type debugView struct{ *view }
 
 func (v debugView) ID() string             { return v.id }
diff --git a/internal/lsp/source/completion_format.go b/internal/lsp/source/completion_format.go
index 3123dae..e03857e 100644
--- a/internal/lsp/source/completion_format.go
+++ b/internal/lsp/source/completion_format.go
@@ -125,7 +125,7 @@
 		return item, nil
 	}
 	uri := span.FileURI(pos.Filename)
-	ph, pkg, err := c.pkg.FindFile(c.ctx, uri)
+	ph, pkg, err := c.view.FindFileInPackage(c.ctx, uri, c.pkg)
 	if err != nil {
 		return CompletionItem{}, err
 	}
diff --git a/internal/lsp/source/identifier.go b/internal/lsp/source/identifier.go
index ac286af..4addaf3 100644
--- a/internal/lsp/source/identifier.go
+++ b/internal/lsp/source/identifier.go
@@ -108,7 +108,7 @@
 	if path == nil {
 		return nil, errors.Errorf("can't find node enclosing position")
 	}
-	view := pkg.View()
+	view := snapshot.View()
 	uri := span.FileURI(view.Session().Cache().FileSet().Position(pos).Filename)
 	var ph ParseGoHandle
 	for _, h := range pkg.Files() {
@@ -134,7 +134,7 @@
 		}
 	}
 	result.Name = result.ident.Name
-	if result.mappedRange, err = posToMappedRange(ctx, pkg, result.ident.Pos(), result.ident.End()); err != nil {
+	if result.mappedRange, err = posToMappedRange(ctx, view, pkg, result.ident.Pos(), result.ident.End()); err != nil {
 		return nil, err
 	}
 	result.Declaration.obj = pkg.GetTypesInfo().ObjectOf(result.ident)
@@ -165,7 +165,7 @@
 			return nil, errors.Errorf("no declaration for %s", result.Name)
 		}
 		result.Declaration.node = decl
-		if result.Declaration.mappedRange, err = nameToMappedRange(ctx, pkg, decl.Pos(), result.Name); err != nil {
+		if result.Declaration.mappedRange, err = nameToMappedRange(ctx, view, pkg, decl.Pos(), result.Name); err != nil {
 			return nil, err
 		}
 		return result, nil
@@ -190,10 +190,10 @@
 		}
 	}
 
-	if result.Declaration.mappedRange, err = objToMappedRange(ctx, pkg, result.Declaration.obj); err != nil {
+	if result.Declaration.mappedRange, err = objToMappedRange(ctx, view, pkg, result.Declaration.obj); err != nil {
 		return nil, err
 	}
-	if result.Declaration.node, err = objToNode(ctx, pkg, result.Declaration.obj); err != nil {
+	if result.Declaration.node, err = objToNode(ctx, snapshot.View(), pkg, result.Declaration.obj); err != nil {
 		return nil, err
 	}
 	typ := pkg.GetTypesInfo().TypeOf(result.ident)
@@ -207,7 +207,7 @@
 		if hasErrorType(result.Type.Object) {
 			return result, nil
 		}
-		if result.Type.mappedRange, err = objToMappedRange(ctx, pkg, result.Type.Object); err != nil {
+		if result.Type.mappedRange, err = objToMappedRange(ctx, view, pkg, result.Type.Object); err != nil {
 			return nil, err
 		}
 	}
@@ -241,10 +241,9 @@
 	return types.IsInterface(obj.Type()) && obj.Pkg() == nil && obj.Name() == "error"
 }
 
-func objToNode(ctx context.Context, pkg Package, obj types.Object) (ast.Decl, error) {
-	view := pkg.View()
-	uri := span.FileURI(view.Session().Cache().FileSet().Position(obj.Pos()).Filename)
-	ph, _, err := pkg.FindFile(ctx, uri)
+func objToNode(ctx context.Context, v View, pkg Package, obj types.Object) (ast.Decl, error) {
+	uri := span.FileURI(v.Session().Cache().FileSet().Position(obj.Pos()).Filename)
+	ph, _, err := v.FindFileInPackage(ctx, uri, pkg)
 	if err != nil {
 		return nil, err
 	}
@@ -292,7 +291,7 @@
 	if err != nil {
 		return nil, errors.Errorf("import path not quoted: %s (%v)", imp.Path.Value, err)
 	}
-	uri := span.FileURI(pkg.View().Session().Cache().FileSet().Position(pos).Filename)
+	uri := span.FileURI(snapshot.View().Session().Cache().FileSet().Position(pos).Filename)
 	var ph ParseGoHandle
 	for _, h := range pkg.Files() {
 		if h.File().Identity().URI == uri {
@@ -305,11 +304,11 @@
 		Name:     importPath,
 		pkg:      pkg,
 	}
-	if result.mappedRange, err = posToMappedRange(ctx, pkg, imp.Path.Pos(), imp.Path.End()); err != nil {
+	if result.mappedRange, err = posToMappedRange(ctx, snapshot.View(), pkg, imp.Path.Pos(), imp.Path.End()); err != nil {
 		return nil, err
 	}
 	// Consider the "declaration" of an import spec to be the imported package.
-	importedPkg, err := pkg.GetImport(ctx, importPath)
+	importedPkg, err := pkg.GetImport(importPath)
 	if err != nil {
 		return nil, err
 	}
@@ -326,7 +325,7 @@
 	if dest == nil {
 		return nil, errors.Errorf("package %q has no files", importPath)
 	}
-	if result.Declaration.mappedRange, err = posToMappedRange(ctx, pkg, dest.Pos(), dest.End()); err != nil {
+	if result.Declaration.mappedRange, err = posToMappedRange(ctx, snapshot.View(), pkg, dest.Pos(), dest.End()); err != nil {
 		return nil, err
 	}
 	result.Declaration.node = imp
diff --git a/internal/lsp/source/references.go b/internal/lsp/source/references.go
index d0c60f5..5fd20f8 100644
--- a/internal/lsp/source/references.go
+++ b/internal/lsp/source/references.go
@@ -55,7 +55,7 @@
 		if obj == nil || !sameObj(obj, i.Declaration.obj) {
 			continue
 		}
-		rng, err := posToMappedRange(ctx, i.pkg, ident.Pos(), ident.End())
+		rng, err := posToMappedRange(ctx, i.Snapshot.View(), i.pkg, ident.Pos(), ident.End())
 		if err != nil {
 			return nil, err
 		}
@@ -73,7 +73,7 @@
 		if obj == nil || !sameObj(obj, i.Declaration.obj) {
 			continue
 		}
-		rng, err := posToMappedRange(ctx, i.pkg, ident.Pos(), ident.End())
+		rng, err := posToMappedRange(ctx, i.Snapshot.View(), i.pkg, ident.Pos(), ident.End())
 		if err != nil {
 			return nil, err
 		}
diff --git a/internal/lsp/source/rename.go b/internal/lsp/source/rename.go
index 69f45eb..d6b50f8 100644
--- a/internal/lsp/source/rename.go
+++ b/internal/lsp/source/rename.go
@@ -218,10 +218,10 @@
 		wasImplicit: true,
 	}
 	var err error
-	if decl.mappedRange, err = objToMappedRange(ctx, ident.pkg, decl.obj); err != nil {
+	if decl.mappedRange, err = objToMappedRange(ctx, ident.Snapshot.View(), ident.pkg, decl.obj); err != nil {
 		return nil, err
 	}
-	if decl.node, err = objToNode(ctx, ident.pkg, decl.obj); err != nil {
+	if decl.node, err = objToNode(ctx, ident.Snapshot.View(), ident.pkg, decl.obj); err != nil {
 		return nil, err
 	}
 	return &IdentifierInfo{
diff --git a/internal/lsp/source/rename_check.go b/internal/lsp/source/rename_check.go
index ce79b58..3207719 100644
--- a/internal/lsp/source/rename_check.go
+++ b/internal/lsp/source/rename_check.go
@@ -850,7 +850,7 @@
 			if err != nil {
 				continue
 			}
-			importPkg, err := pkg.GetImport(ctx, importPath)
+			importPkg, err := pkg.GetImport(importPath)
 			if err != nil {
 				return nil, nil, false
 			}
diff --git a/internal/lsp/source/signature_help.go b/internal/lsp/source/signature_help.go
index 4f19067..c884eda 100644
--- a/internal/lsp/source/signature_help.go
+++ b/internal/lsp/source/signature_help.go
@@ -121,11 +121,11 @@
 		comment *ast.CommentGroup
 	)
 	if obj != nil {
-		node, err := objToNode(ctx, pkg, obj)
+		node, err := objToNode(ctx, view, pkg, obj)
 		if err != nil {
 			return nil, err
 		}
-		rng, err := objToMappedRange(ctx, pkg, obj)
+		rng, err := objToMappedRange(ctx, view, pkg, obj)
 		if err != nil {
 			return nil, err
 		}
diff --git a/internal/lsp/source/util.go b/internal/lsp/source/util.go
index 6559765..e056a6e 100644
--- a/internal/lsp/source/util.go
+++ b/internal/lsp/source/util.go
@@ -127,7 +127,7 @@
 	return mrng.Range()
 }
 
-func objToMappedRange(ctx context.Context, pkg Package, obj types.Object) (mappedRange, error) {
+func objToMappedRange(ctx context.Context, v View, pkg Package, obj types.Object) (mappedRange, error) {
 	if pkgName, ok := obj.(*types.PkgName); ok {
 		// An imported Go package has a package-local, unqualified name.
 		// When the name matches the imported package name, there is no
@@ -140,26 +140,26 @@
 		// When the identifier does not appear in the source, have the range
 		// of the object be the point at the beginning of the declaration.
 		if pkgName.Imported().Name() == pkgName.Name() {
-			return nameToMappedRange(ctx, pkg, obj.Pos(), "")
+			return nameToMappedRange(ctx, v, pkg, obj.Pos(), "")
 		}
 	}
-	return nameToMappedRange(ctx, pkg, obj.Pos(), obj.Name())
+	return nameToMappedRange(ctx, v, pkg, obj.Pos(), obj.Name())
 }
 
-func nameToMappedRange(ctx context.Context, pkg Package, pos token.Pos, name string) (mappedRange, error) {
-	return posToMappedRange(ctx, pkg, pos, pos+token.Pos(len(name)))
+func nameToMappedRange(ctx context.Context, v View, pkg Package, pos token.Pos, name string) (mappedRange, error) {
+	return posToMappedRange(ctx, v, pkg, pos, pos+token.Pos(len(name)))
 }
 
 func nodeToMappedRange(ctx context.Context, view View, m *protocol.ColumnMapper, n ast.Node) (mappedRange, error) {
 	return posToRange(ctx, view, m, n.Pos(), n.End())
 }
 
-func posToMappedRange(ctx context.Context, pkg Package, pos, end token.Pos) (mappedRange, error) {
-	m, err := posToMapper(ctx, pkg, pos)
+func posToMappedRange(ctx context.Context, v View, pkg Package, pos, end token.Pos) (mappedRange, error) {
+	m, err := posToMapper(ctx, v, pkg, pos)
 	if err != nil {
 		return mappedRange{}, err
 	}
-	return posToRange(ctx, pkg.View(), m, pos, end)
+	return posToRange(ctx, v, m, pos, end)
 }
 
 func posToRange(ctx context.Context, view View, m *protocol.ColumnMapper, pos, end token.Pos) (mappedRange, error) {
@@ -175,9 +175,9 @@
 	}, nil
 }
 
-func posToMapper(ctx context.Context, pkg Package, pos token.Pos) (*protocol.ColumnMapper, error) {
-	posn := pkg.View().Session().Cache().FileSet().Position(pos)
-	ph, _, err := pkg.FindFile(ctx, span.FileURI(posn.Filename))
+func posToMapper(ctx context.Context, v View, pkg Package, pos token.Pos) (*protocol.ColumnMapper, error) {
+	posn := v.Session().Cache().FileSet().Position(pos)
+	ph, _, err := v.FindFileInPackage(ctx, span.FileURI(posn.Filename), pkg)
 	if err != nil {
 		return nil, err
 	}
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index fad38dc..8935f33 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -249,6 +249,10 @@
 	// dependencies of this file's package.
 	GetActiveReverseDeps(ctx context.Context, f File) []CheckPackageHandle
 
+	// FindFileInPackage returns the AST and type information for a file that may
+	// belong to or be part of a dependency of the given package.
+	FindFileInPackage(ctx context.Context, uri span.URI, pkg Package) (ParseGoHandle, Package, error)
+
 	// Snapshot returns the current snapshot for the view.
 	Snapshot() Snapshot
 }
@@ -292,15 +296,8 @@
 	GetTypesInfo() *types.Info
 	GetTypesSizes() types.Sizes
 	IsIllTyped() bool
-
-	// GetImport returns the CheckPackageHandle for a package imported by this package.
-	GetImport(ctx context.Context, pkgPath string) (Package, error)
-
-	// FindFile returns the AST and type information for a file that may
-	// belong to or be part of a dependency of the given package.
-	FindFile(ctx context.Context, uri span.URI) (ParseGoHandle, Package, error)
-
-	View() View
+	GetImport(pkgPath string) (Package, error)
+	Imports() []Package
 }
 
 type Error struct {