gopls/internal/lsp/cache: use Package.FileSet where possible

This change adds a FileSet field to Package, and uses it in
preference to Snapshot.FileSet wherever that is appropriate:
all but a handful of places.

For now, they must continue to refer to the same instance,
but once we do away with the Snapshot's cache of parsed files,
there will be no need for a global FileSet and each Package
will be able to create its own. (Some care will be required
to make sure it is always clear which package owns each
each token.Pos/ast.Node/types.Object when there are several
in play.)

Updates golang/go#56291

Change-Id: I017eb794ffb737550da6ae88462d23a8f5c1e1e7
Reviewed-on: https://go-review.googlesource.com/c/tools/+/448377
Run-TryBot: Alan Donovan <adonovan@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
gopls-CI: kokoro <noreply+kokoro@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
This commit is contained in:
Alan Donovan 2022-11-07 18:08:35 -05:00
parent 8f3241104a
commit 13648cdeaf
31 changed files with 144 additions and 123 deletions

View File

@ -286,7 +286,7 @@ func actionImpl(ctx context.Context, snapshot *snapshot, deps []*actionHandle, a
var rawDiagnostics []analysis.Diagnostic
pass := &analysis.Pass{
Analyzer: analyzer,
Fset: snapshot.FileSet(),
Fset: pkg.FileSet(),
Files: syntax,
Pkg: pkg.GetTypes(),
TypesInfo: pkg.GetTypesInfo(),

View File

@ -450,6 +450,7 @@ func doTypeCheck(ctx context.Context, snapshot *snapshot, goFiles, compiledGoFil
pkg := &pkg{
m: m,
mode: mode,
fset: snapshot.FileSet(), // must match parse call below (snapshot.ParseGo for now)
deps: make(map[PackageID]*pkg),
types: types.NewPackage(string(m.PkgPath), string(m.Name)),
typesInfo: &types.Info{
@ -565,7 +566,7 @@ func doTypeCheck(ctx context.Context, snapshot *snapshot, goFiles, compiledGoFil
// We passed typecheckCgo to go/packages when we Loaded.
typesinternal.SetUsesCgo(cfg)
check := types.NewChecker(cfg, snapshot.FileSet(), pkg.types, pkg.typesInfo)
check := types.NewChecker(cfg, pkg.fset, pkg.types, pkg.typesInfo)
var files []*ast.File
for _, cgf := range pkg.compiledGoFiles {
@ -593,7 +594,7 @@ func parseCompiledGoFiles(ctx context.Context, compiledGoFiles []source.FileHand
if mode == source.ParseFull {
pgf, err = snapshot.ParseGo(ctx, fh, mode)
} else {
pgf, err = parseGoImpl(ctx, snapshot.FileSet(), fh, mode) // ~20us/KB
pgf, err = parseGoImpl(ctx, pkg.fset, fh, mode) // ~20us/KB
}
if err != nil {
return err
@ -661,6 +662,7 @@ func (s *snapshot) depsErrors(ctx context.Context, pkg *pkg) ([]*source.Diagnost
}
allImports := map[string][]fileImport{}
for _, cgf := range pkg.compiledGoFiles {
// TODO(adonovan): modify Imports() to accept a single token.File (cgf.Tok).
for _, group := range astutil.Imports(s.FileSet(), cgf.File) {
for _, imp := range group {
if imp.Path == nil {

View File

@ -104,7 +104,7 @@ var importErrorRe = regexp.MustCompile(`could not import ([^\s]+)`)
var unsupportedFeatureRe = regexp.MustCompile(`.*require.* go(\d+\.\d+) or later`)
func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*source.Diagnostic, error) {
code, spn, err := typeErrorData(snapshot.FileSet(), pkg, e.primary)
code, spn, err := typeErrorData(pkg, e.primary)
if err != nil {
return nil, err
}
@ -129,7 +129,7 @@ func typeErrorDiagnostics(snapshot *snapshot, pkg *pkg, e extendedError) ([]*sou
}
for _, secondary := range e.secondaries {
_, secondarySpan, err := typeErrorData(snapshot.FileSet(), pkg, secondary)
_, secondarySpan, err := typeErrorData(pkg, secondary)
if err != nil {
return nil, err
}
@ -201,7 +201,7 @@ func analysisDiagnosticDiagnostics(snapshot *snapshot, pkg *pkg, a *analysis.Ana
break
}
}
tokFile := snapshot.FileSet().File(e.Pos)
tokFile := pkg.fset.File(e.Pos)
if tokFile == nil {
return nil, bug.Errorf("no file for position of %q diagnostic", e.Category)
}
@ -221,7 +221,7 @@ func analysisDiagnosticDiagnostics(snapshot *snapshot, pkg *pkg, a *analysis.Ana
if len(srcAnalyzer.ActionKind) == 0 {
kinds = append(kinds, protocol.QuickFix)
}
fixes, err := suggestedAnalysisFixes(snapshot, pkg, e, kinds)
fixes, err := suggestedAnalysisFixes(pkg, e, kinds)
if err != nil {
return nil, err
}
@ -238,7 +238,7 @@ func analysisDiagnosticDiagnostics(snapshot *snapshot, pkg *pkg, a *analysis.Ana
fixes = append(fixes, source.SuggestedFixFromCommand(cmd, kind))
}
}
related, err := relatedInformation(pkg, snapshot.FileSet(), e)
related, err := relatedInformation(pkg, e)
if err != nil {
return nil, err
}
@ -289,12 +289,12 @@ func typesCodeHref(snapshot *snapshot, code typesinternal.ErrorCode) string {
return source.BuildLink(target, "golang.org/x/tools/internal/typesinternal", code.String())
}
func suggestedAnalysisFixes(snapshot *snapshot, pkg *pkg, diag *analysis.Diagnostic, kinds []protocol.CodeActionKind) ([]source.SuggestedFix, error) {
func suggestedAnalysisFixes(pkg *pkg, diag *analysis.Diagnostic, kinds []protocol.CodeActionKind) ([]source.SuggestedFix, error) {
var fixes []source.SuggestedFix
for _, fix := range diag.SuggestedFixes {
edits := make(map[span.URI][]protocol.TextEdit)
for _, e := range fix.TextEdits {
tokFile := snapshot.FileSet().File(e.Pos)
tokFile := pkg.fset.File(e.Pos)
if tokFile == nil {
return nil, bug.Errorf("no file for edit position")
}
@ -327,10 +327,10 @@ func suggestedAnalysisFixes(snapshot *snapshot, pkg *pkg, diag *analysis.Diagnos
return fixes, nil
}
func relatedInformation(pkg *pkg, fset *token.FileSet, diag *analysis.Diagnostic) ([]source.RelatedInformation, error) {
func relatedInformation(pkg *pkg, diag *analysis.Diagnostic) ([]source.RelatedInformation, error) {
var out []source.RelatedInformation
for _, related := range diag.Related {
tokFile := fset.File(related.Pos)
tokFile := pkg.fset.File(related.Pos)
if tokFile == nil {
return nil, bug.Errorf("no file for %q diagnostic position", diag.Category)
}
@ -355,7 +355,7 @@ func relatedInformation(pkg *pkg, fset *token.FileSet, diag *analysis.Diagnostic
return out, nil
}
func typeErrorData(fset *token.FileSet, pkg *pkg, terr types.Error) (typesinternal.ErrorCode, span.Span, error) {
func typeErrorData(pkg *pkg, terr types.Error) (typesinternal.ErrorCode, span.Span, error) {
ecode, start, end, ok := typesinternal.ReadGo116ErrorData(terr)
if !ok {
start, end = terr.Pos, terr.Pos
@ -368,6 +368,7 @@ func typeErrorData(fset *token.FileSet, pkg *pkg, terr types.Error) (typesintern
}
// go/types errors retain their FileSet.
// Sanity-check that we're using the right one.
fset := pkg.FileSet()
if fset != terr.Fset {
return 0, span.Span{}, bug.Errorf("wrong FileSet for type error")
}

View File

@ -50,11 +50,6 @@ func (s *snapshot) load(ctx context.Context, allowNetwork bool, scopes ...loadSc
for _, scope := range scopes {
switch scope := scope.(type) {
case packageLoadScope:
// TODO(adonovan): is this cast sound?? A
// packageLoadScope is really a PackagePath I think.
if source.IsCommandLineArguments(PackageID(scope)) {
panic("attempted to load command-line-arguments")
}
// The only time we pass package paths is when we're doing a
// partial workspace load. In those cases, the paths came back from
// go list and should already be GOPATH-vendorized when appropriate.

View File

@ -36,6 +36,8 @@ type parseKey struct {
// ParseGo parses the file whose contents are provided by fh, using a cache.
// The resulting tree may have be fixed up.
//
// Token position information will be added to the snapshot's FileSet.
//
// The parser mode must not be ParseExported: that mode is used during
// type checking to destructively trim the tree to reduce work,
// which is not safe for values from a shared cache.

View File

@ -8,6 +8,7 @@ import (
"fmt"
"go/ast"
"go/scanner"
"go/token"
"go/types"
"sort"
@ -21,6 +22,7 @@ import (
type pkg struct {
m *Metadata
mode source.ParseMode
fset *token.FileSet // for now, same as the snapshot's FileSet
goFiles []*source.ParsedGoFile
compiledGoFiles []*source.ParsedGoFile
diagnostics []*source.Diagnostic
@ -45,7 +47,7 @@ type loadScope interface {
type (
fileLoadScope span.URI // load packages containing a file (including command-line-arguments)
packageLoadScope string // load a specific package
packageLoadScope string // load a specific package (the value is its PackageID)
moduleLoadScope string // load packages in a specific module
viewLoadScope span.URI // load the workspace
)
@ -90,6 +92,10 @@ func (p *pkg) GetSyntax() []*ast.File {
return syntax
}
func (p *pkg) FileSet() *token.FileSet {
return p.fset
}
func (p *pkg) GetTypes() *types.Package {
return p.types
}

View File

@ -757,7 +757,7 @@ func (c *commandHandler) ListImports(ctx context.Context, args command.URIArg) (
if err != nil {
return err
}
for _, group := range astutil.Imports(deps.snapshot.FileSet(), pgf.File) {
for _, group := range astutil.Imports(pkg.FileSet(), pgf.File) {
for _, imp := range group {
if imp.Path == nil {
continue

View File

@ -9,14 +9,14 @@ import (
"fmt"
"strings"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
"golang.org/x/tools/gopls/internal/lsp/lsppos"
"golang.org/x/tools/gopls/internal/lsp/protocol"
"golang.org/x/tools/gopls/internal/lsp/source"
"golang.org/x/tools/gopls/internal/lsp/source/completion"
"golang.org/x/tools/gopls/internal/lsp/template"
"golang.org/x/tools/gopls/internal/lsp/work"
"golang.org/x/tools/internal/event"
"golang.org/x/tools/internal/event/tag"
)
func (s *Server) completion(ctx context.Context, params *protocol.CompletionParams) (*protocol.CompletionList, error) {
@ -64,9 +64,9 @@ func (s *Server) completion(ctx context.Context, params *protocol.CompletionPara
if err != nil {
return nil, err
}
tf := snapshot.FileSet().File(surrounding.Start())
mapper := lsppos.NewTokenMapper(src, tf)
rng, err := mapper.Range(surrounding.Start(), surrounding.End())
srng := surrounding.Range()
tf := snapshot.FileSet().File(srng.Start) // not same as srng.TokFile due to //line
rng, err := lsppos.NewTokenMapper(src, tf).Range(srng.Start, srng.End)
if err != nil {
return nil, err
}

View File

@ -112,7 +112,7 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
rng: rng,
ti: pkg.GetTypesInfo(),
pkg: pkg,
fset: snapshot.FileSet(),
fset: pkg.FileSet(),
tokTypes: s.session.Options().SemanticTypes,
tokMods: s.session.Options().SemanticMods,
noStrings: vv.Options().NoSemanticString,

View File

@ -205,7 +205,7 @@ func OutgoingCalls(ctx context.Context, snapshot Snapshot, fh FileHandle, pos pr
// TODO(adonovan): avoid Fileset.File call by somehow getting at
// declMappedRange.spanRange.TokFile, or making Identifier retain the
// token.File of the identifier and its declaration, since it looks up both anyway.
tokFile := snapshot.FileSet().File(node.Pos())
tokFile := identifier.pkg.FileSet().File(node.Pos())
if tokFile == nil {
return nil, fmt.Errorf("no file for position")
}

View File

@ -289,7 +289,7 @@ type completionContext struct {
// A Selection represents the cursor position and surrounding identifier.
type Selection struct {
content string
cursor token.Pos
cursor token.Pos // relative to rng.TokFile
rng span.Range
}
@ -297,12 +297,8 @@ func (p Selection) Content() string {
return p.content
}
func (p Selection) Start() token.Pos {
return p.rng.Start
}
func (p Selection) End() token.Pos {
return p.rng.End
func (p Selection) Range() span.Range {
return p.rng
}
func (p Selection) Prefix() string {
@ -693,7 +689,7 @@ func (c *completer) containingIdent(src []byte) *ast.Ident {
// scanToken scans pgh's contents for the token containing pos.
func (c *completer) scanToken(contents []byte) (token.Pos, token.Token, string) {
tok := c.snapshot.FileSet().File(c.pos)
tok := c.pkg.FileSet().File(c.pos)
var s scanner.Scanner
s.Init(tok, contents, nil, 0)
@ -879,7 +875,7 @@ func (c *completer) populateCommentCompletions(ctx context.Context, comment *ast
}
// Using the comment position find the line after
file := c.snapshot.FileSet().File(comment.End())
file := c.pkg.FileSet().File(comment.End())
if file == nil {
return
}
@ -1246,7 +1242,7 @@ func (c *completer) methodsAndFields(typ types.Type, addressable bool, imp *impo
if isStarTestingDotF(typ) && addressable {
// is that a sufficient test? (or is more care needed?)
if c.fuzz(typ, mset, imp, cb, c.snapshot.FileSet()) {
if c.fuzz(typ, mset, imp, cb, c.pkg.FileSet()) {
return
}
}
@ -1331,7 +1327,7 @@ func (c *completer) lexical(ctx context.Context) error {
node = c.path[i-1]
}
if node != nil {
if resolved := resolveInvalid(c.snapshot.FileSet(), obj, node, c.pkg.GetTypesInfo()); resolved != nil {
if resolved := resolveInvalid(c.pkg.FileSet(), obj, node, c.pkg.GetTypesInfo()); resolved != nil {
obj = resolved
}
}
@ -2033,7 +2029,7 @@ Nodes:
//
// TODO: remove this after https://go.dev/issue/52503
info := &types.Info{Types: make(map[ast.Expr]types.TypeAndValue)}
types.CheckExpr(c.snapshot.FileSet(), c.pkg.GetTypes(), node.Fun.Pos(), node.Fun, info)
types.CheckExpr(c.pkg.FileSet(), c.pkg.GetTypes(), node.Fun.Pos(), node.Fun, info)
sig, _ = info.Types[node.Fun].Type.(*types.Signature)
}

View File

@ -80,7 +80,7 @@ func (c *completer) item(ctx context.Context, cand candidate) (CompletionItem, e
if _, ok := obj.Type().(*types.Struct); ok {
detail = "struct{...}" // for anonymous structs
} else if obj.IsField() {
detail = source.FormatVarType(c.snapshot.FileSet(), c.pkg, obj, c.qf)
detail = source.FormatVarType(c.pkg, obj, c.qf)
}
if obj.IsField() {
kind = protocol.FieldCompletion
@ -227,7 +227,7 @@ Suffixes:
if !c.opts.documentation {
return item, nil
}
pos := c.snapshot.FileSet().Position(obj.Pos())
pos := c.pkg.FileSet().Position(obj.Pos())
// We ignore errors here, because some types, like "unsafe" or "error",
// may not have valid positions that we can use to get documentation.
@ -237,7 +237,7 @@ Suffixes:
uri := span.URIFromPath(pos.Filename)
// Find the source file of the candidate.
pkg, err := source.FindPackageFromPos(c.snapshot.FileSet(), c.pkg, obj.Pos())
pkg, err := source.FindPackageFromPos(c.pkg, obj.Pos())
if err != nil {
return item, nil
}

View File

@ -202,7 +202,7 @@ func (c *completer) functionLiteral(sig *types.Signature, matchScore float64) {
// If the param has no name in the signature, guess a name based
// on the type. Use an empty qualifier to ignore the package.
// For example, we want to name "http.Request" "r", not "hr".
name = source.FormatVarType(c.snapshot.FileSet(), c.pkg, p, func(p *types.Package) string {
name = source.FormatVarType(c.pkg, p, func(p *types.Package) string {
return ""
})
name = abbreviateTypeName(name)
@ -264,7 +264,7 @@ func (c *completer) functionLiteral(sig *types.Signature, matchScore float64) {
// of "i int, j int".
if i == sig.Params().Len()-1 || !types.Identical(p.Type(), sig.Params().At(i+1).Type()) {
snip.WriteText(" ")
typeStr := source.FormatVarType(c.snapshot.FileSet(), c.pkg, p, c.qf)
typeStr := source.FormatVarType(c.pkg, p, c.qf)
if sig.Variadic() && i == sig.Params().Len()-1 {
typeStr = strings.Replace(typeStr, "[]", "...", 1)
}
@ -314,7 +314,7 @@ func (c *completer) functionLiteral(sig *types.Signature, matchScore float64) {
snip.WriteText(name + " ")
}
text := source.FormatVarType(c.snapshot.FileSet(), c.pkg, r, c.qf)
text := source.FormatVarType(c.pkg, r, c.qf)
if tp, _ := r.Type().(*typeparams.TypeParam); tp != nil && !c.typeParamInScope(tp) {
snip.WritePlaceholder(func(snip *snippet.Builder) {
snip.WriteText(text)

View File

@ -31,6 +31,7 @@ import (
func packageClauseCompletions(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle, position protocol.Position) ([]CompletionItem, *Selection, error) {
// We know that the AST for this file will be empty due to the missing
// package declaration, but parse it anyway to get a mapper.
fset := snapshot.FileSet()
pgf, err := snapshot.ParseGo(ctx, fh, source.ParseFull)
if err != nil {
return nil, nil, err
@ -41,7 +42,7 @@ func packageClauseCompletions(ctx context.Context, snapshot source.Snapshot, fh
return nil, nil, err
}
surrounding, err := packageCompletionSurrounding(snapshot.FileSet(), pgf, pos)
surrounding, err := packageCompletionSurrounding(fset, pgf, pos)
if err != nil {
return nil, nil, fmt.Errorf("invalid position for package completion: %w", err)
}

View File

@ -322,7 +322,7 @@ func (c *completer) addPostfixSnippetCandidates(ctx context.Context, sel *ast.Se
return
}
tokFile := c.snapshot.FileSet().File(c.pos)
tokFile := c.pkg.FileSet().File(c.pos)
// Only replace sel with a statement if sel is already a statement.
var stmtOK bool
@ -379,7 +379,7 @@ func (c *completer) addPostfixSnippetCandidates(ctx context.Context, sel *ast.Se
}
tmplArgs := postfixTmplArgs{
X: source.FormatNode(c.snapshot.FileSet(), sel.X),
X: source.FormatNode(c.pkg.FileSet(), sel.X),
StmtOK: stmtOK,
Obj: exprObj(c.pkg.GetTypesInfo(), sel.X),
Type: selType,
@ -442,7 +442,8 @@ func (c *completer) importIfNeeded(pkgPath string, scope *types.Scope) (string,
// Check if file already imports pkgPath.
for _, s := range c.file.Imports {
// TODO(adonovan): what if pkgPath has a vendor/ prefix?
// TODO(adonovan): what if pkgPath has a vendor/ suffix?
// This may be the cause of go.dev/issue/56291.
if source.UnquoteImportPath(s) == source.ImportPath(pkgPath) {
if s.Name == nil {
return defaultName, nil, nil

View File

@ -39,7 +39,7 @@ func (c *completer) structFieldSnippet(cand candidate, detail string, snip *snip
}
})
fset := c.snapshot.FileSet()
fset := c.pkg.FileSet()
// If the cursor position is on a different line from the literal's opening brace,
// we are in a multiline literal.

View File

@ -52,7 +52,7 @@ func (c *completer) addAssignAppend() {
// needsLHS is true if we need to prepend the LHS slice name and
// "=" to our candidate.
needsLHS = false
fset = c.snapshot.FileSet()
fset = c.pkg.FileSet()
)
switch n := c.path[1].(type) {
@ -213,7 +213,7 @@ func (c *completer) addErrCheck() {
var (
// errVar is e.g. "err" in "foo, err := bar()".
errVar = source.FormatNode(c.snapshot.FileSet(), lastAssignee)
errVar = source.FormatNode(c.pkg.FileSet(), lastAssignee)
// Whether we need to include the "if" keyword in our candidate.
needsIf = true

View File

@ -26,7 +26,7 @@ type (
// suggested fixes with their diagnostics, so we have to compute them
// separately. Such analyzers should provide a function with a signature of
// SuggestedFixFunc.
SuggestedFixFunc func(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) (*analysis.SuggestedFix, error)
SuggestedFixFunc func(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) (*token.FileSet, *analysis.SuggestedFix, error)
singleFileFixFunc func(fset *token.FileSet, rng span.Range, src []byte, file *ast.File, pkg *types.Package, info *types.Info) (*analysis.SuggestedFix, error)
)
@ -51,12 +51,13 @@ var suggestedFixes = map[string]SuggestedFixFunc{
// singleFile calls analyzers that expect inputs for a single file
func singleFile(sf singleFileFixFunc) SuggestedFixFunc {
return func(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) (*analysis.SuggestedFix, error) {
return func(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, pRng protocol.Range) (*token.FileSet, *analysis.SuggestedFix, error) {
fset, rng, src, file, pkg, info, err := getAllSuggestedFixInputs(ctx, snapshot, fh, pRng)
if err != nil {
return nil, err
return nil, nil, err
}
return sf(fset, rng, src, file, pkg, info)
fix, err := sf(fset, rng, src, file, pkg, info)
return fset, fix, err
}
}
@ -75,14 +76,13 @@ func ApplyFix(ctx context.Context, fix string, snapshot Snapshot, fh VersionedFi
if !ok {
return nil, fmt.Errorf("no suggested fix function for %s", fix)
}
suggestion, err := handler(ctx, snapshot, fh, pRng)
fset, suggestion, err := handler(ctx, snapshot, fh, pRng)
if err != nil {
return nil, err
}
if suggestion == nil {
return nil, nil
}
fset := snapshot.FileSet()
editsPerFile := map[span.URI]*protocol.TextDocumentEdit{}
for _, edit := range suggestion.TextEdits {
tokFile := fset.File(edit.Pos)
@ -140,5 +140,5 @@ func getAllSuggestedFixInputs(ctx context.Context, snapshot Snapshot, fh FileHan
if err != nil {
return nil, span.Range{}, nil, nil, nil, nil, err
}
return snapshot.FileSet(), rng, pgf.Src, pgf.File, pkg.GetTypes(), pkg.GetTypesInfo(), nil
return pkg.FileSet(), rng, pgf.Src, pgf.File, pkg.GetTypes(), pkg.GetTypesInfo(), nil
}

View File

@ -34,6 +34,7 @@ func Format(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.T
return nil, fmt.Errorf("can't format %q: file is generated", fh.URI().Filename())
}
fset := snapshot.FileSet()
pgf, err := snapshot.ParseGo(ctx, fh, ParseFull)
if err != nil {
return nil, err
@ -49,8 +50,6 @@ func Format(ctx context.Context, snapshot Snapshot, fh FileHandle) ([]protocol.T
return computeTextEdits(ctx, snapshot, pgf, string(formatted))
}
fset := snapshot.FileSet()
// format.Node changes slightly from one release to another, so the version
// of Go used to build the LSP server will determine how it formats code.
// This should be acceptable for all users, who likely be prompted to rebuild

View File

@ -59,7 +59,7 @@ func Highlight(ctx context.Context, snapshot Snapshot, fh FileHandle, position p
}
var ranges []protocol.Range
for rng := range result {
mRng, err := posToMappedRange(snapshot.FileSet(), pkg, rng.start, rng.end)
mRng, err := posToMappedRange(pkg, rng.start, rng.end)
if err != nil {
return nil, err
}

View File

@ -237,7 +237,7 @@ func findRune(ctx context.Context, snapshot Snapshot, fh FileHandle, position pr
return 0, MappedRange{}, ErrNoRuneFound
}
mappedRange, err := posToMappedRange(snapshot.FileSet(), pkg, start, end)
mappedRange, err := posToMappedRange(pkg, start, end)
if err != nil {
return 0, MappedRange{}, err
}
@ -258,7 +258,7 @@ func HoverIdentifier(ctx context.Context, i *IdentifierInfo) (*HoverJSON, error)
Synopsis: doc.Synopsis(hoverCtx.Comment.Text()),
}
fset := i.Snapshot.FileSet()
fset := i.pkg.FileSet()
// Determine the symbol's signature.
switch x := hoverCtx.signatureSource.(type) {
case string:
@ -564,7 +564,7 @@ func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Ob
}
// obj may not have been produced by type checking the AST containing
// node, so we need to be careful about using token.Pos.
tok := s.FileSet().File(obj.Pos())
tok := pkg.FileSet().File(obj.Pos())
offset, err := safetoken.Offset(tok, obj.Pos())
if err != nil {
return nil, err
@ -572,7 +572,7 @@ func FindHoverContext(ctx context.Context, s Snapshot, pkg Package, obj types.Ob
// fullTok and fullPos are the *token.File and object position in for the
// full AST.
fullTok := s.FileSet().File(node.Pos())
fullTok := pkg.FileSet().File(node.Pos())
fullPos, err := safetoken.Pos(fullTok, offset)
if err != nil {
return nil, err

View File

@ -26,7 +26,7 @@ import (
// IdentifierInfo holds information about an identifier in Go source.
type IdentifierInfo struct {
Name string
Snapshot Snapshot
Snapshot Snapshot // only needed for .View(); TODO(adonovan): reduce.
MappedRange
Type struct {
@ -122,7 +122,7 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
// Special case for package declarations, since they have no
// corresponding types.Object.
if ident == file.Name {
rng, err := posToMappedRange(snapshot.FileSet(), pkg, file.Name.Pos(), file.Name.End())
rng, err := posToMappedRange(pkg, file.Name.Pos(), file.Name.End())
if err != nil {
return nil, err
}
@ -136,7 +136,7 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
if declAST == nil {
declAST = file
}
declRng, err := posToMappedRange(snapshot.FileSet(), pkg, declAST.Name.Pos(), declAST.Name.End())
declRng, err := posToMappedRange(pkg, declAST.Name.Pos(), declAST.Name.End())
if err != nil {
return nil, err
}
@ -164,7 +164,7 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
result.Name = result.ident.Name
var err error
if result.MappedRange, err = posToMappedRange(snapshot.FileSet(), pkg, result.ident.Pos(), result.ident.End()); err != nil {
if result.MappedRange, err = posToMappedRange(pkg, result.ident.Pos(), result.ident.End()); err != nil {
return nil, err
}
@ -263,13 +263,13 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
}
}
rng, err := objToMappedRange(snapshot.FileSet(), pkg, result.Declaration.obj)
rng, err := objToMappedRange(pkg, result.Declaration.obj)
if err != nil {
return nil, err
}
result.Declaration.MappedRange = append(result.Declaration.MappedRange, rng)
declPkg, err := FindPackageFromPos(snapshot.FileSet(), pkg, result.Declaration.obj.Pos())
declPkg, err := FindPackageFromPos(pkg, result.Declaration.obj.Pos())
if err != nil {
return nil, err
}
@ -277,7 +277,7 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
// Ensure that we have the full declaration, in case the declaration was
// parsed in ParseExported and therefore could be missing information.
if result.Declaration.fullDecl, err = fullNode(snapshot, result.Declaration.obj, declPkg); err != nil {
if result.Declaration.fullDecl, err = fullNode(pkg.FileSet(), result.Declaration.obj, declPkg); err != nil {
return nil, err
}
typ := pkg.GetTypesInfo().TypeOf(result.ident)
@ -293,7 +293,7 @@ func findIdentifier(ctx context.Context, snapshot Snapshot, pkg Package, pgf *Pa
if hasErrorType(result.Type.Object) {
return result, nil
}
if result.Type.MappedRange, err = objToMappedRange(snapshot.FileSet(), pkg, result.Type.Object); err != nil {
if result.Type.MappedRange, err = objToMappedRange(pkg, result.Type.Object); err != nil {
return nil, err
}
}
@ -315,9 +315,9 @@ func findGenDecl(f *ast.File, spec ast.Spec) *ast.GenDecl {
// fullNode tries to extract the full spec corresponding to obj's declaration.
// If the package was not parsed in full, the declaration file will be
// re-parsed to ensure it has complete syntax.
func fullNode(snapshot Snapshot, obj types.Object, pkg Package) (ast.Decl, error) {
func fullNode(fset *token.FileSet, obj types.Object, pkg Package) (ast.Decl, error) {
// declaration in a different package... make sure we have full AST information.
tok := snapshot.FileSet().File(obj.Pos())
tok := fset.File(obj.Pos())
uri := span.URIFromPath(tok.Name())
pgf, err := pkg.File(uri)
if err != nil {
@ -326,7 +326,6 @@ func fullNode(snapshot Snapshot, obj types.Object, pkg Package) (ast.Decl, error
file := pgf.File
pos := obj.Pos()
if pgf.Mode != ParseFull {
fset := snapshot.FileSet()
file2, _ := parser.ParseFile(fset, tok.Name(), pgf.Src, parser.AllErrors|parser.ParseComments)
if file2 != nil {
offset, err := safetoken.Offset(tok, obj.Pos())
@ -465,13 +464,13 @@ func importSpec(snapshot Snapshot, pkg Package, file *ast.File, pos token.Pos) (
Name: importPath, // should this perhaps be imported.PkgPath()?
pkg: pkg,
}
if result.MappedRange, err = posToMappedRange(snapshot.FileSet(), pkg, imp.Path.Pos(), imp.Path.End()); err != nil {
if result.MappedRange, err = posToMappedRange(pkg, imp.Path.Pos(), imp.Path.End()); err != nil {
return nil, err
}
// Consider the "declaration" of an import spec to be the imported package.
// Return all of the files in the package as the definition of the import spec.
for _, dst := range imported.GetSyntax() {
rng, err := posToMappedRange(snapshot.FileSet(), pkg, dst.Pos(), dst.End())
rng, err := posToMappedRange(pkg, dst.Pos(), dst.End())
if err != nil {
return nil, err
}

View File

@ -32,7 +32,7 @@ func Implementation(ctx context.Context, snapshot Snapshot, f FileHandle, pp pro
if impl.pkg == nil || len(impl.pkg.CompiledGoFiles()) == 0 {
continue
}
rng, err := objToMappedRange(snapshot.FileSet(), impl.pkg, impl.obj)
rng, err := objToMappedRange(impl.pkg, impl.obj)
if err != nil {
return nil, err
}
@ -145,16 +145,28 @@ func implementations(ctx context.Context, s Snapshot, f FileHandle, pp protocol.
candObj = sel.Obj()
}
pos := s.FileSet().Position(candObj.Pos())
if candObj == queryMethod || seen[pos] {
if candObj == queryMethod {
continue
}
seen[pos] = true
pkg := pkgs[candObj.Pkg()] // may be nil (e.g. error)
// TODO(adonovan): the logic below assumes there is only one
// predeclared (pkg=nil) object of interest, the error type.
// That could change in a future version of Go.
var posn token.Position
if pkg != nil {
posn = pkg.FileSet().Position(candObj.Pos())
}
if seen[posn] {
continue
}
seen[posn] = true
impls = append(impls, qualifiedObject{
obj: candObj,
pkg: pkgs[candObj.Pkg()], // may be nil (e.g. error)
pkg: pkg,
})
}
}

View File

@ -144,7 +144,7 @@ func references(ctx context.Context, snapshot Snapshot, qos []qualifiedObject, i
}
// Inv: qos[0].pkg != nil, since Pos is valid.
// Inv: qos[*].pkg != nil, since all qos are logically the same declaration.
filename := snapshot.FileSet().Position(pos).Filename
filename := qos[0].pkg.FileSet().File(pos).Name()
pgf, err := qos[0].pkg.File(span.URIFromPath(filename))
if err != nil {
return nil, err
@ -208,7 +208,7 @@ func references(ctx context.Context, snapshot Snapshot, qos []qualifiedObject, i
continue
}
seen[key] = true
rng, err := posToMappedRange(snapshot.FileSet(), pkg, ident.Pos(), ident.End())
rng, err := posToMappedRange(pkg, ident.Pos(), ident.End())
if err != nil {
return nil, err
}

View File

@ -28,7 +28,6 @@ import (
type renamer struct {
ctx context.Context
fset *token.FileSet
refs []*ReferenceInfo
objsToUpdate map[types.Object]bool
hadConflicts bool
@ -136,7 +135,7 @@ func PrepareRename(ctx context.Context, snapshot Snapshot, f FileHandle, pp prot
}
func computePrepareRenameResp(snapshot Snapshot, pkg Package, node ast.Node, text string) (*PrepareItem, error) {
mr, err := posToMappedRange(snapshot.FileSet(), pkg, node.Pos(), node.End())
mr, err := posToMappedRange(pkg, node.Pos(), node.End())
if err != nil {
return nil, err
}
@ -484,7 +483,6 @@ func renameObj(ctx context.Context, s Snapshot, newName string, qos []qualifiedO
}
r := renamer{
ctx: ctx,
fset: s.FileSet(),
refs: refs,
objsToUpdate: make(map[types.Object]bool),
from: obj.Name(),
@ -604,7 +602,7 @@ func (r *renamer) update() (map[span.URI][]diff.Edit, error) {
// TODO(adonovan): why are we looping over lines?
// Just run the loop body once over the entire multiline comment.
lines := strings.Split(comment.Text, "\n")
tokFile := r.fset.File(comment.Pos())
tokFile := ref.pkg.FileSet().File(comment.Pos())
commentLine := tokFile.Line(comment.Pos())
uri := span.URIFromPath(tokFile.Name())
for i, line := range lines {
@ -632,7 +630,7 @@ func (r *renamer) update() (map[span.URI][]diff.Edit, error) {
// docComment returns the doc for an identifier.
func (r *renamer) docComment(pkg Package, id *ast.Ident) *ast.CommentGroup {
_, tokFile, nodes, _ := pathEnclosingInterval(r.fset, pkg, id.Pos(), id.End())
_, tokFile, nodes, _ := pathEnclosingInterval(pkg, id.Pos(), id.End())
for _, node := range nodes {
switch decl := node.(type) {
case *ast.FuncDecl:
@ -685,7 +683,7 @@ func (r *renamer) docComment(pkg Package, id *ast.Ident) *ast.CommentGroup {
func (r *renamer) updatePkgName(pkgName *types.PkgName) (*diff.Edit, error) {
// Modify ImportSpec syntax to add or remove the Name as needed.
pkg := r.packages[pkgName.Pkg()]
_, tokFile, path, _ := pathEnclosingInterval(r.fset, pkg, pkgName.Pos(), pkgName.Pos())
_, tokFile, path, _ := pathEnclosingInterval(pkg, pkgName.Pos(), pkgName.Pos())
if len(path) < 2 {
return nil, fmt.Errorf("no path enclosing interval for %s", pkgName.Name())
}

View File

@ -371,7 +371,7 @@ func (r *renamer) checkStructField(from *types.Var) {
if !ok {
return
}
pkg, _, path, _ := pathEnclosingInterval(r.fset, fromPkg, from.Pos(), from.Pos())
pkg, _, path, _ := pathEnclosingInterval(fromPkg, from.Pos(), from.Pos())
if pkg == nil || path == nil {
return
}
@ -826,7 +826,7 @@ func someUse(info *types.Info, obj types.Object) *ast.Ident {
// exact is defined as for astutil.PathEnclosingInterval.
//
// The zero value is returned if not found.
func pathEnclosingInterval(fset *token.FileSet, pkg Package, start, end token.Pos) (resPkg Package, tokFile *token.File, path []ast.Node, exact bool) {
func pathEnclosingInterval(pkg Package, start, end token.Pos) (resPkg Package, tokFile *token.File, path []ast.Node, exact bool) {
pkgs := []Package{pkg}
for _, f := range pkg.GetSyntax() {
for _, imp := range f.Imports {
@ -852,7 +852,7 @@ func pathEnclosingInterval(fset *token.FileSet, pkg Package, start, end token.Po
// (Use parser.AllErrors to prevent that.)
continue
}
tokFile := fset.File(f.Pos())
tokFile := p.FileSet().File(f.Pos())
if !tokenFileContainsPos(tokFile, start) {
continue
}

View File

@ -94,7 +94,7 @@ FindCall:
comment *ast.CommentGroup
)
if obj != nil {
declPkg, err := FindPackageFromPos(snapshot.FileSet(), pkg, obj.Pos())
declPkg, err := FindPackageFromPos(pkg, obj.Pos())
if err != nil {
return nil, 0, err
}

View File

@ -24,22 +24,22 @@ import (
"golang.org/x/tools/internal/typeparams"
)
func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, rng protocol.Range) (*analysis.SuggestedFix, error) {
func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh VersionedFileHandle, rng protocol.Range) (*token.FileSet, *analysis.SuggestedFix, error) {
pkg, pgf, err := GetParsedFile(ctx, snapshot, fh, NarrowestPackage)
if err != nil {
return nil, fmt.Errorf("GetParsedFile: %w", err)
return nil, nil, fmt.Errorf("GetParsedFile: %w", err)
}
nodes, pos, err := getStubNodes(pgf, rng)
if err != nil {
return nil, fmt.Errorf("getNodes: %w", err)
return nil, nil, fmt.Errorf("getNodes: %w", err)
}
si := stubmethods.GetStubInfo(pkg.GetTypesInfo(), nodes, pos)
if si == nil {
return nil, fmt.Errorf("nil interface request")
return nil, nil, fmt.Errorf("nil interface request")
}
parsedConcreteFile, concreteFH, err := getStubFile(ctx, si.Concrete.Obj(), snapshot)
if err != nil {
return nil, fmt.Errorf("getFile(concrete): %w", err)
return nil, nil, fmt.Errorf("getFile(concrete): %w", err)
}
var (
methodsSrc []byte
@ -51,16 +51,16 @@ func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh VersionedFi
methodsSrc, stubImports, err = stubMethods(ctx, parsedConcreteFile.File, si, snapshot)
}
if err != nil {
return nil, fmt.Errorf("stubMethods: %w", err)
return nil, nil, fmt.Errorf("stubMethods: %w", err)
}
nodes, _ = astutil.PathEnclosingInterval(parsedConcreteFile.File, si.Concrete.Obj().Pos(), si.Concrete.Obj().Pos())
concreteSrc, err := concreteFH.Read()
if err != nil {
return nil, fmt.Errorf("error reading concrete file source: %w", err)
return nil, nil, fmt.Errorf("error reading concrete file source: %w", err)
}
insertPos, err := safetoken.Offset(parsedConcreteFile.Tok, nodes[1].End())
if err != nil || insertPos >= len(concreteSrc) {
return nil, fmt.Errorf("insertion position is past the end of the file")
return nil, nil, fmt.Errorf("insertion position is past the end of the file")
}
var buf bytes.Buffer
buf.Write(concreteSrc[:insertPos])
@ -70,7 +70,7 @@ func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh VersionedFi
fset := token.NewFileSet()
newF, err := parser.ParseFile(fset, parsedConcreteFile.File.Name.Name, buf.Bytes(), parser.ParseComments)
if err != nil {
return nil, fmt.Errorf("could not reparse file: %w", err)
return nil, nil, fmt.Errorf("could not reparse file: %w", err)
}
for _, imp := range stubImports {
astutil.AddNamedImport(fset, newF, imp.Name, imp.Path)
@ -78,7 +78,7 @@ func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh VersionedFi
var source bytes.Buffer
err = format.Node(&source, fset, newF)
if err != nil {
return nil, fmt.Errorf("format.Node: %w", err)
return nil, nil, fmt.Errorf("format.Node: %w", err)
}
diffs := snapshot.View().Options().ComputeEdits(string(parsedConcreteFile.Src), source.String())
tf := parsedConcreteFile.Mapper.TokFile
@ -90,9 +90,9 @@ func stubSuggestedFixFunc(ctx context.Context, snapshot Snapshot, fh VersionedFi
NewText: []byte(edit.New),
})
}
return &analysis.SuggestedFix{
TextEdits: edits,
}, nil
return snapshot.FileSet(), // from getStubFile
&analysis.SuggestedFix{TextEdits: edits},
nil
}
// stubMethods returns the Go code of all methods
@ -304,6 +304,7 @@ func missingMethods(ctx context.Context, snapshot Snapshot, concMS *types.Method
return missing, nil
}
// Token position information for obj.Pos and the ParsedGoFile result is in Snapshot.FileSet.
func getStubFile(ctx context.Context, obj types.Object, snapshot Snapshot) (*ParsedGoFile, VersionedFileHandle, error) {
objPos := snapshot.FileSet().Position(obj.Pos())
objFile := span.URIFromPath(objPos.Filename)

View File

@ -86,6 +86,7 @@ func (s *signature) Params() []string {
// NewBuiltinSignature returns signature for the builtin object with a given
// name, if a builtin object with the name exists.
func NewBuiltinSignature(ctx context.Context, s Snapshot, name string) (*signature, error) {
fset := s.FileSet()
builtin, err := s.BuiltinFile(ctx)
if err != nil {
return nil, err
@ -109,8 +110,8 @@ func NewBuiltinSignature(ctx context.Context, s Snapshot, name string) (*signatu
variadic = true
}
}
params, _ := formatFieldList(ctx, s, decl.Type.Params, variadic)
results, needResultParens := formatFieldList(ctx, s, decl.Type.Results, false)
params, _ := formatFieldList(ctx, fset, decl.Type.Params, variadic)
results, needResultParens := formatFieldList(ctx, fset, decl.Type.Results, false)
d := decl.Doc.Text()
switch s.View().Options().HoverKind {
case SynopsisDocumentation:
@ -134,7 +135,7 @@ var replacer = strings.NewReplacer(
`IntegerType`, `int`,
)
func formatFieldList(ctx context.Context, snapshot Snapshot, list *ast.FieldList, variadic bool) ([]string, bool) {
func formatFieldList(ctx context.Context, fset *token.FileSet, list *ast.FieldList, variadic bool) ([]string, bool) {
if list == nil {
return nil, false
}
@ -147,7 +148,7 @@ func formatFieldList(ctx context.Context, snapshot Snapshot, list *ast.FieldList
p := list.List[i]
cfg := printer.Config{Mode: printer.UseSpaces | printer.TabIndent, Tabwidth: 4}
b := &bytes.Buffer{}
if err := cfg.Fprint(b, snapshot.FileSet(), p.Type); err != nil {
if err := cfg.Fprint(b, fset, p.Type); err != nil {
event.Error(ctx, "unable to print type", nil, tag.Type.Of(p.Type))
continue
}
@ -205,7 +206,7 @@ func NewSignature(ctx context.Context, s Snapshot, pkg Package, sig *types.Signa
params := make([]string, 0, sig.Params().Len())
for i := 0; i < sig.Params().Len(); i++ {
el := sig.Params().At(i)
typ := FormatVarType(s.FileSet(), pkg, el, qf)
typ := FormatVarType(pkg, el, qf)
p := typ
if el.Name() != "" {
p = el.Name() + " " + typ
@ -220,7 +221,7 @@ func NewSignature(ctx context.Context, s Snapshot, pkg Package, sig *types.Signa
needResultParens = true
}
el := sig.Results().At(i)
typ := FormatVarType(s.FileSet(), pkg, el, qf)
typ := FormatVarType(pkg, el, qf)
if el.Name() == "" {
results = append(results, typ)
} else {
@ -253,8 +254,8 @@ func NewSignature(ctx context.Context, s Snapshot, pkg Package, sig *types.Signa
// FormatVarType formats a *types.Var, accounting for type aliases.
// To do this, it looks in the AST of the file in which the object is declared.
// On any errors, it always falls back to types.TypeString.
func FormatVarType(fset *token.FileSet, srcpkg Package, obj *types.Var, qf types.Qualifier) string {
pkg, err := FindPackageFromPos(fset, srcpkg, obj.Pos())
func FormatVarType(srcpkg Package, obj *types.Var, qf types.Qualifier) string {
pkg, err := FindPackageFromPos(srcpkg, obj.Pos())
if err != nil {
return types.TypeString(obj.Type(), qf)
}
@ -283,7 +284,7 @@ func FormatVarType(fset *token.FileSet, srcpkg Package, obj *types.Var, qf types
// If the request came from a different package than the one in which the
// types are defined, we may need to modify the qualifiers.
qualified = qualifyExpr(qualified, srcpkg, pkg, clonedInfo, qf)
fmted := FormatNode(fset, qualified)
fmted := FormatNode(srcpkg.FileSet(), qualified)
return fmted
}

View File

@ -125,7 +125,7 @@ func IsGenerated(ctx context.Context, snapshot Snapshot, uri span.URI) bool {
return false
}
func objToMappedRange(fset *token.FileSet, pkg Package, obj types.Object) (MappedRange, error) {
func objToMappedRange(pkg Package, obj types.Object) (MappedRange, error) {
nameLen := len(obj.Name())
if pkgName, ok := obj.(*types.PkgName); ok {
// An imported Go package has a package-local, unqualified name.
@ -142,12 +142,12 @@ func objToMappedRange(fset *token.FileSet, pkg Package, obj types.Object) (Mappe
nameLen = len(pkgName.Imported().Path()) + len(`""`)
}
}
return posToMappedRange(fset, pkg, obj.Pos(), obj.Pos()+token.Pos(nameLen))
return posToMappedRange(pkg, obj.Pos(), obj.Pos()+token.Pos(nameLen))
}
// posToMappedRange returns the MappedRange for the given [start, end) span,
// which must be among the transitive dependencies of pkg.
func posToMappedRange(fset *token.FileSet, pkg Package, pos, end token.Pos) (MappedRange, error) {
func posToMappedRange(pkg Package, pos, end token.Pos) (MappedRange, error) {
if !pos.IsValid() {
return MappedRange{}, fmt.Errorf("invalid start position")
}
@ -155,6 +155,7 @@ func posToMappedRange(fset *token.FileSet, pkg Package, pos, end token.Pos) (Map
return MappedRange{}, fmt.Errorf("invalid end position")
}
fset := pkg.FileSet()
tokFile := fset.File(pos)
// Subtle: it is not safe to simplify this to tokFile.Name
// because, due to //line directives, a Position within a
@ -183,11 +184,11 @@ func posToMappedRange(fset *token.FileSet, pkg Package, pos, end token.Pos) (Map
// TODO(rfindley): is this the best factoring of this API? This function is
// really a trivial wrapper around findFileInDeps, which may be a more useful
// function to expose.
func FindPackageFromPos(fset *token.FileSet, pkg Package, pos token.Pos) (Package, error) {
func FindPackageFromPos(pkg Package, pos token.Pos) (Package, error) {
if !pos.IsValid() {
return nil, fmt.Errorf("invalid position")
}
fileName := fset.File(pos).Name()
fileName := pkg.FileSet().File(pos).Name()
uri := span.URIFromPath(fileName)
_, pkg, err := findFileInDeps(pkg, uri)
return pkg, err

View File

@ -40,6 +40,11 @@ type Snapshot interface {
BackgroundContext() context.Context
// Fileset returns the Fileset used to parse all the Go files in this snapshot.
//
// If the files are known to belong to a specific Package, use
// Package.FileSet instead. (We plan to eliminate the
// Snapshot's cache of parsed files, and thus the need for a
// snapshot-wide FileSet.)
FileSet() *token.FileSet
// ValidBuildConfiguration returns true if there is some error in the
@ -610,6 +615,7 @@ type Package interface {
PkgPath() PackagePath
CompiledGoFiles() []*ParsedGoFile
File(uri span.URI) (*ParsedGoFile, error)
FileSet() *token.FileSet
GetSyntax() []*ast.File
GetTypes() *types.Package
GetTypesInfo() *types.Info