GoPLS Viewer

Home|gopls/go/packages/golist_overlay.go
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
5package packages
6
7import (
8    "encoding/json"
9    "fmt"
10    "go/parser"
11    "go/token"
12    "os"
13    "path/filepath"
14    "regexp"
15    "sort"
16    "strconv"
17    "strings"
18
19    "golang.org/x/tools/internal/gocommand"
20)
21
22// processGolistOverlay provides rudimentary support for adding
23// files that don't exist on disk to an overlay. The results can be
24// sometimes incorrect.
25// TODO(matloob): Handle unsupported cases, including the following:
26// - determining the correct package to add given a new import path
27func (state *golistStateprocessGolistOverlay(response *responseDeduper) (modifiedPkgsneedPkgs []stringerr error) {
28    havePkgs := make(map[string]string// importPath -> non-test package ID
29    needPkgsSet := make(map[string]bool)
30    modifiedPkgsSet := make(map[string]bool)
31
32    pkgOfDir := make(map[string][]*Package)
33    for _pkg := range response.dr.Packages {
34        // This is an approximation of import path to id. This can be
35        // wrong for tests, vendored packages, and a number of other cases.
36        havePkgs[pkg.PkgPath] = pkg.ID
37        direrr := commonDir(pkg.GoFiles)
38        if err != nil {
39            return nilnilerr
40        }
41        if dir != "" {
42            pkgOfDir[dir] = append(pkgOfDir[dir], pkg)
43        }
44    }
45
46    // If no new imports are added, it is safe to avoid loading any needPkgs.
47    // Otherwise, it's hard to tell which package is actually being loaded
48    // (due to vendoring) and whether any modified package will show up
49    // in the transitive set of dependencies (because new imports are added,
50    // potentially modifying the transitive set of dependencies).
51    var overlayAddsImports bool
52
53    // If both a package and its test package are created by the overlay, we
54    // need the real package first. Process all non-test files before test
55    // files, and make the whole process deterministic while we're at it.
56    var overlayFiles []string
57    for opath := range state.cfg.Overlay {
58        overlayFiles = append(overlayFilesopath)
59    }
60    sort.Slice(overlayFiles, func(ij intbool {
61        iTest := strings.HasSuffix(overlayFiles[i], "_test.go")
62        jTest := strings.HasSuffix(overlayFiles[j], "_test.go")
63        if iTest != jTest {
64            return !iTest // non-tests are before tests.
65        }
66        return overlayFiles[i] < overlayFiles[j]
67    })
68    for _opath := range overlayFiles {
69        contents := state.cfg.Overlay[opath]
70        base := filepath.Base(opath)
71        dir := filepath.Dir(opath)
72        var pkg *Package           // if opath belongs to both a package and its test variant, this will be the test variant
73        var testVariantOf *Package // if opath is a test file, this is the package it is testing
74        var fileExists bool
75        isTestFile := strings.HasSuffix(opath"_test.go")
76        pkgNameok := extractPackageName(opathcontents)
77        if !ok {
78            // Don't bother adding a file that doesn't even have a parsable package statement
79            // to the overlay.
80            continue
81        }
82        // If all the overlay files belong to a different package, change the
83        // package name to that package.
84        maybeFixPackageName(pkgNameisTestFilepkgOfDir[dir])
85    nextPackage:
86        for _p := range response.dr.Packages {
87            if pkgName != p.Name && p.ID != "command-line-arguments" {
88                continue
89            }
90            for _f := range p.GoFiles {
91                if !sameFile(filepath.Dir(f), dir) {
92                    continue
93                }
94                // Make sure to capture information on the package's test variant, if needed.
95                if isTestFile && !hasTestFiles(p) {
96                    // TODO(matloob): Are there packages other than the 'production' variant
97                    // of a package that this can match? This shouldn't match the test main package
98                    // because the file is generated in another directory.
99                    testVariantOf = p
100                    continue nextPackage
101                } else if !isTestFile && hasTestFiles(p) {
102                    // We're examining a test variant, but the overlaid file is
103                    // a non-test file. Because the overlay implementation
104                    // (currently) only adds a file to one package, skip this
105                    // package, so that we can add the file to the production
106                    // variant of the package. (https://golang.org/issue/36857
107                    // tracks handling overlays on both the production and test
108                    // variant of a package).
109                    continue nextPackage
110                }
111                if pkg != nil && p != pkg && pkg.PkgPath == p.PkgPath {
112                    // We have already seen the production version of the
113                    // for which p is a test variant.
114                    if hasTestFiles(p) {
115                        testVariantOf = pkg
116                    }
117                }
118                pkg = p
119                if filepath.Base(f) == base {
120                    fileExists = true
121                }
122            }
123        }
124        // The overlay could have included an entirely new package or an
125        // ad-hoc package. An ad-hoc package is one that we have manually
126        // constructed from inadequate `go list` results for a file= query.
127        // It will have the ID command-line-arguments.
128        if pkg == nil || pkg.ID == "command-line-arguments" {
129            // Try to find the module or gopath dir the file is contained in.
130            // Then for modules, add the module opath to the beginning.
131            pkgPathokerr := state.getPkgPath(dir)
132            if err != nil {
133                return nilnilerr
134            }
135            if !ok {
136                break
137            }
138            var forTest string // only set for x tests
139            isXTest := strings.HasSuffix(pkgName"_test")
140            if isXTest {
141                forTest = pkgPath
142                pkgPath += "_test"
143            }
144            id := pkgPath
145            if isTestFile {
146                if isXTest {
147                    id = fmt.Sprintf("%s [%s.test]"pkgPathforTest)
148                } else {
149                    id = fmt.Sprintf("%s [%s.test]"pkgPathpkgPath)
150                }
151            }
152            if pkg != nil {
153                // TODO(rstambler): We should change the package's path and ID
154                // here. The only issue is that this messes with the roots.
155            } else {
156                // Try to reclaim a package with the same ID, if it exists in the response.
157                for _p := range response.dr.Packages {
158                    if reclaimPackage(pidopathcontents) {
159                        pkg = p
160                        break
161                    }
162                }
163                // Otherwise, create a new package.
164                if pkg == nil {
165                    pkg = &Package{
166                        PkgPathpkgPath,
167                        ID:      id,
168                        Name:    pkgName,
169                        Importsmake(map[string]*Package),
170                    }
171                    response.addPackage(pkg)
172                    havePkgs[pkg.PkgPath] = id
173                    // Add the production package's sources for a test variant.
174                    if isTestFile && !isXTest && testVariantOf != nil {
175                        pkg.GoFiles = append(pkg.GoFilestestVariantOf.GoFiles...)
176                        pkg.CompiledGoFiles = append(pkg.CompiledGoFilestestVariantOf.CompiledGoFiles...)
177                        // Add the package under test and its imports to the test variant.
178                        pkg.forTest = testVariantOf.PkgPath
179                        for kv := range testVariantOf.Imports {
180                            pkg.Imports[k] = &Package{IDv.ID}
181                        }
182                    }
183                    if isXTest {
184                        pkg.forTest = forTest
185                    }
186                }
187            }
188        }
189        if !fileExists {
190            pkg.GoFiles = append(pkg.GoFilesopath)
191            // TODO(matloob): Adding the file to CompiledGoFiles can exhibit the wrong behavior
192            // if the file will be ignored due to its build tags.
193            pkg.CompiledGoFiles = append(pkg.CompiledGoFilesopath)
194            modifiedPkgsSet[pkg.ID] = true
195        }
196        importserr := extractImports(opathcontents)
197        if err != nil {
198            // Let the parser or type checker report errors later.
199            continue
200        }
201        for _imp := range imports {
202            // TODO(rstambler): If the package is an x test and the import has
203            // a test variant, make sure to replace it.
204            if _found := pkg.Imports[imp]; found {
205                continue
206            }
207            overlayAddsImports = true
208            idok := havePkgs[imp]
209            if !ok {
210                var err error
211                iderr = state.resolveImport(dirimp)
212                if err != nil {
213                    return nilnilerr
214                }
215            }
216            pkg.Imports[imp] = &Package{IDid}
217            // Add dependencies to the non-test variant version of this package as well.
218            if testVariantOf != nil {
219                testVariantOf.Imports[imp] = &Package{IDid}
220            }
221        }
222    }
223
224    // toPkgPath guesses the package path given the id.
225    toPkgPath := func(sourceDirid string) (stringerror) {
226        if i := strings.IndexByte(id' '); i >= 0 {
227            return state.resolveImport(sourceDirid[:i])
228        }
229        return state.resolveImport(sourceDirid)
230    }
231
232    // Now that new packages have been created, do another pass to determine
233    // the new set of missing packages.
234    for _pkg := range response.dr.Packages {
235        for _imp := range pkg.Imports {
236            if len(pkg.GoFiles) == 0 {
237                return nilnilfmt.Errorf("cannot resolve imports for package %q with no Go files"pkg.PkgPath)
238            }
239            pkgPatherr := toPkgPath(filepath.Dir(pkg.GoFiles[0]), imp.ID)
240            if err != nil {
241                return nilnilerr
242            }
243            if _ok := havePkgs[pkgPath]; !ok {
244                needPkgsSet[pkgPath] = true
245            }
246        }
247    }
248
249    if overlayAddsImports {
250        needPkgs = make([]string0len(needPkgsSet))
251        for pkg := range needPkgsSet {
252            needPkgs = append(needPkgspkg)
253        }
254    }
255    modifiedPkgs = make([]string0len(modifiedPkgsSet))
256    for pkg := range modifiedPkgsSet {
257        modifiedPkgs = append(modifiedPkgspkg)
258    }
259    return modifiedPkgsneedPkgserr
260}
261
262// resolveImport finds the ID of a package given its import path.
263// In particular, it will find the right vendored copy when in GOPATH mode.
264func (state *golistStateresolveImport(sourceDirimportPath string) (stringerror) {
265    enverr := state.getEnv()
266    if err != nil {
267        return ""err
268    }
269    if env["GOMOD"] != "" {
270        return importPathnil
271    }
272
273    searchDir := sourceDir
274    for {
275        vendorDir := filepath.Join(searchDir"vendor")
276        existsok := state.vendorDirs[vendorDir]
277        if !ok {
278            infoerr := os.Stat(vendorDir)
279            exists = err == nil && info.IsDir()
280            state.vendorDirs[vendorDir] = exists
281        }
282
283        if exists {
284            vendoredPath := filepath.Join(vendorDirimportPath)
285            if infoerr := os.Stat(vendoredPath); err == nil && info.IsDir() {
286                // We should probably check for .go files here, but shame on anyone who fools us.
287                pathokerr := state.getPkgPath(vendoredPath)
288                if err != nil {
289                    return ""err
290                }
291                if ok {
292                    return pathnil
293                }
294            }
295        }
296
297        // We know we've hit the top of the filesystem when we Dir / and get /,
298        // or C:\ and get C:\, etc.
299        next := filepath.Dir(searchDir)
300        if next == searchDir {
301            break
302        }
303        searchDir = next
304    }
305    return importPathnil
306}
307
308func hasTestFiles(p *Packagebool {
309    for _f := range p.GoFiles {
310        if strings.HasSuffix(f"_test.go") {
311            return true
312        }
313    }
314    return false
315}
316
317// determineRootDirs returns a mapping from absolute directories that could
318// contain code to their corresponding import path prefixes.
319func (state *golistStatedetermineRootDirs() (map[string]stringerror) {
320    enverr := state.getEnv()
321    if err != nil {
322        return nilerr
323    }
324    if env["GOMOD"] != "" {
325        state.rootsOnce.Do(func() {
326            state.rootDirsstate.rootDirsError = state.determineRootDirsModules()
327        })
328    } else {
329        state.rootsOnce.Do(func() {
330            state.rootDirsstate.rootDirsError = state.determineRootDirsGOPATH()
331        })
332    }
333    return state.rootDirsstate.rootDirsError
334}
335
336func (state *golistStatedetermineRootDirsModules() (map[string]stringerror) {
337    // List all of the modules--the first will be the directory for the main
338    // module. Any replaced modules will also need to be treated as roots.
339    // Editing files in the module cache isn't a great idea, so we don't
340    // plan to ever support that.
341    outerr := state.invokeGo("list""-m""-json""all")
342    if err != nil {
343        // 'go list all' will fail if we're outside of a module and
344        // GO111MODULE=on. Try falling back without 'all'.
345        var innerErr error
346        outinnerErr = state.invokeGo("list""-m""-json")
347        if innerErr != nil {
348            return nilerr
349        }
350    }
351    roots := map[string]string{}
352    modules := map[string]string{}
353    var i int
354    for dec := json.NewDecoder(out); dec.More(); {
355        mod := new(gocommand.ModuleJSON)
356        if err := dec.Decode(mod); err != nil {
357            return nilerr
358        }
359        if mod.Dir != "" && mod.Path != "" {
360            // This is a valid module; add it to the map.
361            absDirerr := filepath.Abs(mod.Dir)
362            if err != nil {
363                return nilerr
364            }
365            modules[absDir] = mod.Path
366            // The first result is the main module.
367            if i == 0 || mod.Replace != nil && mod.Replace.Path != "" {
368                roots[absDir] = mod.Path
369            }
370        }
371        i++
372    }
373    return rootsnil
374}
375
376func (state *golistStatedetermineRootDirsGOPATH() (map[string]stringerror) {
377    m := map[string]string{}
378    for _dir := range filepath.SplitList(state.mustGetEnv()["GOPATH"]) {
379        absDirerr := filepath.Abs(dir)
380        if err != nil {
381            return nilerr
382        }
383        m[filepath.Join(absDir"src")] = ""
384    }
385    return mnil
386}
387
388func extractImports(filename stringcontents []byte) ([]stringerror) {
389    ferr := parser.ParseFile(token.NewFileSet(), filenamecontentsparser.ImportsOnly// TODO(matloob): reuse fileset?
390    if err != nil {
391        return nilerr
392    }
393    var res []string
394    for _imp := range f.Imports {
395        quotedPath := imp.Path.Value
396        patherr := strconv.Unquote(quotedPath)
397        if err != nil {
398            return nilerr
399        }
400        res = append(respath)
401    }
402    return resnil
403}
404
405// reclaimPackage attempts to reuse a package that failed to load in an overlay.
406//
407// If the package has errors and has no Name, GoFiles, or Imports,
408// then it's possible that it doesn't yet exist on disk.
409func reclaimPackage(pkg *Packageid stringfilename stringcontents []bytebool {
410    // TODO(rstambler): Check the message of the actual error?
411    // It differs between $GOPATH and module mode.
412    if pkg.ID != id {
413        return false
414    }
415    if len(pkg.Errors) != 1 {
416        return false
417    }
418    if pkg.Name != "" || pkg.ExportFile != "" {
419        return false
420    }
421    if len(pkg.GoFiles) > 0 || len(pkg.CompiledGoFiles) > 0 || len(pkg.OtherFiles) > 0 {
422        return false
423    }
424    if len(pkg.Imports) > 0 {
425        return false
426    }
427    pkgNameok := extractPackageName(filenamecontents)
428    if !ok {
429        return false
430    }
431    pkg.Name = pkgName
432    pkg.Errors = nil
433    return true
434}
435
436func extractPackageName(filename stringcontents []byte) (stringbool) {
437    // TODO(rstambler): Check the message of the actual error?
438    // It differs between $GOPATH and module mode.
439    ferr := parser.ParseFile(token.NewFileSet(), filenamecontentsparser.PackageClauseOnly// TODO(matloob): reuse fileset?
440    if err != nil {
441        return ""false
442    }
443    return f.Name.Nametrue
444}
445
446// commonDir returns the directory that all files are in, "" if files is empty,
447// or an error if they aren't in the same directory.
448func commonDir(files []string) (stringerror) {
449    seen := make(map[string]bool)
450    for _f := range files {
451        seen[filepath.Dir(f)] = true
452    }
453    if len(seen) > 1 {
454        return ""fmt.Errorf("files (%v) are in more than one directory: %v"filesseen)
455    }
456    for k := range seen {
457        // seen has only one element; return it.
458        return knil
459    }
460    return ""nil // no files
461}
462
463// It is possible that the files in the disk directory dir have a different package
464// name from newName, which is deduced from the overlays. If they all have a different
465// package name, and they all have the same package name, then that name becomes
466// the package name.
467// It returns true if it changes the package name, false otherwise.
468func maybeFixPackageName(newName stringisTestFile boolpkgsOfDir []*Package) {
469    names := make(map[string]int)
470    for _p := range pkgsOfDir {
471        names[p.Name]++
472    }
473    if len(names) != 1 {
474        // some files are in different packages
475        return
476    }
477    var oldName string
478    for k := range names {
479        oldName = k
480    }
481    if newName == oldName {
482        return
483    }
484    // We might have a case where all of the package names in the directory are
485    // the same, but the overlay file is for an x test, which belongs to its
486    // own package. If the x test does not yet exist on disk, we may not yet
487    // have its package name on disk, but we should not rename the packages.
488    //
489    // We use a heuristic to determine if this file belongs to an x test:
490    // The test file should have a package name whose package name has a _test
491    // suffix or looks like "newName_test".
492    maybeXTest := strings.HasPrefix(oldName+"_test"newName) || strings.HasSuffix(newName"_test")
493    if isTestFile && maybeXTest {
494        return
495    }
496    for _p := range pkgsOfDir {
497        p.Name = newName
498    }
499}
500
501// This function is copy-pasted from
502// https://github.com/golang/go/blob/9706f510a5e2754595d716bd64be8375997311fb/src/cmd/go/internal/search/search.go#L360.
503// It should be deleted when we remove support for overlays from go/packages.
504//
505// NOTE: This does not handle any ./... or ./ style queries, as this function
506// doesn't know the working directory.
507//
508// matchPattern(pattern)(name) reports whether
509// name matches pattern. Pattern is a limited glob
510// pattern in which '...' means 'any string' and there
511// is no other special syntax.
512// Unfortunately, there are two special cases. Quoting "go help packages":
513//
514// First, /... at the end of the pattern can match an empty string,
515// so that net/... matches both net and packages in its subdirectories, like net/http.
516// Second, any slash-separated pattern element containing a wildcard never
517// participates in a match of the "vendor" element in the path of a vendored
518// package, so that ./... does not match packages in subdirectories of
519// ./vendor or ./mycode/vendor, but ./vendor/... and ./mycode/vendor/... do.
520// Note, however, that a directory named vendor that itself contains code
521// is not a vendored package: cmd/vendor would be a command named vendor,
522// and the pattern cmd/... matches it.
523func matchPattern(pattern string) func(name stringbool {
524    // Convert pattern to regular expression.
525    // The strategy for the trailing /... is to nest it in an explicit ? expression.
526    // The strategy for the vendor exclusion is to change the unmatchable
527    // vendor strings to a disallowed code point (vendorChar) and to use
528    // "(anything but that codepoint)*" as the implementation of the ... wildcard.
529    // This is a bit complicated but the obvious alternative,
530    // namely a hand-written search like in most shell glob matchers,
531    // is too easy to make accidentally exponential.
532    // Using package regexp guarantees linear-time matching.
533
534    const vendorChar = "\x00"
535
536    if strings.Contains(patternvendorChar) {
537        return func(name stringbool { return false }
538    }
539
540    re := regexp.QuoteMeta(pattern)
541    re = replaceVendor(revendorChar)
542    switch {
543    case strings.HasSuffix(re`/`+vendorChar+`/\.\.\.`):
544        re = strings.TrimSuffix(re`/`+vendorChar+`/\.\.\.`) + `(/vendor|/` + vendorChar + `/\.\.\.)`
545    case re == vendorChar+`/\.\.\.`:
546        re = `(/vendor|/` + vendorChar + `/\.\.\.)`
547    case strings.HasSuffix(re`/\.\.\.`):
548        re = strings.TrimSuffix(re`/\.\.\.`) + `(/\.\.\.)?`
549    }
550    re = strings.ReplaceAll(re`\.\.\.``[^`+vendorChar+`]*`)
551
552    reg := regexp.MustCompile(`^` + re + `$`)
553
554    return func(name stringbool {
555        if strings.Contains(namevendorChar) {
556            return false
557        }
558        return reg.MatchString(replaceVendor(namevendorChar))
559    }
560}
561
562// replaceVendor returns the result of replacing
563// non-trailing vendor path elements in x with repl.
564func replaceVendor(xrepl stringstring {
565    if !strings.Contains(x"vendor") {
566        return x
567    }
568    elem := strings.Split(x"/")
569    for i := 0i < len(elem)-1i++ {
570        if elem[i] == "vendor" {
571            elem[i] = repl
572        }
573    }
574    return strings.Join(elem"/")
575}
576
MembersX
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.imports
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.RangeStmt_7080.imp
golistState.determineRootDirsModules.out
golistState.determineRootDirsGOPATH
regexp
golistState.processGolistOverlay
golistState.processGolistOverlay.BlockStmt.iTest
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.fileExists
extractImports.res
extractImports.RangeStmt_12545.BlockStmt.path
reclaimPackage.contents
matchPattern.vendorChar
reclaimPackage.filename
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.ok
hasTestFiles.p
golistState.determineRootDirsModules.state
golistState.determineRootDirsModules
golistState.resolveImport.searchDir
extractImports
matchPattern.pattern
extractImports.RangeStmt_12545.imp
maybeFixPackageName.RangeStmt_14906.p
golistState.processGolistOverlay.RangeStmt_1948.opath
matchPattern.reg
golistState.processGolistOverlay.state
golistState.determineRootDirsGOPATH.RangeStmt_12086.dir
extractImports.RangeStmt_12545.BlockStmt.err
maybeFixPackageName.pkgsOfDir
replaceVendor.x
golistState.processGolistOverlay.pkgOfDir
golistState.processGolistOverlay.overlayAddsImports
extractImports.filename
commonDir.files
reclaimPackage.ok
maybeFixPackageName.isTestFile
maybeFixPackageName.oldName
golistState.processGolistOverlay.err
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.pkgName
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.RangeStmt_3110.p
golistState.processGolistOverlay.BlockStmt.RangeStmt_8553.pkg
golistState.processGolistOverlay.BlockStmt.jTest
extractImports.f
golistState.determineRootDirsModules.BlockStmt.BlockStmt.err
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.pkgPath
golistState.resolveImport
golistState.determineRootDirs.env
golistState.determineRootDirsModules.err
hasTestFiles
golistState.determineRootDirsModules.BlockStmt.BlockStmt.absDir
extractImports.err
golistState.processGolistOverlay.response
golistState.processGolistOverlay.needPkgsSet
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.isTestFile
golistState.resolveImport.BlockStmt.BlockStmt.BlockStmt.ok
golistState.resolveImport.BlockStmt.next
extractImports.contents
golistState.resolveImport.env
golistState.determineRootDirs.err
golistState.determineRootDirsModules.dec
matchPattern.re
golistState.processGolistOverlay.RangeStmt_956.BlockStmt.dir
golistState.determineRootDirs
golistState.determineRootDirsModules.BlockStmt.innerErr
reclaimPackage.pkgName
replaceVendor.elem
golistState.processGolistOverlay.havePkgs
golistState.processGolistOverlay.BlockStmt.i
golistState.resolveImport.BlockStmt.BlockStmt.vendoredPath
golistState.determineRootDirsModules.BlockStmt.mod
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.BlockStmt.BlockStmt.BlockStmt.RangeStmt_6463.k
golistState.determineRootDirsGOPATH.RangeStmt_12086.BlockStmt.absDir
reclaimPackage.id
golistState.processGolistOverlay.RangeStmt_956.BlockStmt.err
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.pkg
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.BlockStmt.RangeStmt_5676.p
golistState.determineRootDirsModules.roots
golistState.resolveImport.BlockStmt.BlockStmt.BlockStmt.err
golistState.determineRootDirsModules.modules
maybeFixPackageName.RangeStmt_15764.p
golistState.processGolistOverlay.overlayFiles
hasTestFiles.RangeStmt_10046.f
reclaimPackage
golistState.determineRootDirsModules.BlockStmt.err
golistState.determineRootDirsGOPATH.state
extractImports.RangeStmt_12545.BlockStmt.quotedPath
extractPackageName.err
golistState.processGolistOverlay.modifiedPkgsSet
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.ok
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.err
golistState.determineRootDirs.state
extractPackageName.contents
token
golistState.resolveImport.importPath
golistState.determineRootDirsModules.i
matchPattern
reclaimPackage.pkg
maybeFixPackageName.newName
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.testVariantOf
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.err
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.forTest
golistState.resolveImport.sourceDir
commonDir.RangeStmt_14166.f
commonDir.RangeStmt_14336.k
maybeFixPackageName.names
golistState.processGolistOverlay.RangeStmt_956.pkg
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.RangeStmt_7080.BlockStmt.BlockStmt.err
golistState.resolveImport.err
golistState.resolveImport.BlockStmt.vendorDir
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.BlockStmt.BlockStmt.BlockStmt.RangeStmt_6463.v
golistState.processGolistOverlay.RangeStmt_8684.pkg
golistState.resolveImport.BlockStmt.BlockStmt.BlockStmt.path
maybeFixPackageName
replaceVendor.i
parser
golistState.processGolistOverlay.RangeStmt_8059.BlockStmt.RangeStmt_8104.BlockStmt.pkgPath
golistState.determineRootDirsGOPATH.RangeStmt_12086.BlockStmt.err
commonDir
extractPackageName.f
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.base
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.RangeStmt_3110.BlockStmt.RangeStmt_3234.f
golistState.processGolistOverlay.RangeStmt_8059.BlockStmt.RangeStmt_8104.BlockStmt.err
golistState.determineRootDirsGOPATH.m
golistState.processGolistOverlay.RangeStmt_8059.BlockStmt.RangeStmt_8104.imp
replaceVendor
replaceVendor.repl
golistState.processGolistOverlay.needPkgs
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.dir
golistState.resolveImport.BlockStmt.BlockStmt.info
maybeFixPackageName.RangeStmt_15054.k
extractPackageName.filename
commonDir.seen
golistState.processGolistOverlay.RangeStmt_2321.opath
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.id
golistState.resolveImport.BlockStmt.BlockStmt.err
extractPackageName
golistState.processGolistOverlay.modifiedPkgs
golistState.processGolistOverlay.RangeStmt_2321.BlockStmt.BlockStmt.isXTest
golistState.processGolistOverlay.RangeStmt_8059.pkg
golistState.resolveImport.state
Members
X