mirror of
https://github.com/golang/go
synced 2024-11-18 14:44:41 -07:00
internal/imports: return non-stdlib candidates from GetAllCandidates
Scan most sources, including GOPATH, the module cache, the main module, and replace targets as appropriate. Use the cached stdlib instead of scanning GOROOT. We heavily cache the contents of the module cache, so performance is decent. But we have to look at all the modules not in the module cache too to get the right versions of modules (see (*ModuleResolver).canonicalize), which currently isn't cached at all, even just for a single run. That ends up being pretty expensive. The implementation changes are relatively small; add package name loading to scan(), cache that result, and allow callers to control what directories are scanned so that it can skip GOROOT. I also cleared out most of the stdlib from the unimported completion test and added a simple external completion to it for safety's sake. Change-Id: Id50fd4703b1126be35a000fe90719e19c3ab84bf Reviewed-on: https://go-review.googlesource.com/c/tools/+/199178 Run-TryBot: Heschi Kreinick <heschi@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
44c9a601ac
commit
eb46839a96
@ -586,18 +586,20 @@ func getFixes(fset *token.FileSet, f *ast.File, filename string, env *ProcessEnv
|
|||||||
|
|
||||||
// getAllCandidates gets all of the candidates to be imported, regardless of if they are needed.
|
// getAllCandidates gets all of the candidates to be imported, regardless of if they are needed.
|
||||||
func getAllCandidates(filename string, env *ProcessEnv) ([]ImportFix, error) {
|
func getAllCandidates(filename string, env *ProcessEnv) ([]ImportFix, error) {
|
||||||
// TODO(suzmue): scan for additional candidates and filter out
|
// TODO(heschi): filter out current package. (Don't forget x_test can import x.)
|
||||||
// current package.
|
|
||||||
|
|
||||||
// Get the stdlib candidates and sort by import path.
|
// Exclude goroot results -- getting them is relatively expensive, not cached,
|
||||||
var paths []string
|
// and generally redundant with the in-memory version.
|
||||||
for importPath := range stdlib {
|
exclude := []gopathwalk.RootType{gopathwalk.RootGOROOT}
|
||||||
paths = append(paths, importPath)
|
// Only the go/packages resolver uses the first argument, and nobody uses that resolver.
|
||||||
|
pkgs, err := env.GetResolver().scan(nil, true, exclude)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
sort.Strings(paths)
|
|
||||||
|
|
||||||
|
// Start off with the standard library.
|
||||||
var imports []ImportFix
|
var imports []ImportFix
|
||||||
for _, importPath := range paths {
|
for importPath := range stdlib {
|
||||||
imports = append(imports, ImportFix{
|
imports = append(imports, ImportFix{
|
||||||
StmtInfo: ImportInfo{
|
StmtInfo: ImportInfo{
|
||||||
ImportPath: importPath,
|
ImportPath: importPath,
|
||||||
@ -606,6 +608,27 @@ func getAllCandidates(filename string, env *ProcessEnv) ([]ImportFix, error) {
|
|||||||
FixType: AddImport,
|
FixType: AddImport,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dupCheck := map[string]struct{}{}
|
||||||
|
for _, pkg := range pkgs {
|
||||||
|
if !canUse(filename, pkg.dir) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if _, ok := dupCheck[pkg.importPathShort]; ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
dupCheck[pkg.importPathShort] = struct{}{}
|
||||||
|
imports = append(imports, ImportFix{
|
||||||
|
StmtInfo: ImportInfo{
|
||||||
|
ImportPath: pkg.importPathShort,
|
||||||
|
},
|
||||||
|
IdentName: pkg.packageName,
|
||||||
|
FixType: AddImport,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
sort.Slice(imports, func(i int, j int) bool {
|
||||||
|
return imports[i].StmtInfo.ImportPath < imports[j].StmtInfo.ImportPath
|
||||||
|
})
|
||||||
return imports, nil
|
return imports, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -736,8 +759,10 @@ func addStdlibCandidates(pass *pass, refs references) {
|
|||||||
type Resolver interface {
|
type Resolver interface {
|
||||||
// loadPackageNames loads the package names in importPaths.
|
// loadPackageNames loads the package names in importPaths.
|
||||||
loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
|
loadPackageNames(importPaths []string, srcDir string) (map[string]string, error)
|
||||||
// scan finds (at least) the packages satisfying refs. The returned slice is unordered.
|
// scan finds (at least) the packages satisfying refs. If loadNames is true,
|
||||||
scan(refs references) ([]*pkg, error)
|
// package names will be set on the results, and dirs whose package name
|
||||||
|
// could not be determined will be excluded.
|
||||||
|
scan(refs references, loadNames bool, exclude []gopathwalk.RootType) ([]*pkg, error)
|
||||||
// loadExports returns the set of exported symbols in the package at dir.
|
// loadExports returns the set of exported symbols in the package at dir.
|
||||||
// It returns an error if the package name in dir does not match expectPackage.
|
// It returns an error if the package name in dir does not match expectPackage.
|
||||||
// loadExports may be called concurrently.
|
// loadExports may be called concurrently.
|
||||||
@ -773,7 +798,7 @@ func (r *goPackagesResolver) loadPackageNames(importPaths []string, srcDir strin
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *goPackagesResolver) scan(refs references) ([]*pkg, error) {
|
func (r *goPackagesResolver) scan(refs references, _ bool, _ []gopathwalk.RootType) ([]*pkg, error) {
|
||||||
var loadQueries []string
|
var loadQueries []string
|
||||||
for pkgName := range refs {
|
for pkgName := range refs {
|
||||||
loadQueries = append(loadQueries, "iamashamedtousethedisabledqueryname="+pkgName)
|
loadQueries = append(loadQueries, "iamashamedtousethedisabledqueryname="+pkgName)
|
||||||
@ -791,6 +816,7 @@ func (r *goPackagesResolver) scan(refs references) ([]*pkg, error) {
|
|||||||
dir: filepath.Dir(goPackage.CompiledGoFiles[0]),
|
dir: filepath.Dir(goPackage.CompiledGoFiles[0]),
|
||||||
importPathShort: VendorlessPath(goPackage.PkgPath),
|
importPathShort: VendorlessPath(goPackage.PkgPath),
|
||||||
goPackage: goPackage,
|
goPackage: goPackage,
|
||||||
|
packageName: goPackage.Name,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return scan, nil
|
return scan, nil
|
||||||
@ -817,7 +843,7 @@ func (r *goPackagesResolver) loadExports(ctx context.Context, expectPackage stri
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addExternalCandidates(pass *pass, refs references, filename string) error {
|
func addExternalCandidates(pass *pass, refs references, filename string) error {
|
||||||
dirScan, err := pass.env.GetResolver().scan(refs)
|
dirScan, err := pass.env.GetResolver().scan(refs, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -1001,6 +1027,7 @@ type pkg struct {
|
|||||||
goPackage *packages.Package
|
goPackage *packages.Package
|
||||||
dir string // absolute file path to pkg directory ("/usr/lib/go/src/net/http")
|
dir string // absolute file path to pkg directory ("/usr/lib/go/src/net/http")
|
||||||
importPathShort string // vendorless import path ("net/http", "a/b")
|
importPathShort string // vendorless import path ("net/http", "a/b")
|
||||||
|
packageName string // package name loaded from source if requested
|
||||||
}
|
}
|
||||||
|
|
||||||
type pkgDistance struct {
|
type pkgDistance struct {
|
||||||
@ -1044,7 +1071,7 @@ func distance(basepath, targetpath string) int {
|
|||||||
return strings.Count(p, string(filepath.Separator)) + 1
|
return strings.Count(p, string(filepath.Separator)) + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *gopathResolver) scan(_ references) ([]*pkg, error) {
|
func (r *gopathResolver) scan(_ references, loadNames bool, exclude []gopathwalk.RootType) ([]*pkg, error) {
|
||||||
dupCheck := make(map[string]bool)
|
dupCheck := make(map[string]bool)
|
||||||
var result []*pkg
|
var result []*pkg
|
||||||
|
|
||||||
@ -1059,15 +1086,38 @@ func (r *gopathResolver) scan(_ references) ([]*pkg, error) {
|
|||||||
}
|
}
|
||||||
dupCheck[dir] = true
|
dupCheck[dir] = true
|
||||||
importpath := filepath.ToSlash(dir[len(root.Path)+len("/"):])
|
importpath := filepath.ToSlash(dir[len(root.Path)+len("/"):])
|
||||||
result = append(result, &pkg{
|
p := &pkg{
|
||||||
importPathShort: VendorlessPath(importpath),
|
importPathShort: VendorlessPath(importpath),
|
||||||
dir: dir,
|
dir: dir,
|
||||||
})
|
}
|
||||||
|
if loadNames {
|
||||||
|
var err error
|
||||||
|
p.packageName, err = packageDirToName(dir)
|
||||||
|
if err != nil {
|
||||||
|
return // Typically an unimportable package like main.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = append(result, p)
|
||||||
}
|
}
|
||||||
gopathwalk.Walk(gopathwalk.SrcDirsRoots(r.env.buildContext()), add, gopathwalk.Options{Debug: r.env.Debug, ModulesEnabled: false})
|
roots := filterRoots(gopathwalk.SrcDirsRoots(r.env.buildContext()), exclude)
|
||||||
|
gopathwalk.Walk(roots, add, gopathwalk.Options{Debug: r.env.Debug, ModulesEnabled: false})
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterRoots(roots []gopathwalk.Root, exclude []gopathwalk.RootType) []gopathwalk.Root {
|
||||||
|
var result []gopathwalk.Root
|
||||||
|
outer:
|
||||||
|
for _, root := range roots {
|
||||||
|
for _, i := range exclude {
|
||||||
|
if i == root.Type {
|
||||||
|
continue outer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = append(result, root)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
func (r *gopathResolver) loadExports(ctx context.Context, expectPackage string, pkg *pkg) (map[string]bool, error) {
|
func (r *gopathResolver) loadExports(ctx context.Context, expectPackage string, pkg *pkg) (map[string]bool, error) {
|
||||||
return loadExportsFromFiles(ctx, r.env, expectPackage, pkg.dir)
|
return loadExportsFromFiles(ctx, r.env, expectPackage, pkg.dir)
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"reflect"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@ -2513,33 +2514,48 @@ var _ = bytes.Buffer{}
|
|||||||
|
|
||||||
// TestStdLibGetCandidates tests that get packages finds std library packages
|
// TestStdLibGetCandidates tests that get packages finds std library packages
|
||||||
// with correct priorities.
|
// with correct priorities.
|
||||||
func TestStdLibGetCandidates(t *testing.T) {
|
func TestGetCandidates(t *testing.T) {
|
||||||
want := []struct {
|
type res struct {
|
||||||
wantName string
|
name, path string
|
||||||
wantPkg string
|
}
|
||||||
}{
|
want := []res{
|
||||||
|
{"bar", "bar.com/bar"},
|
||||||
{"bytes", "bytes"},
|
{"bytes", "bytes"},
|
||||||
{"rand", "crypto/rand"},
|
{"rand", "crypto/rand"},
|
||||||
|
{"foo", "foo.com/foo"},
|
||||||
{"rand", "math/rand"},
|
{"rand", "math/rand"},
|
||||||
{"http", "net/http"},
|
{"http", "net/http"},
|
||||||
}
|
}
|
||||||
|
|
||||||
got, err := GetAllCandidates("", nil)
|
testConfig{
|
||||||
if err != nil {
|
modules: []packagestest.Module{
|
||||||
t.Fatalf("Process() = %v", err)
|
{
|
||||||
}
|
Name: "foo.com",
|
||||||
wantIdx := 0
|
Files: fm{"foo/foo.go": "package foo\n"},
|
||||||
for _, fix := range got {
|
},
|
||||||
if wantIdx >= len(want) {
|
{
|
||||||
break
|
Name: "bar.com",
|
||||||
|
Files: fm{"bar/bar.go": "package bar\n"},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
goPackagesIncompatible: true, // getAllCandidates doesn't support the go/packages resolver.
|
||||||
|
}.test(t, func(t *goimportTest) {
|
||||||
|
candidates, err := getAllCandidates("x.go", t.env)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GetAllCandidates() = %v", err)
|
||||||
}
|
}
|
||||||
if want[wantIdx].wantName == fix.IdentName && want[wantIdx].wantPkg == fix.StmtInfo.ImportPath && "" == fix.StmtInfo.Name {
|
var got []res
|
||||||
wantIdx++
|
for _, c := range candidates {
|
||||||
|
for _, w := range want {
|
||||||
|
if c.StmtInfo.ImportPath == w.path {
|
||||||
|
got = append(got, res{c.IdentName, c.StmtInfo.ImportPath})
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
if !reflect.DeepEqual(want, got) {
|
||||||
if wantIdx < len(want) {
|
t.Errorf("wanted stdlib results in order %v, got %v", want, got)
|
||||||
t.Errorf("expected to find candidate with path: %q, name: %q next in ordered scan of results`", want[wantIdx].wantPkg, want[wantIdx].wantName)
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests #34895: process should not panic on concurrent calls.
|
// Tests #34895: process should not panic on concurrent calls.
|
||||||
|
@ -119,14 +119,19 @@ func (r *ModuleResolver) findPackage(importPath string) (*ModuleJSON, string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if info, ok := r.moduleCacheInfo.Load(pkgDir); ok {
|
if info, ok := r.moduleCacheInfo.Load(pkgDir); ok {
|
||||||
if packageScanned, err := info.reachedStatus(directoryScanned); packageScanned {
|
// This is slightly wrong: a directory doesn't have to have an
|
||||||
|
// importable package to count as a package for package-to-module
|
||||||
|
// resolution. package main or _test files should count but
|
||||||
|
// don't.
|
||||||
|
if loaded, err := info.reachedStatus(nameLoaded); loaded {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// There was some error with scanning this directory.
|
continue // No package in this dir.
|
||||||
// It does not contain a valid package.
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
return m, pkgDir
|
return m, pkgDir
|
||||||
}
|
}
|
||||||
|
if scanned, err := info.reachedStatus(directoryScanned); scanned && err != nil {
|
||||||
|
continue // Dir is unreadable, etc.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pkgFiles, err := ioutil.ReadDir(pkgDir)
|
pkgFiles, err := ioutil.ReadDir(pkgDir)
|
||||||
@ -237,7 +242,7 @@ func (r *ModuleResolver) loadPackageNames(importPaths []string, srcDir string) (
|
|||||||
return names, nil
|
return names, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ModuleResolver) scan(_ references) ([]*pkg, error) {
|
func (r *ModuleResolver) scan(_ references, loadNames bool, exclude []gopathwalk.RootType) ([]*pkg, error) {
|
||||||
if err := r.init(); err != nil {
|
if err := r.init(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -261,6 +266,8 @@ func (r *ModuleResolver) scan(_ references) ([]*pkg, error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
roots = filterRoots(roots, exclude)
|
||||||
|
|
||||||
var result []*pkg
|
var result []*pkg
|
||||||
dupCheck := make(map[string]bool)
|
dupCheck := make(map[string]bool)
|
||||||
var mu sync.Mutex
|
var mu sync.Mutex
|
||||||
@ -311,9 +318,16 @@ func (r *ModuleResolver) scan(_ references) ([]*pkg, error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if loadNames {
|
||||||
|
info.packageName, info.err = packageDirToName(dir)
|
||||||
|
if info.err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The rest of this function canonicalizes the packages using the results
|
// The rest of this function canonicalizes the packages using the results
|
||||||
// of initializing the resolver from 'go list -m'.
|
// of initializing the resolver from 'go list -m'.
|
||||||
res, err := r.canonicalize(root.Type, info.nonCanonicalImportPath, info.dir, info.needsReplace)
|
res, err := r.canonicalize(root.Type, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -335,7 +349,23 @@ func (r *ModuleResolver) scan(_ references) ([]*pkg, error) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
res, err := r.canonicalize(gopathwalk.RootModuleCache, info.nonCanonicalImportPath, info.dir, info.needsReplace)
|
// If we want package names, make sure the cache has them.
|
||||||
|
if loadNames {
|
||||||
|
loaded, err := info.reachedStatus(nameLoaded)
|
||||||
|
if loaded && err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if !loaded {
|
||||||
|
info.packageName, info.err = packageDirToName(info.dir)
|
||||||
|
info.status = nameLoaded
|
||||||
|
r.moduleCacheInfo.Store(info.dir, info)
|
||||||
|
if info.err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
res, err := r.canonicalize(gopathwalk.RootModuleCache, info)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -347,38 +377,42 @@ func (r *ModuleResolver) scan(_ references) ([]*pkg, error) {
|
|||||||
|
|
||||||
// canonicalize gets the result of canonicalizing the packages using the results
|
// canonicalize gets the result of canonicalizing the packages using the results
|
||||||
// of initializing the resolver from 'go list -m'.
|
// of initializing the resolver from 'go list -m'.
|
||||||
func (r *ModuleResolver) canonicalize(rootType gopathwalk.RootType, importPath, dir string, needsReplace bool) (res *pkg, err error) {
|
func (r *ModuleResolver) canonicalize(rootType gopathwalk.RootType, info directoryPackageInfo) (*pkg, error) {
|
||||||
// Packages in GOROOT are already canonical, regardless of the std/cmd modules.
|
// Packages in GOROOT are already canonical, regardless of the std/cmd modules.
|
||||||
if rootType == gopathwalk.RootGOROOT {
|
if rootType == gopathwalk.RootGOROOT {
|
||||||
return &pkg{
|
return &pkg{
|
||||||
importPathShort: importPath,
|
importPathShort: info.nonCanonicalImportPath,
|
||||||
dir: dir,
|
dir: info.dir,
|
||||||
|
packageName: path.Base(info.nonCanonicalImportPath),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
importPath := info.nonCanonicalImportPath
|
||||||
// Check if the directory is underneath a module that's in scope.
|
// Check if the directory is underneath a module that's in scope.
|
||||||
if mod := r.findModuleByDir(dir); mod != nil {
|
if mod := r.findModuleByDir(info.dir); mod != nil {
|
||||||
// It is. If dir is the target of a replace directive,
|
// It is. If dir is the target of a replace directive,
|
||||||
// our guessed import path is wrong. Use the real one.
|
// our guessed import path is wrong. Use the real one.
|
||||||
if mod.Dir == dir {
|
if mod.Dir == info.dir {
|
||||||
importPath = mod.Path
|
importPath = mod.Path
|
||||||
} else {
|
} else {
|
||||||
dirInMod := dir[len(mod.Dir)+len("/"):]
|
dirInMod := info.dir[len(mod.Dir)+len("/"):]
|
||||||
importPath = path.Join(mod.Path, filepath.ToSlash(dirInMod))
|
importPath = path.Join(mod.Path, filepath.ToSlash(dirInMod))
|
||||||
}
|
}
|
||||||
} else if needsReplace {
|
} else if info.needsReplace {
|
||||||
return nil, fmt.Errorf("needed this package to be in scope: %s", dir)
|
return nil, fmt.Errorf("package in %q is not valid without a replace statement", info.dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
res := &pkg{
|
||||||
|
importPathShort: VendorlessPath(importPath),
|
||||||
|
dir: info.dir,
|
||||||
|
packageName: info.packageName, // may not be populated if the caller didn't ask for it
|
||||||
|
}
|
||||||
// We may have discovered a package that has a different version
|
// We may have discovered a package that has a different version
|
||||||
// in scope already. Canonicalize to that one if possible.
|
// in scope already. Canonicalize to that one if possible.
|
||||||
if _, canonicalDir := r.findPackage(importPath); canonicalDir != "" {
|
if _, canonicalDir := r.findPackage(importPath); canonicalDir != "" {
|
||||||
dir = canonicalDir
|
res.dir = canonicalDir
|
||||||
}
|
}
|
||||||
return &pkg{
|
return res, nil
|
||||||
importPathShort: VendorlessPath(importPath),
|
|
||||||
dir: dir,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ModuleResolver) loadExports(ctx context.Context, expectPackage string, pkg *pkg) (map[string]bool, error) {
|
func (r *ModuleResolver) loadExports(ctx context.Context, expectPackage string, pkg *pkg) (map[string]bool, error) {
|
||||||
|
@ -30,6 +30,7 @@ type directoryPackageStatus int
|
|||||||
const (
|
const (
|
||||||
_ directoryPackageStatus = iota
|
_ directoryPackageStatus = iota
|
||||||
directoryScanned
|
directoryScanned
|
||||||
|
nameLoaded
|
||||||
)
|
)
|
||||||
|
|
||||||
type directoryPackageInfo struct {
|
type directoryPackageInfo struct {
|
||||||
@ -38,7 +39,7 @@ type directoryPackageInfo struct {
|
|||||||
// err is non-nil when there was an error trying to reach status.
|
// err is non-nil when there was an error trying to reach status.
|
||||||
err error
|
err error
|
||||||
|
|
||||||
// Set when status > directoryScanned.
|
// Set when status >= directoryScanned.
|
||||||
|
|
||||||
// dir is the absolute directory of this package.
|
// dir is the absolute directory of this package.
|
||||||
dir string
|
dir string
|
||||||
@ -49,6 +50,10 @@ type directoryPackageInfo struct {
|
|||||||
// the modules declared path, making it impossible to import without a
|
// the modules declared path, making it impossible to import without a
|
||||||
// replace directive.
|
// replace directive.
|
||||||
needsReplace bool
|
needsReplace bool
|
||||||
|
|
||||||
|
// Set when status >= nameLoaded.
|
||||||
|
|
||||||
|
packageName string // the package name, as declared in the source.
|
||||||
}
|
}
|
||||||
|
|
||||||
// reachedStatus returns true when info has a status at least target and any error associated with
|
// reachedStatus returns true when info has a status at least target and any error associated with
|
||||||
@ -90,13 +95,8 @@ type moduleCacheInfo struct {
|
|||||||
func (d *moduleCacheInfo) Store(dir string, info directoryPackageInfo) {
|
func (d *moduleCacheInfo) Store(dir string, info directoryPackageInfo) {
|
||||||
d.mu.Lock()
|
d.mu.Lock()
|
||||||
defer d.mu.Unlock()
|
defer d.mu.Unlock()
|
||||||
d.modCacheDirInfo[dir] = &directoryPackageInfo{
|
stored := info // defensive copy
|
||||||
status: info.status,
|
d.modCacheDirInfo[dir] = &stored
|
||||||
err: info.err,
|
|
||||||
dir: info.dir,
|
|
||||||
nonCanonicalImportPath: info.nonCanonicalImportPath,
|
|
||||||
needsReplace: info.needsReplace,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load returns a copy of the directoryPackageInfo for absolute directory dir.
|
// Load returns a copy of the directoryPackageInfo for absolute directory dir.
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
@ -14,6 +15,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/gopathwalk"
|
||||||
"golang.org/x/tools/internal/module"
|
"golang.org/x/tools/internal/module"
|
||||||
"golang.org/x/tools/internal/testenv"
|
"golang.org/x/tools/internal/testenv"
|
||||||
"golang.org/x/tools/internal/txtar"
|
"golang.org/x/tools/internal/txtar"
|
||||||
@ -86,7 +88,7 @@ package z
|
|||||||
|
|
||||||
mt.assertFound("y", "y")
|
mt.assertFound("y", "y")
|
||||||
|
|
||||||
scan, err := mt.resolver.scan(nil)
|
scan, err := mt.resolver.scan(nil, false, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -164,8 +166,8 @@ import _ "rsc.io/quote"
|
|||||||
`, "")
|
`, "")
|
||||||
defer mt.cleanup()
|
defer mt.cleanup()
|
||||||
|
|
||||||
mt.assertScanFinds("rsc.io/quote/buggy", "buggy")
|
mt.assertScanFinds("rsc.io/quote", "quote")
|
||||||
mt.assertScanFinds("rsc.io/quote/buggy", "buggy")
|
mt.assertScanFinds("rsc.io/quote", "quote")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that scanning the module cache > 1 after changing a package in module cache to make it unimportable
|
// Tests that scanning the module cache > 1 after changing a package in module cache to make it unimportable
|
||||||
@ -215,7 +217,7 @@ import _ "rsc.io/quote"
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Tests that -mod=vendor sort of works. Adapted from mod_getmode_vendor.txt.
|
// Tests that -mod=vendor sort of works. Adapted from mod_getmode_vendor.txt.
|
||||||
func TestModeGetmodeVendor(t *testing.T) {
|
func TestModGetmodeVendor(t *testing.T) {
|
||||||
t.Skip("'go list -m -mod=vendor' currently not allowed: see golang.org/issue/34826")
|
t.Skip("'go list -m -mod=vendor' currently not allowed: see golang.org/issue/34826")
|
||||||
mt := setup(t, `
|
mt := setup(t, `
|
||||||
-- go.mod --
|
-- go.mod --
|
||||||
@ -540,7 +542,7 @@ func (t *modTest) assertFound(importPath, pkgName string) (string, *pkg) {
|
|||||||
|
|
||||||
func (t *modTest) assertScanFinds(importPath, pkgName string) *pkg {
|
func (t *modTest) assertScanFinds(importPath, pkgName string) *pkg {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
scan, err := t.resolver.scan(nil)
|
scan, err := t.resolver.scan(nil, true, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("scan failed: %v", err)
|
t.Errorf("scan failed: %v", err)
|
||||||
}
|
}
|
||||||
@ -795,5 +797,20 @@ func TestInvalidModCache(t *testing.T) {
|
|||||||
WorkingDir: dir,
|
WorkingDir: dir,
|
||||||
}
|
}
|
||||||
resolver := &ModuleResolver{env: env}
|
resolver := &ModuleResolver{env: env}
|
||||||
resolver.scan(nil)
|
resolver.scan(nil, true, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkScanModCache(b *testing.B) {
|
||||||
|
env := &ProcessEnv{
|
||||||
|
Debug: true,
|
||||||
|
GOPATH: build.Default.GOPATH,
|
||||||
|
GOROOT: build.Default.GOROOT,
|
||||||
|
Logf: log.Printf,
|
||||||
|
}
|
||||||
|
exclude := []gopathwalk.RootType{gopathwalk.RootCurrentModule, gopathwalk.RootGOROOT, gopathwalk.RootOther}
|
||||||
|
env.GetResolver().scan(nil, true, exclude)
|
||||||
|
b.ResetTimer()
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
env.GetResolver().scan(nil, true, exclude)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
1
internal/lsp/cache/view.go
vendored
1
internal/lsp/cache/view.go
vendored
@ -173,6 +173,7 @@ func (v *view) buildProcessEnv(ctx context.Context) (*imports.ProcessEnv, error)
|
|||||||
Logf: func(format string, args ...interface{}) {
|
Logf: func(format string, args ...interface{}) {
|
||||||
log.Print(ctx, fmt.Sprintf(format, args...))
|
log.Print(ctx, fmt.Sprintf(format, args...))
|
||||||
},
|
},
|
||||||
|
Debug: true,
|
||||||
}
|
}
|
||||||
for _, kv := range cfg.Env {
|
for _, kv := range cfg.Env {
|
||||||
split := strings.Split(kv, "=")
|
split := strings.Split(kv, "=")
|
||||||
|
@ -51,7 +51,7 @@ func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Co
|
|||||||
got = tests.FilterBuiltins(got)
|
got = tests.FilterBuiltins(got)
|
||||||
}
|
}
|
||||||
want := expected(t, test, items)
|
want := expected(t, test, items)
|
||||||
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
if diff := tests.CheckCompletionOrder(want, got); diff != "" {
|
||||||
t.Errorf("%s: %s", src, diff)
|
t.Errorf("%s: %s", src, diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -136,7 +136,7 @@ func (r *runner) UnimportedCompletion(t *testing.T, src span.Span, test tests.Co
|
|||||||
if !strings.Contains(string(src.URI()), "builtins") {
|
if !strings.Contains(string(src.URI()), "builtins") {
|
||||||
got = tests.FilterBuiltins(got)
|
got = tests.FilterBuiltins(got)
|
||||||
}
|
}
|
||||||
if diff := tests.DiffCompletionItems(want, got); diff != "" {
|
if diff := tests.CheckCompletionOrder(want, got); diff != "" {
|
||||||
t.Errorf("%s: %s", src, diff)
|
t.Errorf("%s: %s", src, diff)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
112
internal/lsp/testdata/unimported/mkunimported.go
vendored
112
internal/lsp/testdata/unimported/mkunimported.go
vendored
@ -1,112 +0,0 @@
|
|||||||
// +build ignore
|
|
||||||
|
|
||||||
// mkunimported generates the unimported.go file, containing the Go standard
|
|
||||||
// library packages.
|
|
||||||
// The completion items from the std library are computed in the same way as in the
|
|
||||||
// golang.org/x/tools/internal/imports.
|
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bufio"
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"go/format"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
pkgpath "path"
|
|
||||||
"path/filepath"
|
|
||||||
"regexp"
|
|
||||||
"runtime"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
func mustOpen(name string) io.Reader {
|
|
||||||
f, err := os.Open(name)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func api(base string) string {
|
|
||||||
return filepath.Join(runtime.GOROOT(), "api", base)
|
|
||||||
}
|
|
||||||
|
|
||||||
var sym = regexp.MustCompile(`^pkg (\S+).*?, (?:var|func|type|const) ([A-Z]\w*)`)
|
|
||||||
|
|
||||||
var unsafeSyms = map[string]bool{"Alignof": true, "ArbitraryType": true, "Offsetof": true, "Pointer": true, "Sizeof": true}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
var buf bytes.Buffer
|
|
||||||
outf := func(format string, args ...interface{}) {
|
|
||||||
fmt.Fprintf(&buf, format, args...)
|
|
||||||
}
|
|
||||||
outf("// Code generated by mkstdlib.go. DO NOT EDIT.\n\n")
|
|
||||||
outf("package unimported\n")
|
|
||||||
outf("func _() {\n")
|
|
||||||
f := io.MultiReader(
|
|
||||||
mustOpen(api("go1.txt")),
|
|
||||||
mustOpen(api("go1.1.txt")),
|
|
||||||
mustOpen(api("go1.2.txt")),
|
|
||||||
mustOpen(api("go1.3.txt")),
|
|
||||||
mustOpen(api("go1.4.txt")),
|
|
||||||
mustOpen(api("go1.5.txt")),
|
|
||||||
mustOpen(api("go1.6.txt")),
|
|
||||||
mustOpen(api("go1.7.txt")),
|
|
||||||
mustOpen(api("go1.8.txt")),
|
|
||||||
mustOpen(api("go1.9.txt")),
|
|
||||||
mustOpen(api("go1.10.txt")),
|
|
||||||
mustOpen(api("go1.11.txt")),
|
|
||||||
mustOpen(api("go1.12.txt")),
|
|
||||||
mustOpen(api("go1.13.txt")),
|
|
||||||
)
|
|
||||||
sc := bufio.NewScanner(f)
|
|
||||||
|
|
||||||
pkgs := map[string]bool{
|
|
||||||
"unsafe": true,
|
|
||||||
"syscall/js": true,
|
|
||||||
}
|
|
||||||
paths := []string{"unsafe", "syscall/js"}
|
|
||||||
for sc.Scan() {
|
|
||||||
l := sc.Text()
|
|
||||||
if m := sym.FindStringSubmatch(l); m != nil {
|
|
||||||
path, _ := m[1], m[2]
|
|
||||||
|
|
||||||
if _, ok := pkgs[path]; !ok {
|
|
||||||
pkgs[path] = true
|
|
||||||
paths = append(paths, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err := sc.Err(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
sort.Strings(paths)
|
|
||||||
|
|
||||||
var markers []string
|
|
||||||
for _, path := range paths {
|
|
||||||
marker := strings.ReplaceAll(path, "/", "slash")
|
|
||||||
markers = append(markers, marker)
|
|
||||||
}
|
|
||||||
outf(" //@unimported(\"\", %s)\n", strings.Join(markers, ", "))
|
|
||||||
outf("}\n")
|
|
||||||
outf("// Create markers for unimported std lib packages. Only for use by this test.\n")
|
|
||||||
|
|
||||||
for i, path := range paths {
|
|
||||||
name := pkgpath.Base(path)
|
|
||||||
marker := markers[i]
|
|
||||||
outf("/* %s *///@item(%s, \"%s\", \"\\\"%s\\\"\", \"package\")\n", name, marker, name, path)
|
|
||||||
}
|
|
||||||
|
|
||||||
fmtbuf, err := format.Source(buf.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
err = ioutil.WriteFile("unimported.go", fmtbuf, 0666)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
145
internal/lsp/testdata/unimported/unimported.go
vendored
145
internal/lsp/testdata/unimported/unimported.go
vendored
@ -1,152 +1,13 @@
|
|||||||
// Code generated by mkstdlib.go. DO NOT EDIT.
|
|
||||||
|
|
||||||
package unimported
|
package unimported
|
||||||
|
|
||||||
func _() {
|
func _() {
|
||||||
//@unimported("", archiveslashtar, archiveslashzip, bufio, bytes, compressslashbzip2, compressslashflate, compressslashgzip, compressslashlzw, compressslashzlib, containerslashheap, containerslashlist, containerslashring, context, crypto, cryptoslashaes, cryptoslashcipher, cryptoslashdes, cryptoslashdsa, cryptoslashecdsa, cryptoslashed25519, cryptoslashelliptic, cryptoslashhmac, cryptoslashmd5, cryptoslashrand, cryptoslashrc4, cryptoslashrsa, cryptoslashsha1, cryptoslashsha256, cryptoslashsha512, cryptoslashsubtle, cryptoslashtls, cryptoslashx509, cryptoslashx509slashpkix, databaseslashsql, databaseslashsqlslashdriver, debugslashdwarf, debugslashelf, debugslashgosym, debugslashmacho, debugslashpe, debugslashplan9obj, encoding, encodingslashascii85, encodingslashasn1, encodingslashbase32, encodingslashbase64, encodingslashbinary, encodingslashcsv, encodingslashgob, encodingslashhex, encodingslashjson, encodingslashpem, encodingslashxml, errors, expvar, flag, fmt, goslashast, goslashbuild, goslashconstant, goslashdoc, goslashformat, goslashimporter, goslashparser, goslashprinter, goslashscanner, goslashtoken, goslashtypes, hash, hashslashadler32, hashslashcrc32, hashslashcrc64, hashslashfnv, html, htmlslashtemplate, image, imageslashcolor, imageslashcolorslashpalette, imageslashdraw, imageslashgif, imageslashjpeg, imageslashpng, indexslashsuffixarray, io, ioslashioutil, log, logslashsyslog, math, mathslashbig, mathslashbits, mathslashcmplx, mathslashrand, mime, mimeslashmultipart, mimeslashquotedprintable, net, netslashhttp, netslashhttpslashcgi, netslashhttpslashcookiejar, netslashhttpslashfcgi, netslashhttpslashhttptest, netslashhttpslashhttptrace, netslashhttpslashhttputil, netslashhttpslashpprof, netslashmail, netslashrpc, netslashrpcslashjsonrpc, netslashsmtp, netslashtextproto, netslashurl, os, osslashexec, osslashsignal, osslashuser, path, pathslashfilepath, plugin, reflect, regexp, regexpslashsyntax, runtime, runtimeslashdebug, runtimeslashpprof, runtimeslashtrace, sort, strconv, strings, sync, syncslashatomic, syscall, syscallslashjs, testing, testingslashiotest, testingslashquick, textslashscanner, textslashtabwriter, textslashtemplate, textslashtemplateslashparse, time, unicode, unicodeslashutf16, unicodeslashutf8, unsafe)
|
//@unimported("", bytes, context, cryptoslashrand, externalpackage, time, unsafe)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create markers for unimported std lib packages. Only for use by this test.
|
// Create markers for unimported std lib packages. Only for use by this test.
|
||||||
/* tar */ //@item(archiveslashtar, "tar", "\"archive/tar\"", "package")
|
|
||||||
/* zip */ //@item(archiveslashzip, "zip", "\"archive/zip\"", "package")
|
|
||||||
/* bufio */ //@item(bufio, "bufio", "\"bufio\"", "package")
|
|
||||||
/* bytes */ //@item(bytes, "bytes", "\"bytes\"", "package")
|
/* bytes */ //@item(bytes, "bytes", "\"bytes\"", "package")
|
||||||
/* bzip2 */ //@item(compressslashbzip2, "bzip2", "\"compress/bzip2\"", "package")
|
|
||||||
/* flate */ //@item(compressslashflate, "flate", "\"compress/flate\"", "package")
|
|
||||||
/* gzip */ //@item(compressslashgzip, "gzip", "\"compress/gzip\"", "package")
|
|
||||||
/* lzw */ //@item(compressslashlzw, "lzw", "\"compress/lzw\"", "package")
|
|
||||||
/* zlib */ //@item(compressslashzlib, "zlib", "\"compress/zlib\"", "package")
|
|
||||||
/* heap */ //@item(containerslashheap, "heap", "\"container/heap\"", "package")
|
|
||||||
/* list */ //@item(containerslashlist, "list", "\"container/list\"", "package")
|
|
||||||
/* ring */ //@item(containerslashring, "ring", "\"container/ring\"", "package")
|
|
||||||
/* context */ //@item(context, "context", "\"context\"", "package")
|
/* context */ //@item(context, "context", "\"context\"", "package")
|
||||||
/* crypto */ //@item(crypto, "crypto", "\"crypto\"", "package")
|
|
||||||
/* aes */ //@item(cryptoslashaes, "aes", "\"crypto/aes\"", "package")
|
|
||||||
/* cipher */ //@item(cryptoslashcipher, "cipher", "\"crypto/cipher\"", "package")
|
|
||||||
/* des */ //@item(cryptoslashdes, "des", "\"crypto/des\"", "package")
|
|
||||||
/* dsa */ //@item(cryptoslashdsa, "dsa", "\"crypto/dsa\"", "package")
|
|
||||||
/* ecdsa */ //@item(cryptoslashecdsa, "ecdsa", "\"crypto/ecdsa\"", "package")
|
|
||||||
/* ed25519 */ //@item(cryptoslashed25519, "ed25519", "\"crypto/ed25519\"", "package")
|
|
||||||
/* elliptic */ //@item(cryptoslashelliptic, "elliptic", "\"crypto/elliptic\"", "package")
|
|
||||||
/* hmac */ //@item(cryptoslashhmac, "hmac", "\"crypto/hmac\"", "package")
|
|
||||||
/* md5 */ //@item(cryptoslashmd5, "md5", "\"crypto/md5\"", "package")
|
|
||||||
/* rand */ //@item(cryptoslashrand, "rand", "\"crypto/rand\"", "package")
|
/* rand */ //@item(cryptoslashrand, "rand", "\"crypto/rand\"", "package")
|
||||||
/* rc4 */ //@item(cryptoslashrc4, "rc4", "\"crypto/rc4\"", "package")
|
/* pkg */ //@item(externalpackage, "pkg", "\"example.com/extramodule/pkg\"", "package" )
|
||||||
/* rsa */ //@item(cryptoslashrsa, "rsa", "\"crypto/rsa\"", "package")
|
|
||||||
/* sha1 */ //@item(cryptoslashsha1, "sha1", "\"crypto/sha1\"", "package")
|
|
||||||
/* sha256 */ //@item(cryptoslashsha256, "sha256", "\"crypto/sha256\"", "package")
|
|
||||||
/* sha512 */ //@item(cryptoslashsha512, "sha512", "\"crypto/sha512\"", "package")
|
|
||||||
/* subtle */ //@item(cryptoslashsubtle, "subtle", "\"crypto/subtle\"", "package")
|
|
||||||
/* tls */ //@item(cryptoslashtls, "tls", "\"crypto/tls\"", "package")
|
|
||||||
/* x509 */ //@item(cryptoslashx509, "x509", "\"crypto/x509\"", "package")
|
|
||||||
/* pkix */ //@item(cryptoslashx509slashpkix, "pkix", "\"crypto/x509/pkix\"", "package")
|
|
||||||
/* sql */ //@item(databaseslashsql, "sql", "\"database/sql\"", "package")
|
|
||||||
/* driver */ //@item(databaseslashsqlslashdriver, "driver", "\"database/sql/driver\"", "package")
|
|
||||||
/* dwarf */ //@item(debugslashdwarf, "dwarf", "\"debug/dwarf\"", "package")
|
|
||||||
/* elf */ //@item(debugslashelf, "elf", "\"debug/elf\"", "package")
|
|
||||||
/* gosym */ //@item(debugslashgosym, "gosym", "\"debug/gosym\"", "package")
|
|
||||||
/* macho */ //@item(debugslashmacho, "macho", "\"debug/macho\"", "package")
|
|
||||||
/* pe */ //@item(debugslashpe, "pe", "\"debug/pe\"", "package")
|
|
||||||
/* plan9obj */ //@item(debugslashplan9obj, "plan9obj", "\"debug/plan9obj\"", "package")
|
|
||||||
/* encoding */ //@item(encoding, "encoding", "\"encoding\"", "package")
|
|
||||||
/* ascii85 */ //@item(encodingslashascii85, "ascii85", "\"encoding/ascii85\"", "package")
|
|
||||||
/* asn1 */ //@item(encodingslashasn1, "asn1", "\"encoding/asn1\"", "package")
|
|
||||||
/* base32 */ //@item(encodingslashbase32, "base32", "\"encoding/base32\"", "package")
|
|
||||||
/* base64 */ //@item(encodingslashbase64, "base64", "\"encoding/base64\"", "package")
|
|
||||||
/* binary */ //@item(encodingslashbinary, "binary", "\"encoding/binary\"", "package")
|
|
||||||
/* csv */ //@item(encodingslashcsv, "csv", "\"encoding/csv\"", "package")
|
|
||||||
/* gob */ //@item(encodingslashgob, "gob", "\"encoding/gob\"", "package")
|
|
||||||
/* hex */ //@item(encodingslashhex, "hex", "\"encoding/hex\"", "package")
|
|
||||||
/* json */ //@item(encodingslashjson, "json", "\"encoding/json\"", "package")
|
|
||||||
/* pem */ //@item(encodingslashpem, "pem", "\"encoding/pem\"", "package")
|
|
||||||
/* xml */ //@item(encodingslashxml, "xml", "\"encoding/xml\"", "package")
|
|
||||||
/* errors */ //@item(errors, "errors", "\"errors\"", "package")
|
|
||||||
/* expvar */ //@item(expvar, "expvar", "\"expvar\"", "package")
|
|
||||||
/* flag */ //@item(flag, "flag", "\"flag\"", "package")
|
|
||||||
/* fmt */ //@item(fmt, "fmt", "\"fmt\"", "package")
|
|
||||||
/* ast */ //@item(goslashast, "ast", "\"go/ast\"", "package")
|
|
||||||
/* build */ //@item(goslashbuild, "build", "\"go/build\"", "package")
|
|
||||||
/* constant */ //@item(goslashconstant, "constant", "\"go/constant\"", "package")
|
|
||||||
/* doc */ //@item(goslashdoc, "doc", "\"go/doc\"", "package")
|
|
||||||
/* format */ //@item(goslashformat, "format", "\"go/format\"", "package")
|
|
||||||
/* importer */ //@item(goslashimporter, "importer", "\"go/importer\"", "package")
|
|
||||||
/* parser */ //@item(goslashparser, "parser", "\"go/parser\"", "package")
|
|
||||||
/* printer */ //@item(goslashprinter, "printer", "\"go/printer\"", "package")
|
|
||||||
/* scanner */ //@item(goslashscanner, "scanner", "\"go/scanner\"", "package")
|
|
||||||
/* token */ //@item(goslashtoken, "token", "\"go/token\"", "package")
|
|
||||||
/* types */ //@item(goslashtypes, "types", "\"go/types\"", "package")
|
|
||||||
/* hash */ //@item(hash, "hash", "\"hash\"", "package")
|
|
||||||
/* adler32 */ //@item(hashslashadler32, "adler32", "\"hash/adler32\"", "package")
|
|
||||||
/* crc32 */ //@item(hashslashcrc32, "crc32", "\"hash/crc32\"", "package")
|
|
||||||
/* crc64 */ //@item(hashslashcrc64, "crc64", "\"hash/crc64\"", "package")
|
|
||||||
/* fnv */ //@item(hashslashfnv, "fnv", "\"hash/fnv\"", "package")
|
|
||||||
/* html */ //@item(html, "html", "\"html\"", "package")
|
|
||||||
/* template */ //@item(htmlslashtemplate, "template", "\"html/template\"", "package")
|
|
||||||
/* image */ //@item(image, "image", "\"image\"", "package")
|
|
||||||
/* color */ //@item(imageslashcolor, "color", "\"image/color\"", "package")
|
|
||||||
/* palette */ //@item(imageslashcolorslashpalette, "palette", "\"image/color/palette\"", "package")
|
|
||||||
/* draw */ //@item(imageslashdraw, "draw", "\"image/draw\"", "package")
|
|
||||||
/* gif */ //@item(imageslashgif, "gif", "\"image/gif\"", "package")
|
|
||||||
/* jpeg */ //@item(imageslashjpeg, "jpeg", "\"image/jpeg\"", "package")
|
|
||||||
/* png */ //@item(imageslashpng, "png", "\"image/png\"", "package")
|
|
||||||
/* suffixarray */ //@item(indexslashsuffixarray, "suffixarray", "\"index/suffixarray\"", "package")
|
|
||||||
/* io */ //@item(io, "io", "\"io\"", "package")
|
|
||||||
/* ioutil */ //@item(ioslashioutil, "ioutil", "\"io/ioutil\"", "package")
|
|
||||||
/* log */ //@item(log, "log", "\"log\"", "package")
|
|
||||||
/* syslog */ //@item(logslashsyslog, "syslog", "\"log/syslog\"", "package")
|
|
||||||
/* math */ //@item(math, "math", "\"math\"", "package")
|
|
||||||
/* big */ //@item(mathslashbig, "big", "\"math/big\"", "package")
|
|
||||||
/* bits */ //@item(mathslashbits, "bits", "\"math/bits\"", "package")
|
|
||||||
/* cmplx */ //@item(mathslashcmplx, "cmplx", "\"math/cmplx\"", "package")
|
|
||||||
/* rand */ //@item(mathslashrand, "rand", "\"math/rand\"", "package")
|
|
||||||
/* mime */ //@item(mime, "mime", "\"mime\"", "package")
|
|
||||||
/* multipart */ //@item(mimeslashmultipart, "multipart", "\"mime/multipart\"", "package")
|
|
||||||
/* quotedprintable */ //@item(mimeslashquotedprintable, "quotedprintable", "\"mime/quotedprintable\"", "package")
|
|
||||||
/* net */ //@item(net, "net", "\"net\"", "package")
|
|
||||||
/* http */ //@item(netslashhttp, "http", "\"net/http\"", "package")
|
|
||||||
/* cgi */ //@item(netslashhttpslashcgi, "cgi", "\"net/http/cgi\"", "package")
|
|
||||||
/* cookiejar */ //@item(netslashhttpslashcookiejar, "cookiejar", "\"net/http/cookiejar\"", "package")
|
|
||||||
/* fcgi */ //@item(netslashhttpslashfcgi, "fcgi", "\"net/http/fcgi\"", "package")
|
|
||||||
/* httptest */ //@item(netslashhttpslashhttptest, "httptest", "\"net/http/httptest\"", "package")
|
|
||||||
/* httptrace */ //@item(netslashhttpslashhttptrace, "httptrace", "\"net/http/httptrace\"", "package")
|
|
||||||
/* httputil */ //@item(netslashhttpslashhttputil, "httputil", "\"net/http/httputil\"", "package")
|
|
||||||
/* pprof */ //@item(netslashhttpslashpprof, "pprof", "\"net/http/pprof\"", "package")
|
|
||||||
/* mail */ //@item(netslashmail, "mail", "\"net/mail\"", "package")
|
|
||||||
/* rpc */ //@item(netslashrpc, "rpc", "\"net/rpc\"", "package")
|
|
||||||
/* jsonrpc */ //@item(netslashrpcslashjsonrpc, "jsonrpc", "\"net/rpc/jsonrpc\"", "package")
|
|
||||||
/* smtp */ //@item(netslashsmtp, "smtp", "\"net/smtp\"", "package")
|
|
||||||
/* textproto */ //@item(netslashtextproto, "textproto", "\"net/textproto\"", "package")
|
|
||||||
/* url */ //@item(netslashurl, "url", "\"net/url\"", "package")
|
|
||||||
/* os */ //@item(os, "os", "\"os\"", "package")
|
|
||||||
/* exec */ //@item(osslashexec, "exec", "\"os/exec\"", "package")
|
|
||||||
/* signal */ //@item(osslashsignal, "signal", "\"os/signal\"", "package")
|
|
||||||
/* user */ //@item(osslashuser, "user", "\"os/user\"", "package")
|
|
||||||
/* path */ //@item(path, "path", "\"path\"", "package")
|
|
||||||
/* filepath */ //@item(pathslashfilepath, "filepath", "\"path/filepath\"", "package")
|
|
||||||
/* plugin */ //@item(plugin, "plugin", "\"plugin\"", "package")
|
|
||||||
/* reflect */ //@item(reflect, "reflect", "\"reflect\"", "package")
|
|
||||||
/* regexp */ //@item(regexp, "regexp", "\"regexp\"", "package")
|
|
||||||
/* syntax */ //@item(regexpslashsyntax, "syntax", "\"regexp/syntax\"", "package")
|
|
||||||
/* runtime */ //@item(runtime, "runtime", "\"runtime\"", "package")
|
|
||||||
/* debug */ //@item(runtimeslashdebug, "debug", "\"runtime/debug\"", "package")
|
|
||||||
/* pprof */ //@item(runtimeslashpprof, "pprof", "\"runtime/pprof\"", "package")
|
|
||||||
/* trace */ //@item(runtimeslashtrace, "trace", "\"runtime/trace\"", "package")
|
|
||||||
/* sort */ //@item(sort, "sort", "\"sort\"", "package")
|
|
||||||
/* strconv */ //@item(strconv, "strconv", "\"strconv\"", "package")
|
|
||||||
/* strings */ //@item(strings, "strings", "\"strings\"", "package")
|
|
||||||
/* sync */ //@item(sync, "sync", "\"sync\"", "package")
|
|
||||||
/* atomic */ //@item(syncslashatomic, "atomic", "\"sync/atomic\"", "package")
|
|
||||||
/* syscall */ //@item(syscall, "syscall", "\"syscall\"", "package")
|
|
||||||
/* js */ //@item(syscallslashjs, "js", "\"syscall/js\"", "package")
|
|
||||||
/* testing */ //@item(testing, "testing", "\"testing\"", "package")
|
|
||||||
/* iotest */ //@item(testingslashiotest, "iotest", "\"testing/iotest\"", "package")
|
|
||||||
/* quick */ //@item(testingslashquick, "quick", "\"testing/quick\"", "package")
|
|
||||||
/* scanner */ //@item(textslashscanner, "scanner", "\"text/scanner\"", "package")
|
|
||||||
/* tabwriter */ //@item(textslashtabwriter, "tabwriter", "\"text/tabwriter\"", "package")
|
|
||||||
/* template */ //@item(textslashtemplate, "template", "\"text/template\"", "package")
|
|
||||||
/* parse */ //@item(textslashtemplateslashparse, "parse", "\"text/template/parse\"", "package")
|
|
||||||
/* time */ //@item(time, "time", "\"time\"", "package")
|
|
||||||
/* unicode */ //@item(unicode, "unicode", "\"unicode\"", "package")
|
|
||||||
/* utf16 */ //@item(unicodeslashutf16, "utf16", "\"unicode/utf16\"", "package")
|
|
||||||
/* utf8 */ //@item(unicodeslashutf8, "utf8", "\"unicode/utf8\"", "package")
|
|
||||||
/* unsafe */ //@item(unsafe, "unsafe", "\"unsafe\"", "package")
|
/* unsafe */ //@item(unsafe, "unsafe", "\"unsafe\"", "package")
|
||||||
|
/* time */ //@item(time, "time", "\"time\"", "package")
|
||||||
|
@ -251,6 +251,12 @@ func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data {
|
|||||||
Files: files,
|
Files: files,
|
||||||
Overlay: overlays,
|
Overlay: overlays,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "example.com/extramodule",
|
||||||
|
Files: map[string]interface{}{
|
||||||
|
"pkg/x.go": "package pkg\n",
|
||||||
|
},
|
||||||
|
},
|
||||||
}
|
}
|
||||||
data.Exported = packagestest.Export(t, exporter, modules)
|
data.Exported = packagestest.Export(t, exporter, modules)
|
||||||
for fragment := range files {
|
for fragment := range files {
|
||||||
|
Loading…
Reference in New Issue
Block a user