kythe.io@v0.0.68-0.20240422202219-7225dbc01741/kythe/go/indexer/indexer.go (about)

     1  /*
     2   * Copyright 2015 The Kythe Authors. All rights reserved.
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *   http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   */
    16  
    17  // Package indexer implements a Kythe indexer for the Go language.
    18  //
    19  // Usage example: Indexing a Kythe CompilationUnit message.
    20  //
    21  //	// Obtain a compilation from some source, e.g., an kzip.
    22  //	var unit *apb.CompilationUnit = ...
    23  //
    24  //	// Parse the sources and resolve types.
    25  //	pi, err := indexer.Resolve(unit, pack, &indexer.ResolveOptions{
    26  //	  Info: indexer.AllTypeInfo(),
    27  //	})
    28  //	if err != nil {
    29  //	  log.Fatal("Resolving failed: %v", err)
    30  //	}
    31  //	// Type information from http://godoc.org/go/types is now available
    32  //	// from pi.Info, which is a *types.Info record.
    33  package indexer // import "kythe.io/kythe/go/indexer"
    34  
    35  import (
    36  	"bytes"
    37  	"encoding/base64"
    38  	"errors"
    39  	"fmt"
    40  	"go/ast"
    41  	"go/build"
    42  	"go/parser"
    43  	"go/token"
    44  	"go/types"
    45  	"io"
    46  	"io/ioutil"
    47  	"path/filepath"
    48  	"strconv"
    49  	"strings"
    50  
    51  	"kythe.io/kythe/go/extractors/govname"
    52  	"kythe.io/kythe/go/util/log"
    53  	"kythe.io/kythe/go/util/metadata"
    54  	"kythe.io/kythe/go/util/ptypes"
    55  	"kythe.io/kythe/go/util/schema/edges"
    56  
    57  	"bitbucket.org/creachadair/stringset"
    58  	"github.com/golang/protobuf/proto"
    59  	"golang.org/x/tools/go/gcexportdata"
    60  
    61  	apb "kythe.io/kythe/proto/analysis_go_proto"
    62  	gopb "kythe.io/kythe/proto/go_go_proto"
    63  	mpb "kythe.io/kythe/proto/metadata_go_proto"
    64  	spb "kythe.io/kythe/proto/storage_go_proto"
    65  )
    66  
    67  // ErrNoSourceFiles is returned from Resolve if it is given a package without any sources files.
    68  var ErrNoSourceFiles = errors.New("no source files in package")
    69  
    70  // A Fetcher retrieves the contents of a file given its path and/or hex-encoded
    71  // SHA256 digest, at least one of which must be set.
    72  type Fetcher interface {
    73  	Fetch(path, digest string) ([]byte, error)
    74  }
    75  
    76  // PackageInfo records information about the Go packages defined by a
    77  // compilation unit and its dependencies.
    78  type PackageInfo struct {
    79  	Name         string                        // The (short) name of the package
    80  	ImportPath   string                        // The nominal import path of the package
    81  	Package      *types.Package                // The package for this compilation
    82  	Dependencies map[string]*types.Package     // Packages imported from dependencies
    83  	VName        *spb.VName                    // The base vname for this package
    84  	PackageVName map[*types.Package]*spb.VName // Resolved package to vname
    85  	FileSet      *token.FileSet                // Location info for the source files
    86  	Files        []*ast.File                   // The parsed ASTs of the source files
    87  	SourceText   map[*ast.File]string          // The text of the source files
    88  	Rules        map[*ast.File]metadata.Rules  // Mapping metadata for each source file
    89  	Vendored     map[string]string             // Mapping from package to its vendor path
    90  
    91  	Info   *types.Info // If non-nil, contains type-checker results
    92  	Errors []error     // All errors reported by the type checker
    93  
    94  	// A lazily-initialized mapping from an object on the RHS of a selection
    95  	// (lhs.RHS) to the nearest enclosing named struct or interface type; or in
    96  	// the body of a function or method to the nearest enclosing named method.
    97  	owner map[types.Object]types.Object
    98  
    99  	// A lazily-initialized mapping from from AST nodes to their corresponding
   100  	// VNames. Only nodes that do not resolve directly to a type object are
   101  	// included in this map, e.g., function literals.
   102  	function map[ast.Node]*funcInfo
   103  
   104  	// A lazily-initialized set of standard library package import paths for
   105  	// which a node has been emitted.
   106  	standardLib stringset.Set
   107  
   108  	// A dummy function representing the undeclared package initilization
   109  	// functions, one per file in the package.
   110  	packageInit map[*ast.File]*funcInfo
   111  
   112  	// A cache of source file vnames.
   113  	fileVName map[*ast.File]*spb.VName
   114  
   115  	// A cache of type vnames.
   116  	typeVName map[types.Type]*spb.VName
   117  
   118  	// Cache storing whether a type's facts have been emitted (keyed by VName signature)
   119  	typeEmitted stringset.Set
   120  
   121  	// A cache of file location mappings. This lets us get back from the
   122  	// parser's location to the vname for the enclosing file, which is in turn
   123  	// affected by the build configuration.
   124  	fileLoc map[*token.File]*ast.File
   125  
   126  	// A cache of already-computed signatures.
   127  	sigs map[types.Object]string
   128  
   129  	// The number of package-level init declarations seen.
   130  	numInits int
   131  
   132  	// The Go-specific details from the compilation record.
   133  	details *gopb.GoDetails
   134  }
   135  
   136  type funcInfo struct {
   137  	vname    *spb.VName
   138  	numAnons int // number of anonymous params/functions defined inside this one
   139  }
   140  
   141  // packageImporter implements the types.Importer interface by fetching files
   142  // from the required inputs of a compilation unit.
   143  type packageImporter struct {
   144  	deps    map[string]*types.Package // packages already loaded
   145  	fileSet *token.FileSet            // source location information
   146  	fileMap map[string]*apb.FileInfo  // :: import path → required input location
   147  	fetcher Fetcher                   // access to required input contents
   148  
   149  	pkgPath  string
   150  	vendored map[string]string // map of package paths to their vendor paths
   151  }
   152  
   153  // Import satisfies the types.Importer interface using the captured data from
   154  // the compilation unit.
   155  func (pi *packageImporter) Import(importPath string) (*types.Package, error) {
   156  	if pkg := pi.deps[importPath]; pkg != nil && pkg.Complete() {
   157  		return pkg, nil
   158  	} else if importPath == "unsafe" {
   159  		// The "unsafe" package is special, and isn't usually added by the
   160  		// resolver into the dependency map.
   161  		pi.deps[importPath] = types.Unsafe
   162  		return types.Unsafe, nil
   163  	}
   164  
   165  	// Fetch the required input holding the package for this import path, and
   166  	// load its export data for use by the type resolver.
   167  	fi := pi.fileMap[importPath]
   168  
   169  	// Check all possible vendor/ paths for missing package file
   170  	if fi == nil {
   171  		// Starting at the current package's path, look upwards for a vendor/ root
   172  		// with the imported package.
   173  		vendorRoot := pi.pkgPath
   174  		for {
   175  			vPath := filepath.Join(vendorRoot, "vendor", importPath)
   176  			fi = pi.fileMap[vPath]
   177  			if fi != nil {
   178  				pi.vendored[importPath] = vPath
   179  				importPath = vPath
   180  				break
   181  			} else if vendorRoot == "" {
   182  				return nil, fmt.Errorf("package %q not found", importPath)
   183  			}
   184  			vendorRoot, _ = filepath.Split(vendorRoot)
   185  			vendorRoot = strings.TrimRight(vendorRoot, "/")
   186  		}
   187  	}
   188  
   189  	data, err := pi.fetcher.Fetch(fi.Path, fi.Digest)
   190  	if err != nil {
   191  		return nil, fmt.Errorf("fetching %q (%s): %v", fi.Path, fi.Digest, err)
   192  	}
   193  	r, err := gcexportdata.NewReader(bytes.NewReader(data))
   194  	if err != nil {
   195  		return nil, fmt.Errorf("reading export data in %q (%s): %v", fi.Path, fi.Digest, err)
   196  	}
   197  	return gcexportdata.Read(r, pi.fileSet, pi.deps, importPath)
   198  }
   199  
   200  // ResolveOptions control the behaviour of the Resolve function. A nil options
   201  // pointer provides default values.
   202  type ResolveOptions struct {
   203  	// Passes a value whose non-nil map fields will be filled in by the type
   204  	// checker during resolution. The value will also be copied to the Info
   205  	// field of the PackageInfo returned by Resolve.
   206  	Info *types.Info
   207  
   208  	// If set, this function is called for each required input to check whether
   209  	// it contains metadata rules.
   210  	//
   211  	// Valid return are:
   212  	//    rs, nil    -- a valid ruleset
   213  	//    nil, nil   -- no ruleset found
   214  	//    _, err     -- an error attempting to load a ruleset
   215  	//
   216  	CheckRules func(ri *apb.CompilationUnit_FileInput, f Fetcher) (*Ruleset, error)
   217  }
   218  
   219  func (r *ResolveOptions) info() *types.Info {
   220  	if r != nil {
   221  		return r.Info
   222  	}
   223  	return nil
   224  }
   225  
   226  func (r *ResolveOptions) checkRules(ri *apb.CompilationUnit_FileInput, f Fetcher) (*Ruleset, error) {
   227  	if r == nil || r.CheckRules == nil {
   228  		return nil, nil
   229  	}
   230  	return r.CheckRules(ri, f)
   231  }
   232  
   233  // A Ruleset represents a collection of mapping rules applicable to a source
   234  // file in a compilation to be indexed.
   235  type Ruleset struct {
   236  	Path  string         // the file path this rule set applies to
   237  	Rules metadata.Rules // the rules that apply to the path
   238  }
   239  
   240  // Resolve resolves the package information for unit and its dependencies.  On
   241  // success the package corresponding to unit is located via ImportPath in the
   242  // Packages map of the returned value.
   243  func Resolve(unit *apb.CompilationUnit, f Fetcher, opts *ResolveOptions) (*PackageInfo, error) {
   244  	sourceFiles := stringset.New(unit.SourceFile...)
   245  
   246  	imap := make(map[string]*spb.VName)     // import path → vname
   247  	srcs := make(map[*ast.File]string)      // file → text
   248  	fmap := make(map[string]*apb.FileInfo)  // import path → file info
   249  	smap := make(map[string]*ast.File)      // file path → file (sources)
   250  	filev := make(map[*ast.File]*spb.VName) // file → vname
   251  	floc := make(map[*token.File]*ast.File) // file → ast
   252  	fset := token.NewFileSet()              // location info for the parser
   253  	details := goDetails(unit)
   254  	var files []*ast.File // parsed sources
   255  	var rules []*Ruleset  // parsed linkage rules
   256  
   257  	// Classify the required inputs as either sources, which are to be parsed,
   258  	// or dependencies, which are to be "imported" via the type-checker's
   259  	// import mechanism.  If successful, this populates fset and files with the
   260  	// lexical and syntactic content of the package's own sources.
   261  	//
   262  	// The build context is used to check build tags.
   263  	bc := &build.Context{
   264  		GOOS:        details.GetGoos(),
   265  		GOARCH:      details.GetGoarch(),
   266  		BuildTags:   details.GetBuildTags(),
   267  		ReleaseTags: build.Default.ReleaseTags,
   268  		ToolTags:    build.Default.ToolTags,
   269  	}
   270  	for _, ri := range unit.RequiredInput {
   271  		if ri.Info == nil {
   272  			return nil, errors.New("required input file info missing")
   273  		}
   274  
   275  		// Source inputs need to be parsed, so we can give their ASTs to the
   276  		// type checker later on.
   277  		fpath := ri.Info.Path
   278  		if sourceFiles.Contains(fpath) {
   279  			data, err := f.Fetch(fpath, ri.Info.Digest)
   280  			if err != nil {
   281  				return nil, fmt.Errorf("fetching %q (%s): %v", fpath, ri.Info.Digest, err)
   282  			}
   283  			if !matchesBuildTags(fpath, data, bc) {
   284  				log.Infof("Skipped source file %q because build tags do not match", fpath)
   285  				continue
   286  			}
   287  			vpath := ri.VName.GetPath()
   288  			if vpath == "" {
   289  				vpath = fpath
   290  			}
   291  			parsed, err := parser.ParseFile(fset, vpath, data, parser.AllErrors|parser.ParseComments)
   292  			if err != nil {
   293  				return nil, fmt.Errorf("parsing %q: %v", fpath, err)
   294  			}
   295  
   296  			// Cache file VNames based on the required input.
   297  			files = append(files, parsed)
   298  			vname := proto.Clone(ri.VName).(*spb.VName)
   299  			if vname == nil {
   300  				vname = proto.Clone(unit.VName).(*spb.VName)
   301  				vname.Signature = ""
   302  				vname.Language = ""
   303  			}
   304  			vname.Path = vpath
   305  			filev[parsed] = vname
   306  			srcs[parsed] = string(data)
   307  			smap[fpath] = parsed
   308  
   309  			// If the file has inlined encoded metadata, add to rules.
   310  			var lastComment string
   311  			if len(parsed.Comments) > 0 {
   312  				lastComment = parsed.Comments[len(parsed.Comments)-1].Text()
   313  			}
   314  			const delimiter = "gokythe-inline-metadata:"
   315  
   316  			if strings.HasPrefix(lastComment, delimiter) {
   317  				encodedMetadata := strings.TrimPrefix(lastComment, delimiter)
   318  				newRule, err := loadInlineMetadata(ri, encodedMetadata)
   319  				if err != nil {
   320  					log.Errorf("loading metadata in %q: %v", ri.Info.GetPath(), err)
   321  				} else {
   322  					rules = append(rules, newRule)
   323  				}
   324  			}
   325  			continue
   326  		}
   327  
   328  		// Check for mapping metadata.
   329  		if rs, err := opts.checkRules(ri, f); err != nil {
   330  			log.Errorf("checking rules in %q: %v", fpath, err)
   331  		} else if rs != nil {
   332  			log.Infof("Found %d metadata rules for path %q", len(rs.Rules), rs.Path)
   333  			rules = append(rules, rs)
   334  			continue
   335  		}
   336  
   337  		// Files may be source or compiled archives with type information for
   338  		// other packages, or may be other ancillary files like C headers to
   339  		// support cgo.  Use the vname to determine which import path for each
   340  		// and save that mapping for use by the importer.
   341  		if ri.VName == nil {
   342  			return nil, fmt.Errorf("missing vname for %q", fpath)
   343  		}
   344  
   345  		var ipath string
   346  		if info := goPackageInfo(ri.Details); info != nil {
   347  			ipath = info.ImportPath
   348  		} else {
   349  			ipath = govname.ImportPath(ri.VName, details.GetGoroot())
   350  		}
   351  		imap[ipath] = ri.VName
   352  		fmap[ipath] = ri.Info
   353  	}
   354  	if len(files) == 0 {
   355  		return nil, ErrNoSourceFiles
   356  	}
   357  
   358  	// Populate the location mapping. This relies on the fact that Iterate
   359  	// reports its files in the order they were added to the set, which in turn
   360  	// is their order in the files list.
   361  	i := 0
   362  	fset.Iterate(func(f *token.File) bool {
   363  		floc[f] = files[i]
   364  		i++
   365  		return true
   366  	})
   367  
   368  	pi := &PackageInfo{
   369  		Name:         files[0].Name.Name,
   370  		FileSet:      fset,
   371  		Files:        files,
   372  		Info:         opts.info(),
   373  		SourceText:   srcs,
   374  		PackageVName: make(map[*types.Package]*spb.VName),
   375  		Dependencies: make(map[string]*types.Package), // :: import path → package
   376  		Vendored:     make(map[string]string),
   377  
   378  		function:    make(map[ast.Node]*funcInfo),
   379  		sigs:        make(map[types.Object]string),
   380  		packageInit: make(map[*ast.File]*funcInfo),
   381  		fileVName:   filev,
   382  		typeVName:   make(map[types.Type]*spb.VName),
   383  		typeEmitted: stringset.New(),
   384  		fileLoc:     floc,
   385  		details:     details,
   386  	}
   387  	if info := goPackageInfo(unit.Details); info != nil {
   388  		pi.ImportPath = info.ImportPath
   389  	} else {
   390  		pi.ImportPath = govname.ImportPath(unit.VName, details.GetGoroot())
   391  	}
   392  
   393  	// If mapping rules were found, populate the corresponding field.
   394  	if len(rules) != 0 {
   395  		pi.Rules = make(map[*ast.File]metadata.Rules)
   396  		for _, rs := range rules {
   397  			f, ok := smap[rs.Path]
   398  			if ok {
   399  				pi.Rules[f] = rs.Rules
   400  			}
   401  		}
   402  	}
   403  
   404  	// Run the type-checker and collect any errors it generates.  Errors in the
   405  	// type checker are not returned directly; the caller can read them from
   406  	// the Errors field.
   407  	c := &types.Config{
   408  		FakeImportC:              true, // so we can handle cgo
   409  		DisableUnusedImportCheck: true, // this is not fatal to type-checking
   410  		Importer: &packageImporter{
   411  			deps:    pi.Dependencies,
   412  			fileSet: pi.FileSet,
   413  			fileMap: fmap,
   414  			fetcher: f,
   415  
   416  			pkgPath:  pi.ImportPath,
   417  			vendored: pi.Vendored,
   418  		},
   419  		Error: func(err error) { pi.Errors = append(pi.Errors, err) },
   420  	}
   421  	pi.Package, _ = c.Check(pi.Name, pi.FileSet, pi.Files, pi.Info)
   422  
   423  	// Fill in the mapping from packages to vnames.
   424  	for ip, vname := range imap {
   425  		if pkg := pi.Dependencies[ip]; pkg != nil {
   426  			pi.PackageVName[pkg] = proto.Clone(vname).(*spb.VName)
   427  			pi.PackageVName[pkg].Signature = "package"
   428  			pi.PackageVName[pkg].Language = govname.Language
   429  		}
   430  	}
   431  	if _, ok := pi.Dependencies["unsafe"]; ok {
   432  		pi.PackageVName[types.Unsafe] = govname.ForStandardLibrary("unsafe")
   433  	}
   434  
   435  	// Set this package's own vname.
   436  	pi.VName = proto.Clone(unit.VName).(*spb.VName)
   437  	pi.VName.Language = govname.Language
   438  	pi.VName.Signature = "package"
   439  	pi.PackageVName[pi.Package] = pi.VName
   440  
   441  	return pi, nil
   442  }
   443  
   444  // String renders a human-readable synopsis of the package information.
   445  func (pi *PackageInfo) String() string {
   446  	if pi == nil {
   447  		return "#<package-info nil>"
   448  	}
   449  	return fmt.Sprintf("#<package-info %q ip=%q pkg=%p #deps=%d #src=%d #errs=%d>",
   450  		pi.Name, pi.ImportPath, pi.Package, len(pi.Dependencies), len(pi.Files), len(pi.Errors))
   451  }
   452  
   453  // Signature returns a signature for obj, suitable for use in a vname.
   454  func (pi *PackageInfo) Signature(obj types.Object) string {
   455  	if obj == nil {
   456  		return ""
   457  	} else if pi.owner == nil {
   458  		pi.owner = make(map[types.Object]types.Object)
   459  		ownerByPos := make(map[token.Position]types.Object)
   460  		unownedByPos := make(map[token.Position][]types.Object)
   461  		pi.addOwners(pi.Package, ownerByPos, unownedByPos)
   462  		for _, pkg := range pi.Dependencies {
   463  			pi.addOwners(pkg, ownerByPos, unownedByPos)
   464  		}
   465  	}
   466  	if sig, ok := pi.sigs[obj]; ok {
   467  		return sig
   468  	}
   469  	tag, base := pi.newSignature(obj)
   470  	sig := base
   471  	if tag != "" {
   472  		sig = tag + " " + base
   473  	}
   474  	pi.sigs[obj] = sig
   475  	return sig
   476  }
   477  
   478  // ObjectVName returns a VName for obj relative to that of its package.
   479  func (pi *PackageInfo) ObjectVName(obj types.Object) *spb.VName {
   480  	if pkg, ok := obj.(*types.PkgName); ok {
   481  		return pi.PackageVName[pkg.Imported()]
   482  	}
   483  	sig := pi.Signature(obj)
   484  	pkg := obj.Pkg()
   485  	var vname *spb.VName
   486  	if base := pi.PackageVName[pkg]; base != nil {
   487  		vname = proto.Clone(base).(*spb.VName)
   488  	} else if pkg == nil {
   489  		return govname.Builtin(obj.Name())
   490  	} else {
   491  		// This is an indirect import, that is, a name imported but not
   492  		// mentioned explicitly by the package being indexed.
   493  		// TODO(#2383): This is a workaround, and may not be correct in all
   494  		// cases; work out a more comprehensive solution (possibly during
   495  		// extraction).
   496  		vname = proto.Clone(pi.VName).(*spb.VName)
   497  		vname.Path = strings.TrimPrefix(pkg.Path(), vname.Corpus+"/")
   498  	}
   499  
   500  	vname.Signature = sig
   501  	return vname
   502  }
   503  
   504  // FileVName returns a VName for path relative to the package base.
   505  func (pi *PackageInfo) FileVName(file *ast.File) *spb.VName {
   506  	if v := pi.fileVName[file]; v != nil {
   507  		return v
   508  	}
   509  	v := proto.Clone(pi.VName).(*spb.VName)
   510  	v.Language = ""
   511  	v.Signature = ""
   512  	v.Path = pi.FileSet.Position(file.Pos()).Filename
   513  	return v
   514  }
   515  
   516  // AnchorVName returns a VName for the given file and offsets.
   517  func (pi *PackageInfo) AnchorVName(file *ast.File, start, end int) *spb.VName {
   518  	vname := proto.Clone(pi.FileVName(file)).(*spb.VName)
   519  	vname.Signature = "#" + strconv.Itoa(start) + ":" + strconv.Itoa(end)
   520  	vname.Language = govname.Language
   521  	return vname
   522  }
   523  
   524  // Span returns the containing file and 0-based offset range of the given AST
   525  // node.  The range is half-open, including the start position but excluding
   526  // the end.
   527  //
   528  // If node == nil or lacks a valid start position, Span returns nil -1, -1.  If
   529  // the end position of node is invalid, start == end.
   530  func (pi *PackageInfo) Span(node ast.Node) (file *ast.File, start, end int) {
   531  	if node == nil {
   532  		return nil, -1, -1
   533  	}
   534  	pos := node.Pos()
   535  	if pos == token.NoPos {
   536  		return nil, -1, -1
   537  	}
   538  	sp := pi.FileSet.Position(pos)
   539  	file = pi.fileLoc[pi.FileSet.File(pos)]
   540  	start = sp.Offset
   541  	end = start
   542  	if pos := node.End(); pos != token.NoPos {
   543  		end = pi.FileSet.Position(pos).Offset
   544  	}
   545  	return
   546  }
   547  
   548  const (
   549  	isBuiltin = "builtin-"
   550  	tagConst  = "const"
   551  	tagField  = "field"
   552  	tagFunc   = "func"
   553  	tagLabel  = "label"
   554  	tagMethod = "method"
   555  	tagParam  = "param"
   556  	tagTVar   = "tvar"
   557  	tagType   = "type"
   558  	tagVar    = "var"
   559  )
   560  
   561  // newSignature constructs and returns a tag and base signature for obj.  The
   562  // tag represents the "kind" of signature, to disambiguate built-in types from
   563  // user-defined names, fields from methods, and so on.  The base is a unique
   564  // name for obj within its package, modulo the tag.
   565  func (pi *PackageInfo) newSignature(obj types.Object) (tag, base string) {
   566  	if obj.Name() == "" {
   567  		return tagVar, "_"
   568  	}
   569  	topLevelTag := tagVar
   570  	switch t := obj.(type) {
   571  	case *types.Builtin:
   572  		return isBuiltin + tagFunc, t.Name()
   573  
   574  	case *types.Nil:
   575  		return isBuiltin + tagConst, "nil"
   576  
   577  	case *types.PkgName:
   578  		return "", "package" // the vname corpus and path carry the package name
   579  
   580  	case *types.Const:
   581  		topLevelTag = tagConst
   582  		if t.Pkg() == nil {
   583  			return isBuiltin + tagConst, t.Name()
   584  		}
   585  
   586  	case *types.Var:
   587  		if t.IsField() {
   588  			if owner, ok := pi.owner[t]; ok {
   589  				_, base := pi.newSignature(owner)
   590  				return tagField, base + "." + t.Name()
   591  			}
   592  			return tagField, pi.anonSignature(t)
   593  		} else if owner, ok := pi.owner[t]; ok {
   594  			_, base := pi.newSignature(owner)
   595  			return tagParam, base + ":" + t.Name()
   596  		}
   597  
   598  	case *types.Func:
   599  		topLevelTag = tagFunc
   600  		if recv := t.Type().(*types.Signature).Recv(); recv != nil { // method
   601  			if owner, ok := pi.owner[t]; ok {
   602  				_, base := pi.newSignature(owner)
   603  				return tagMethod, base + "." + t.Name()
   604  			}
   605  			// If the receiver is defined in this package, fully qualify the
   606  			// name so references from elsewhere will work. Strictly speaking
   607  			// this is only necessary for exported methods, but it's simpler to
   608  			// do it for everything.
   609  			return tagMethod, fmt.Sprintf("(%s).%s", types.TypeString(recv.Type(), func(pkg *types.Package) string {
   610  				return pkg.Name()
   611  			}), t.Name())
   612  		}
   613  
   614  	case *types.TypeName:
   615  		if param, ok := t.Type().(*types.TypeParam); ok {
   616  			return tagTVar, fmt.Sprintf("[%p]%s", t, param.String())
   617  		}
   618  		topLevelTag = tagType
   619  		if t.Pkg() == nil {
   620  			return isBuiltin + tagType, t.Name()
   621  		}
   622  
   623  	case *types.Label:
   624  		return tagLabel, pi.anonSignature(t)
   625  
   626  	default:
   627  		panic(fmt.Sprintf("Unexpected object kind: %T", obj))
   628  	}
   629  
   630  	// At this point, we have eliminated built-in objects; everything else must
   631  	// be defined in a package.
   632  	if obj.Pkg() == nil {
   633  		panic(fmt.Sprintf("Object without a package: %v", obj))
   634  	}
   635  
   636  	// Objects at package scope (i.e., parent scope is package scope).
   637  	if obj.Parent() == obj.Pkg().Scope() {
   638  		return topLevelTag, obj.Name()
   639  	}
   640  
   641  	// Objects in interior (local) scopes, i.e., everything else.
   642  	return topLevelTag, pi.anonSignature(obj)
   643  }
   644  
   645  func (pi *PackageInfo) anonSignature(obj types.Object) string {
   646  	// Use the object's line number and file basename to differentiate the
   647  	// node while allowing for cross-package references (other parts of the
   648  	// Position may differ).  This may collide if a source file isn't gofmt'd
   649  	// and defines multiple anonymous fields with the same name on the same
   650  	// line, but that's unlikely to happen in practice.
   651  	pos := pi.FileSet.Position(obj.Pos())
   652  	return fmt.Sprintf("[%s#%d].%s", filepath.Base(pos.Filename), pos.Line, obj.Name())
   653  }
   654  
   655  // addOwners updates pi.owner from the types in pkg, adding mapping from fields
   656  // of package-level named struct types to the owning named struct type; from
   657  // methods of package-level named interface types to the owning named interface
   658  // type; and from parameters of package-level named function or method types to
   659  // the owning named function or method.
   660  //
   661  // This relation is used to construct signatures for these fields/methods,
   662  // since they may be referenced from another package and thus need
   663  // deterministic names. An object does not expose its "owner"; indeed it may
   664  // have several.
   665  //
   666  // Caveats:
   667  //
   668  // (1) This mapping is deterministic but not necessarily the best one according
   669  // to the original syntax, to which, in general, we do not have access.  In
   670  // these two examples, the type checker considers field X as belonging equally
   671  // to types T and U, even though according the syntax, it belongs primarily to
   672  // T in the first example and U in the second:
   673  //
   674  //	type T struct {X int}
   675  //	type U T
   676  //
   677  //	type T U
   678  //	type U struct {X int}
   679  //
   680  // Similarly:
   681  //
   682  //	type U struct {X int}
   683  //	type V struct {U}
   684  //
   685  // TODO(adonovan): sameer@ points out a useful heuristic: in a case of struct
   686  // or interface embedding, if one struct/interface has fewer fields/methods,
   687  // then it must be the primary one.
   688  //
   689  // (2) This pass is not exhaustive: there remain objects that may be referenced
   690  // from outside the package but for which we can't easily come up with good
   691  // names.  Here are some examples:
   692  //
   693  //	// package p
   694  //	var V1, V2 struct {X int} = ...
   695  //	func F() struct{X int} {...}
   696  //	type T struct {
   697  //	        Y struct { X int }
   698  //	}
   699  //
   700  //	// main
   701  //	p.V2.X = 1
   702  //	print(p.F().X)
   703  //	new(p.T).Y[0].X
   704  //
   705  // Also note that there may be arbitrary pointer, struct, chan, map, array, and
   706  // slice type constructors between the type of the exported package member (V2,
   707  // F or T) and the type of its X subelement.  For now, we simply ignore such
   708  // names.  They should be rare in readable code.
   709  func (pi *PackageInfo) addOwners(pkg *types.Package, ownerByPos map[token.Position]types.Object, unownedByPos map[token.Position][]types.Object) {
   710  	scope := pkg.Scope()
   711  	addTypeParams := func(obj types.Object, params *types.TypeParamList) {
   712  		mapTypeParams(params, func(i int, param *types.TypeParam) {
   713  			typeName := param.Obj()
   714  			if _, ok := pi.owner[typeName]; !ok {
   715  				pi.owner[typeName] = obj
   716  			}
   717  		})
   718  	}
   719  	addFunc := func(obj *types.Func) {
   720  		// Inspect the receiver, parameters, and result values.
   721  		fsig := obj.Type().(*types.Signature)
   722  		if recv := fsig.Recv(); recv != nil {
   723  			pi.owner[recv] = obj
   724  		}
   725  		if params := fsig.Params(); params != nil {
   726  			for i := 0; i < params.Len(); i++ {
   727  				pi.owner[params.At(i)] = obj
   728  			}
   729  		}
   730  		if res := fsig.Results(); res != nil {
   731  			for i := 0; i < res.Len(); i++ {
   732  				pi.owner[res.At(i)] = obj
   733  			}
   734  		}
   735  		addTypeParams(obj, fsig.TypeParams())
   736  		addTypeParams(obj, fsig.RecvTypeParams())
   737  	}
   738  	addMethods := func(obj types.Object, n int, method func(i int) *types.Func) {
   739  		for i := 0; i < n; i++ {
   740  			m := method(i)
   741  			if _, ok := pi.owner[m]; !ok {
   742  				pos := pi.FileSet.Position(m.Pos())
   743  				if m.Pkg() == pkg {
   744  					pi.owner[m] = obj
   745  					addFunc(m)
   746  
   747  					// Keep track of owners by position to facilitate ownership across
   748  					// package boundaries for new type names of existing interfaces:
   749  					//
   750  					//    package pkg
   751  					//    type A fmt.Stringer
   752  					//
   753  					//    -----
   754  					//
   755  					//    package other
   756  					//    import "pkg"
   757  					//                         \/
   758  					//    func f(a pkg.A) { a.String() }
   759  					//
   760  					// Understanding that the above reference is to
   761  					// (fmt.Stringer).String() is lost due to compiler unwrapping the
   762  					// `type A fmt.Stringer` definition for downstream compilations.
   763  					// However, position info remains behind for stack traces so we can
   764  					// use it as fallback heuristic to determine "sameness" of methods.
   765  					ownerByPos[pos] = obj
   766  					for _, m := range unownedByPos[pos] {
   767  						pi.owner[m] = obj
   768  					}
   769  					delete(unownedByPos, pos)
   770  				} else if owner, ok := ownerByPos[pos]; ok {
   771  					pi.owner[m] = owner
   772  					addFunc(m)
   773  				} else {
   774  					unownedByPos[pos] = append(unownedByPos[pos], m)
   775  				}
   776  			}
   777  		}
   778  	}
   779  	addNamed := func(obj types.Object, named *types.Named) {
   780  		addTypeParams(obj, named.TypeParams())
   781  		switch t := named.Underlying().(type) {
   782  		case *types.Struct:
   783  			// Inspect the fields of a struct.
   784  			for i := 0; i < t.NumFields(); i++ {
   785  				f := t.Field(i)
   786  				if f.Pkg() != pkg && named.TypeArgs().Len() == 0 {
   787  					continue // wrong package (and not an instantiated type)
   788  				}
   789  				if _, ok := pi.owner[f]; !ok {
   790  					pi.owner[f] = obj
   791  				}
   792  			}
   793  			addMethods(obj, named.NumMethods(), named.Method)
   794  
   795  		case *types.Interface:
   796  			// Inspect the declared methods of an interface.
   797  			addMethods(obj, t.NumExplicitMethods(), t.ExplicitMethod)
   798  
   799  		default:
   800  			// Inspect declared methods of other named types.
   801  			addMethods(obj, named.NumMethods(), named.Method)
   802  		}
   803  	}
   804  
   805  	for _, name := range scope.Names() {
   806  		switch obj := scope.Lookup(name).(type) {
   807  		case *types.TypeName:
   808  			// TODO(schroederc): support for type aliases.  For now, skip these so we
   809  			// don't wind up emitting redundant declaration sites for the aliased
   810  			// type.
   811  			named, ok := obj.Type().(*types.Named)
   812  			if !ok {
   813  				continue
   814  			}
   815  			addNamed(obj, named)
   816  
   817  		case *types.Func:
   818  			addFunc(obj)
   819  		}
   820  	}
   821  
   822  	if pkg == pi.Package {
   823  		// Add owners for members of known known instantiations
   824  		for _, t := range pi.Info.Types {
   825  			if n, ok := t.Type.(*types.Named); ok && n.TypeArgs().Len() > 0 {
   826  				addNamed(n.Obj(), n)
   827  			}
   828  		}
   829  	}
   830  }
   831  
   832  // mapTypeParams applies f to each type parameter declared in params.  Each call
   833  // to f is given the offset and the type parameter.
   834  func mapTypeParams(params *types.TypeParamList, f func(i int, id *types.TypeParam)) {
   835  	if params == nil {
   836  		return
   837  	}
   838  	for i := 0; i < params.Len(); i++ {
   839  		f(i, params.At(i))
   840  	}
   841  }
   842  
   843  // findFieldName tries to resolve the identifier that names an embedded
   844  // anonymous field declaration at expr, and reports whether successful.
   845  func (pi *PackageInfo) findFieldName(expr ast.Expr) (id *ast.Ident, ok bool) {
   846  	// There are three cases we care about here:
   847  	//
   848  	// A bare identifier (foo), which refers to a type defined in
   849  	// this package, or a builtin type,
   850  	//
   851  	// A selector expression (pkg.Foo) referring to an exported
   852  	// type defined in another package, or
   853  	//
   854  	// A pointer to either of these.
   855  
   856  	switch t := expr.(type) {
   857  	case *ast.StarExpr: // *T
   858  		return pi.findFieldName(t.X)
   859  	case *ast.Ident: // T declared locally
   860  		return t, true
   861  	case *ast.SelectorExpr: // pkg.T declared elsewhere
   862  		return t.Sel, true
   863  	default:
   864  		// No idea what this is; possibly malformed code.
   865  		return nil, false
   866  	}
   867  }
   868  
   869  // importPath returns the import path of pkg.
   870  func (pi *PackageInfo) importPath(pkg *types.Package) string {
   871  	if v := pi.PackageVName[pkg]; v != nil {
   872  		return govname.ImportPath(v, pi.details.GetGoroot())
   873  	}
   874  	return pkg.Name()
   875  }
   876  
   877  // isPackageInit reports whether fi belongs to a package-level init function.
   878  func (pi *PackageInfo) isPackageInit(fi *funcInfo) bool {
   879  	for _, v := range pi.packageInit {
   880  		if fi == v {
   881  			return true
   882  		}
   883  	}
   884  	return false
   885  }
   886  
   887  // goDetails returns the GoDetails message attached to unit, if there is one;
   888  // otherwise it returns nil.
   889  func goDetails(unit *apb.CompilationUnit) *gopb.GoDetails {
   890  	for _, msg := range unit.Details {
   891  		var dets gopb.GoDetails
   892  		if err := ptypes.UnmarshalAny(msg, &dets); err == nil {
   893  			return &dets
   894  		}
   895  	}
   896  	return nil
   897  }
   898  
   899  // goPackageInfo returns the GoPackageInfo message within the given slice, if
   900  // there is one; otherwise it returns nil.
   901  func goPackageInfo(details []*ptypes.Any) *gopb.GoPackageInfo {
   902  	for _, msg := range details {
   903  		var info gopb.GoPackageInfo
   904  		if err := ptypes.UnmarshalAny(msg, &info); err == nil {
   905  			return &info
   906  		}
   907  	}
   908  	return nil
   909  }
   910  
   911  // loadInlineMetadata unmarshals the encoded metadata string and returns
   912  // the corresponding metadata rules which link source definitions
   913  // to the file fi. An error is returned if unmarshalling fails.
   914  func loadInlineMetadata(fi *apb.CompilationUnit_FileInput, encodedMetadata string) (*Ruleset, error) {
   915  	var gci mpb.GeneratedCodeInfo
   916  	err := unmarshalProtoBase64(encodedMetadata, &gci)
   917  	if err != nil {
   918  		return nil, err
   919  	}
   920  
   921  	rules := make(metadata.Rules, 0, len(gci.GetMeta()))
   922  	for _, r := range gci.GetMeta() {
   923  		k, rev := strings.CutPrefix(r.Edge, "%")
   924  		rules = append(rules, metadata.Rule{
   925  			EdgeIn:  edges.DefinesBinding,
   926  			EdgeOut: k,
   927  			VName:   r.GetVname(),
   928  			Reverse: rev,
   929  			Begin:   int(r.GetBegin()),
   930  			End:     int(r.GetEnd()),
   931  		})
   932  	}
   933  	return &Ruleset{
   934  		Path:  fi.Info.GetPath(),
   935  		Rules: rules,
   936  	}, nil
   937  }
   938  
   939  // matchesBuildTags reports whether the file at fpath, whose content is in
   940  // data, would be matched by the settings in bc.
   941  func matchesBuildTags(fpath string, data []byte, bc *build.Context) bool {
   942  	dir, name := filepath.Split(fpath)
   943  	bc.OpenFile = func(path string) (io.ReadCloser, error) {
   944  		if path != fpath {
   945  			return nil, errors.New("file not found")
   946  		}
   947  		return ioutil.NopCloser(bytes.NewReader(data)), nil
   948  	}
   949  	match, err := bc.MatchFile(dir, name)
   950  	return err == nil && match
   951  }
   952  
   953  // unmarshalProtoBase64 parses a base64 encoded proto string into the supplied
   954  // message, mutating msg.
   955  func unmarshalProtoBase64(base64Str string, msg proto.Message) error {
   956  	b, _ := base64.StdEncoding.DecodeString(base64Str)
   957  	return proto.Unmarshal(b, msg)
   958  }
   959  
   960  // AllTypeInfo creates a new types.Info value with empty maps for each of the
   961  // fields that can be filled in by the type-checker.
   962  func AllTypeInfo() *types.Info {
   963  	return &types.Info{
   964  		Types:      make(map[ast.Expr]types.TypeAndValue),
   965  		Defs:       make(map[*ast.Ident]types.Object),
   966  		Uses:       make(map[*ast.Ident]types.Object),
   967  		Implicits:  make(map[ast.Node]types.Object),
   968  		Selections: make(map[*ast.SelectorExpr]*types.Selection),
   969  		Scopes:     make(map[ast.Node]*types.Scope),
   970  	}
   971  }
   972  
   973  // XRefTypeInfo creates a new types.Info value with empty maps for each of the
   974  // fields needed for cross-reference indexing.
   975  func XRefTypeInfo() *types.Info {
   976  	return &types.Info{
   977  		Types:     make(map[ast.Expr]types.TypeAndValue),
   978  		Defs:      make(map[*ast.Ident]types.Object),
   979  		Uses:      make(map[*ast.Ident]types.Object),
   980  		Implicits: make(map[ast.Node]types.Object),
   981  	}
   982  }