summaryrefslogtreecommitdiffstats
path: root/src/cmd/go/internal/imports/scan.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/go/internal/imports/scan.go')
-rw-r--r--src/cmd/go/internal/imports/scan.go107
1 files changed, 107 insertions, 0 deletions
diff --git a/src/cmd/go/internal/imports/scan.go b/src/cmd/go/internal/imports/scan.go
new file mode 100644
index 0000000..ee11a87
--- /dev/null
+++ b/src/cmd/go/internal/imports/scan.go
@@ -0,0 +1,107 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package imports
+
+import (
+ "fmt"
+ "io/fs"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+
+ "cmd/go/internal/fsys"
+)
+
+func ScanDir(dir string, tags map[string]bool) ([]string, []string, error) {
+ infos, err := fsys.ReadDir(dir)
+ if err != nil {
+ return nil, nil, err
+ }
+ var files []string
+ for _, info := range infos {
+ name := info.Name()
+
+ // If the directory entry is a symlink, stat it to obtain the info for the
+ // link target instead of the link itself.
+ if info.Mode()&fs.ModeSymlink != 0 {
+ info, err = fsys.Stat(filepath.Join(dir, name))
+ if err != nil {
+ continue // Ignore broken symlinks.
+ }
+ }
+
+ if info.Mode().IsRegular() && !strings.HasPrefix(name, "_") && !strings.HasPrefix(name, ".") && strings.HasSuffix(name, ".go") && MatchFile(name, tags) {
+ files = append(files, filepath.Join(dir, name))
+ }
+ }
+ return scanFiles(files, tags, false)
+}
+
+func ScanFiles(files []string, tags map[string]bool) ([]string, []string, error) {
+ return scanFiles(files, tags, true)
+}
+
+func scanFiles(files []string, tags map[string]bool, explicitFiles bool) ([]string, []string, error) {
+ imports := make(map[string]bool)
+ testImports := make(map[string]bool)
+ numFiles := 0
+Files:
+ for _, name := range files {
+ r, err := fsys.Open(name)
+ if err != nil {
+ return nil, nil, err
+ }
+ var list []string
+ data, err := ReadImports(r, false, &list)
+ r.Close()
+ if err != nil {
+ return nil, nil, fmt.Errorf("reading %s: %v", name, err)
+ }
+
+ // import "C" is implicit requirement of cgo tag.
+ // When listing files on the command line (explicitFiles=true)
+ // we do not apply build tag filtering but we still do apply
+ // cgo filtering, so no explicitFiles check here.
+ // Why? Because we always have, and it's not worth breaking
+ // that behavior now.
+ for _, path := range list {
+ if path == `"C"` && !tags["cgo"] && !tags["*"] {
+ continue Files
+ }
+ }
+
+ if !explicitFiles && !ShouldBuild(data, tags) {
+ continue
+ }
+ numFiles++
+ m := imports
+ if strings.HasSuffix(name, "_test.go") {
+ m = testImports
+ }
+ for _, p := range list {
+ q, err := strconv.Unquote(p)
+ if err != nil {
+ continue
+ }
+ m[q] = true
+ }
+ }
+ if numFiles == 0 {
+ return nil, nil, ErrNoGo
+ }
+ return keys(imports), keys(testImports), nil
+}
+
+var ErrNoGo = fmt.Errorf("no Go source files")
+
+func keys(m map[string]bool) []string {
+ var list []string
+ for k := range m {
+ list = append(list, k)
+ }
+ sort.Strings(list)
+ return list
+}