github.com/pankona/gometalinter@v2.0.11+incompatible/_linters/src/golang.org/x/tools/go/buildutil/fakecontext.go (about) 1 package buildutil 2 3 import ( 4 "fmt" 5 "go/build" 6 "io" 7 "io/ioutil" 8 "os" 9 "path" 10 "path/filepath" 11 "sort" 12 "strings" 13 "time" 14 ) 15 16 // FakeContext returns a build.Context for the fake file tree specified 17 // by pkgs, which maps package import paths to a mapping from file base 18 // names to contents. 19 // 20 // The fake Context has a GOROOT of "/go" and no GOPATH, and overrides 21 // the necessary file access methods to read from memory instead of the 22 // real file system. 23 // 24 // Unlike a real file tree, the fake one has only two levels---packages 25 // and files---so ReadDir("/go/src/") returns all packages under 26 // /go/src/ including, for instance, "math" and "math/big". 27 // ReadDir("/go/src/math/big") would return all the files in the 28 // "math/big" package. 29 // 30 func FakeContext(pkgs map[string]map[string]string) *build.Context { 31 clean := func(filename string) string { 32 f := path.Clean(filepath.ToSlash(filename)) 33 // Removing "/go/src" while respecting segment 34 // boundaries has this unfortunate corner case: 35 if f == "/go/src" { 36 return "" 37 } 38 return strings.TrimPrefix(f, "/go/src/") 39 } 40 41 ctxt := build.Default // copy 42 ctxt.GOROOT = "/go" 43 ctxt.GOPATH = "" 44 ctxt.IsDir = func(dir string) bool { 45 dir = clean(dir) 46 if dir == "" { 47 return true // needed by (*build.Context).SrcDirs 48 } 49 return pkgs[dir] != nil 50 } 51 ctxt.ReadDir = func(dir string) ([]os.FileInfo, error) { 52 dir = clean(dir) 53 var fis []os.FileInfo 54 if dir == "" { 55 // enumerate packages 56 for importPath := range pkgs { 57 fis = append(fis, fakeDirInfo(importPath)) 58 } 59 } else { 60 // enumerate files of package 61 for basename := range pkgs[dir] { 62 fis = append(fis, fakeFileInfo(basename)) 63 } 64 } 65 sort.Sort(byName(fis)) 66 return fis, nil 67 } 68 ctxt.OpenFile = func(filename string) (io.ReadCloser, error) { 69 filename = clean(filename) 70 dir, base := path.Split(filename) 71 content, ok := pkgs[path.Clean(dir)][base] 72 if !ok { 73 return nil, fmt.Errorf("file not found: %s", filename) 74 } 75 return ioutil.NopCloser(strings.NewReader(content)), nil 76 } 77 ctxt.IsAbsPath = func(path string) bool { 78 path = filepath.ToSlash(path) 79 // Don't rely on the default (filepath.Path) since on 80 // Windows, it reports virtual paths as non-absolute. 81 return strings.HasPrefix(path, "/") 82 } 83 return &ctxt 84 } 85 86 type byName []os.FileInfo 87 88 func (s byName) Len() int { return len(s) } 89 func (s byName) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 90 func (s byName) Less(i, j int) bool { return s[i].Name() < s[j].Name() } 91 92 type fakeFileInfo string 93 94 func (fi fakeFileInfo) Name() string { return string(fi) } 95 func (fakeFileInfo) Sys() interface{} { return nil } 96 func (fakeFileInfo) ModTime() time.Time { return time.Time{} } 97 func (fakeFileInfo) IsDir() bool { return false } 98 func (fakeFileInfo) Size() int64 { return 0 } 99 func (fakeFileInfo) Mode() os.FileMode { return 0644 } 100 101 type fakeDirInfo string 102 103 func (fd fakeDirInfo) Name() string { return string(fd) } 104 func (fakeDirInfo) Sys() interface{} { return nil } 105 func (fakeDirInfo) ModTime() time.Time { return time.Time{} } 106 func (fakeDirInfo) IsDir() bool { return true } 107 func (fakeDirInfo) Size() int64 { return 0 } 108 func (fakeDirInfo) Mode() os.FileMode { return 0755 }