golang.org/x/tools/gopls@v0.15.3/internal/cache/pkg.go (about)

     1  // Copyright 2019 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package cache
     6  
     7  import (
     8  	"fmt"
     9  	"go/ast"
    10  	"go/scanner"
    11  	"go/token"
    12  	"go/types"
    13  	"sync"
    14  
    15  	"golang.org/x/tools/gopls/internal/cache/metadata"
    16  	"golang.org/x/tools/gopls/internal/cache/methodsets"
    17  	"golang.org/x/tools/gopls/internal/cache/parsego"
    18  	"golang.org/x/tools/gopls/internal/cache/xrefs"
    19  	"golang.org/x/tools/gopls/internal/protocol"
    20  )
    21  
    22  // Convenient aliases for very heavily used types.
    23  type (
    24  	PackageID    = metadata.PackageID
    25  	PackagePath  = metadata.PackagePath
    26  	PackageName  = metadata.PackageName
    27  	ImportPath   = metadata.ImportPath
    28  	ParsedGoFile = parsego.File
    29  )
    30  
    31  const (
    32  	ParseHeader = parsego.ParseHeader
    33  	ParseFull   = parsego.ParseFull
    34  )
    35  
    36  // A Package is the union of package metadata and type checking results.
    37  //
    38  // TODO(rfindley): for now, we do not persist the post-processing of
    39  // loadDiagnostics, because the value of the snapshot.packages map is just the
    40  // package handle. Fix this.
    41  type Package struct {
    42  	metadata        *metadata.Package
    43  	loadDiagnostics []*Diagnostic
    44  	pkg             *syntaxPackage
    45  }
    46  
    47  // syntaxPackage contains parse trees and type information for a package.
    48  type syntaxPackage struct {
    49  	// -- identifiers --
    50  	id PackageID
    51  
    52  	// -- outputs --
    53  	fset            *token.FileSet // for now, same as the snapshot's FileSet
    54  	goFiles         []*ParsedGoFile
    55  	compiledGoFiles []*ParsedGoFile
    56  	diagnostics     []*Diagnostic
    57  	parseErrors     []scanner.ErrorList
    58  	typeErrors      []types.Error
    59  	types           *types.Package
    60  	typesInfo       *types.Info
    61  	importMap       map[PackagePath]*types.Package
    62  
    63  	xrefsOnce sync.Once
    64  	_xrefs    []byte // only used by the xrefs method
    65  
    66  	methodsetsOnce sync.Once
    67  	_methodsets    *methodsets.Index // only used by the methodsets method
    68  }
    69  
    70  func (p *syntaxPackage) xrefs() []byte {
    71  	p.xrefsOnce.Do(func() {
    72  		p._xrefs = xrefs.Index(p.compiledGoFiles, p.types, p.typesInfo)
    73  	})
    74  	return p._xrefs
    75  }
    76  
    77  func (p *syntaxPackage) methodsets() *methodsets.Index {
    78  	p.methodsetsOnce.Do(func() {
    79  		p._methodsets = methodsets.NewIndex(p.fset, p.types)
    80  	})
    81  	return p._methodsets
    82  }
    83  
    84  func (p *Package) String() string { return string(p.metadata.ID) }
    85  
    86  func (p *Package) Metadata() *metadata.Package { return p.metadata }
    87  
    88  // A loadScope defines a package loading scope for use with go/packages.
    89  //
    90  // TODO(rfindley): move this to load.go.
    91  type loadScope interface {
    92  	aScope()
    93  }
    94  
    95  type (
    96  	fileLoadScope    protocol.DocumentURI // load packages containing a file (including command-line-arguments)
    97  	packageLoadScope string               // load a specific package (the value is its PackageID)
    98  	moduleLoadScope  struct {
    99  		dir        string // dir containing the go.mod file
   100  		modulePath string // parsed module path
   101  	}
   102  	viewLoadScope struct{} // load the workspace
   103  )
   104  
   105  // Implement the loadScope interface.
   106  func (fileLoadScope) aScope()    {}
   107  func (packageLoadScope) aScope() {}
   108  func (moduleLoadScope) aScope()  {}
   109  func (viewLoadScope) aScope()    {}
   110  
   111  func (p *Package) CompiledGoFiles() []*ParsedGoFile {
   112  	return p.pkg.compiledGoFiles
   113  }
   114  
   115  func (p *Package) File(uri protocol.DocumentURI) (*ParsedGoFile, error) {
   116  	return p.pkg.File(uri)
   117  }
   118  
   119  func (pkg *syntaxPackage) File(uri protocol.DocumentURI) (*ParsedGoFile, error) {
   120  	for _, cgf := range pkg.compiledGoFiles {
   121  		if cgf.URI == uri {
   122  			return cgf, nil
   123  		}
   124  	}
   125  	for _, gf := range pkg.goFiles {
   126  		if gf.URI == uri {
   127  			return gf, nil
   128  		}
   129  	}
   130  	return nil, fmt.Errorf("no parsed file for %s in %v", uri, pkg.id)
   131  }
   132  
   133  func (p *Package) GetSyntax() []*ast.File {
   134  	var syntax []*ast.File
   135  	for _, pgf := range p.pkg.compiledGoFiles {
   136  		syntax = append(syntax, pgf.File)
   137  	}
   138  	return syntax
   139  }
   140  
   141  func (p *Package) FileSet() *token.FileSet {
   142  	return p.pkg.fset
   143  }
   144  
   145  func (p *Package) GetTypes() *types.Package {
   146  	return p.pkg.types
   147  }
   148  
   149  func (p *Package) GetTypesInfo() *types.Info {
   150  	return p.pkg.typesInfo
   151  }
   152  
   153  // DependencyTypes returns the type checker's symbol for the specified
   154  // package. It returns nil if path is not among the transitive
   155  // dependencies of p, or if no symbols from that package were
   156  // referenced during the type-checking of p.
   157  func (p *Package) DependencyTypes(path PackagePath) *types.Package {
   158  	return p.pkg.importMap[path]
   159  }
   160  
   161  func (p *Package) GetParseErrors() []scanner.ErrorList {
   162  	return p.pkg.parseErrors
   163  }
   164  
   165  func (p *Package) GetTypeErrors() []types.Error {
   166  	return p.pkg.typeErrors
   167  }