golang.org/x/tools@v0.21.0/go/packages/golist_overlay.go (about)

     1  // Copyright 2018 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 packages
     6  
     7  import (
     8  	"encoding/json"
     9  	"path/filepath"
    10  
    11  	"golang.org/x/tools/internal/gocommand"
    12  )
    13  
    14  // determineRootDirs returns a mapping from absolute directories that could
    15  // contain code to their corresponding import path prefixes.
    16  func (state *golistState) determineRootDirs() (map[string]string, error) {
    17  	env, err := state.getEnv()
    18  	if err != nil {
    19  		return nil, err
    20  	}
    21  	if env["GOMOD"] != "" {
    22  		state.rootsOnce.Do(func() {
    23  			state.rootDirs, state.rootDirsError = state.determineRootDirsModules()
    24  		})
    25  	} else {
    26  		state.rootsOnce.Do(func() {
    27  			state.rootDirs, state.rootDirsError = state.determineRootDirsGOPATH()
    28  		})
    29  	}
    30  	return state.rootDirs, state.rootDirsError
    31  }
    32  
    33  func (state *golistState) determineRootDirsModules() (map[string]string, error) {
    34  	// List all of the modules--the first will be the directory for the main
    35  	// module. Any replaced modules will also need to be treated as roots.
    36  	// Editing files in the module cache isn't a great idea, so we don't
    37  	// plan to ever support that.
    38  	out, err := state.invokeGo("list", "-m", "-json", "all")
    39  	if err != nil {
    40  		// 'go list all' will fail if we're outside of a module and
    41  		// GO111MODULE=on. Try falling back without 'all'.
    42  		var innerErr error
    43  		out, innerErr = state.invokeGo("list", "-m", "-json")
    44  		if innerErr != nil {
    45  			return nil, err
    46  		}
    47  	}
    48  	roots := map[string]string{}
    49  	modules := map[string]string{}
    50  	var i int
    51  	for dec := json.NewDecoder(out); dec.More(); {
    52  		mod := new(gocommand.ModuleJSON)
    53  		if err := dec.Decode(mod); err != nil {
    54  			return nil, err
    55  		}
    56  		if mod.Dir != "" && mod.Path != "" {
    57  			// This is a valid module; add it to the map.
    58  			absDir, err := filepath.Abs(mod.Dir)
    59  			if err != nil {
    60  				return nil, err
    61  			}
    62  			modules[absDir] = mod.Path
    63  			// The first result is the main module.
    64  			if i == 0 || mod.Replace != nil && mod.Replace.Path != "" {
    65  				roots[absDir] = mod.Path
    66  			}
    67  		}
    68  		i++
    69  	}
    70  	return roots, nil
    71  }
    72  
    73  func (state *golistState) determineRootDirsGOPATH() (map[string]string, error) {
    74  	m := map[string]string{}
    75  	for _, dir := range filepath.SplitList(state.mustGetEnv()["GOPATH"]) {
    76  		absDir, err := filepath.Abs(dir)
    77  		if err != nil {
    78  			return nil, err
    79  		}
    80  		m[filepath.Join(absDir, "src")] = ""
    81  	}
    82  	return m, nil
    83  }