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 }