diff options
Diffstat (limited to 'src/cmd/go/internal/imports')
32 files changed, 1084 insertions, 0 deletions
diff --git a/src/cmd/go/internal/imports/build.go b/src/cmd/go/internal/imports/build.go new file mode 100644 index 0000000..50aeabc --- /dev/null +++ b/src/cmd/go/internal/imports/build.go @@ -0,0 +1,251 @@ +// 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. + +// Copied from Go distribution src/go/build/build.go, syslist.go + +package imports + +import ( + "bytes" + "strings" + "unicode" +) + +var slashslash = []byte("//") + +// ShouldBuild reports whether it is okay to use this file, +// The rule is that in the file's leading run of // comments +// and blank lines, which must be followed by a blank line +// (to avoid including a Go package clause doc comment), +// lines beginning with '// +build' are taken as build directives. +// +// The file is accepted only if each such line lists something +// matching the file. For example: +// +// // +build windows linux +// +// marks the file as applicable only on Windows and Linux. +// +// If tags["*"] is true, then ShouldBuild will consider every +// build tag except "ignore" to be both true and false for +// the purpose of satisfying build tags, in order to estimate +// (conservatively) whether a file could ever possibly be used +// in any build. +// +func ShouldBuild(content []byte, tags map[string]bool) bool { + // Pass 1. Identify leading run of // comments and blank lines, + // which must be followed by a blank line. + end := 0 + p := content + for len(p) > 0 { + line := p + if i := bytes.IndexByte(line, '\n'); i >= 0 { + line, p = line[:i], p[i+1:] + } else { + p = p[len(p):] + } + line = bytes.TrimSpace(line) + if len(line) == 0 { // Blank line + end = len(content) - len(p) + continue + } + if !bytes.HasPrefix(line, slashslash) { // Not comment line + break + } + } + content = content[:end] + + // Pass 2. Process each line in the run. + p = content + allok := true + for len(p) > 0 { + line := p + if i := bytes.IndexByte(line, '\n'); i >= 0 { + line, p = line[:i], p[i+1:] + } else { + p = p[len(p):] + } + line = bytes.TrimSpace(line) + if !bytes.HasPrefix(line, slashslash) { + continue + } + line = bytes.TrimSpace(line[len(slashslash):]) + if len(line) > 0 && line[0] == '+' { + // Looks like a comment +line. + f := strings.Fields(string(line)) + if f[0] == "+build" { + ok := false + for _, tok := range f[1:] { + if matchTags(tok, tags) { + ok = true + } + } + if !ok { + allok = false + } + } + } + } + + return allok +} + +// matchTags reports whether the name is one of: +// +// tag (if tags[tag] is true) +// !tag (if tags[tag] is false) +// a comma-separated list of any of these +// +func matchTags(name string, tags map[string]bool) bool { + if name == "" { + return false + } + if i := strings.Index(name, ","); i >= 0 { + // comma-separated list + ok1 := matchTags(name[:i], tags) + ok2 := matchTags(name[i+1:], tags) + return ok1 && ok2 + } + if strings.HasPrefix(name, "!!") { // bad syntax, reject always + return false + } + if strings.HasPrefix(name, "!") { // negation + return len(name) > 1 && matchTag(name[1:], tags, false) + } + return matchTag(name, tags, true) +} + +// matchTag reports whether the tag name is valid and satisfied by tags[name]==want. +func matchTag(name string, tags map[string]bool, want bool) bool { + // Tags must be letters, digits, underscores or dots. + // Unlike in Go identifiers, all digits are fine (e.g., "386"). + for _, c := range name { + if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { + return false + } + } + + if tags["*"] && name != "" && name != "ignore" { + // Special case for gathering all possible imports: + // if we put * in the tags map then all tags + // except "ignore" are considered both present and not + // (so we return true no matter how 'want' is set). + return true + } + + have := tags[name] + if name == "linux" { + have = have || tags["android"] + } + if name == "solaris" { + have = have || tags["illumos"] + } + if name == "darwin" { + have = have || tags["ios"] + } + return have == want +} + +// MatchFile returns false if the name contains a $GOOS or $GOARCH +// suffix which does not match the current system. +// The recognized name formats are: +// +// name_$(GOOS).* +// name_$(GOARCH).* +// name_$(GOOS)_$(GOARCH).* +// name_$(GOOS)_test.* +// name_$(GOARCH)_test.* +// name_$(GOOS)_$(GOARCH)_test.* +// +// Exceptions: +// if GOOS=android, then files with GOOS=linux are also matched. +// if GOOS=illumos, then files with GOOS=solaris are also matched. +// if GOOS=ios, then files with GOOS=darwin are also matched. +// +// If tags["*"] is true, then MatchFile will consider all possible +// GOOS and GOARCH to be available and will consequently +// always return true. +func MatchFile(name string, tags map[string]bool) bool { + if tags["*"] { + return true + } + if dot := strings.Index(name, "."); dot != -1 { + name = name[:dot] + } + + // Before Go 1.4, a file called "linux.go" would be equivalent to having a + // build tag "linux" in that file. For Go 1.4 and beyond, we require this + // auto-tagging to apply only to files with a non-empty prefix, so + // "foo_linux.go" is tagged but "linux.go" is not. This allows new operating + // systems, such as android, to arrive without breaking existing code with + // innocuous source code in "android.go". The easiest fix: cut everything + // in the name before the initial _. + i := strings.Index(name, "_") + if i < 0 { + return true + } + name = name[i:] // ignore everything before first _ + + l := strings.Split(name, "_") + if n := len(l); n > 0 && l[n-1] == "test" { + l = l[:n-1] + } + n := len(l) + if n >= 2 && KnownOS[l[n-2]] && KnownArch[l[n-1]] { + return matchTag(l[n-2], tags, true) && matchTag(l[n-1], tags, true) + } + if n >= 1 && KnownOS[l[n-1]] { + return matchTag(l[n-1], tags, true) + } + if n >= 1 && KnownArch[l[n-1]] { + return matchTag(l[n-1], tags, true) + } + return true +} + +var KnownOS = map[string]bool{ + "aix": true, + "android": true, + "darwin": true, + "dragonfly": true, + "freebsd": true, + "hurd": true, + "illumos": true, + "ios": true, + "js": true, + "linux": true, + "nacl": true, // legacy; don't remove + "netbsd": true, + "openbsd": true, + "plan9": true, + "solaris": true, + "windows": true, + "zos": true, +} + +var KnownArch = map[string]bool{ + "386": true, + "amd64": true, + "amd64p32": true, // legacy; don't remove + "arm": true, + "armbe": true, + "arm64": true, + "arm64be": true, + "ppc64": true, + "ppc64le": true, + "mips": true, + "mipsle": true, + "mips64": true, + "mips64le": true, + "mips64p32": true, + "mips64p32le": true, + "ppc": true, + "riscv": true, + "riscv64": true, + "s390": true, + "s390x": true, + "sparc": true, + "sparc64": true, + "wasm": true, +} diff --git a/src/cmd/go/internal/imports/read.go b/src/cmd/go/internal/imports/read.go new file mode 100644 index 0000000..5e27078 --- /dev/null +++ b/src/cmd/go/internal/imports/read.go @@ -0,0 +1,249 @@ +// Copyright 2012 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. + +// Copied from Go distribution src/go/build/read.go. + +package imports + +import ( + "bufio" + "errors" + "io" + "unicode/utf8" +) + +type importReader struct { + b *bufio.Reader + buf []byte + peek byte + err error + eof bool + nerr int +} + +func isIdent(c byte) bool { + return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf +} + +var ( + errSyntax = errors.New("syntax error") + errNUL = errors.New("unexpected NUL in input") +) + +// syntaxError records a syntax error, but only if an I/O error has not already been recorded. +func (r *importReader) syntaxError() { + if r.err == nil { + r.err = errSyntax + } +} + +// readByte reads the next byte from the input, saves it in buf, and returns it. +// If an error occurs, readByte records the error in r.err and returns 0. +func (r *importReader) readByte() byte { + c, err := r.b.ReadByte() + if err == nil { + r.buf = append(r.buf, c) + if c == 0 { + err = errNUL + } + } + if err != nil { + if err == io.EOF { + r.eof = true + } else if r.err == nil { + r.err = err + } + c = 0 + } + return c +} + +// peekByte returns the next byte from the input reader but does not advance beyond it. +// If skipSpace is set, peekByte skips leading spaces and comments. +func (r *importReader) peekByte(skipSpace bool) byte { + if r.err != nil { + if r.nerr++; r.nerr > 10000 { + panic("go/build: import reader looping") + } + return 0 + } + + // Use r.peek as first input byte. + // Don't just return r.peek here: it might have been left by peekByte(false) + // and this might be peekByte(true). + c := r.peek + if c == 0 { + c = r.readByte() + } + for r.err == nil && !r.eof { + if skipSpace { + // For the purposes of this reader, semicolons are never necessary to + // understand the input and are treated as spaces. + switch c { + case ' ', '\f', '\t', '\r', '\n', ';': + c = r.readByte() + continue + + case '/': + c = r.readByte() + if c == '/' { + for c != '\n' && r.err == nil && !r.eof { + c = r.readByte() + } + } else if c == '*' { + var c1 byte + for (c != '*' || c1 != '/') && r.err == nil { + if r.eof { + r.syntaxError() + } + c, c1 = c1, r.readByte() + } + } else { + r.syntaxError() + } + c = r.readByte() + continue + } + } + break + } + r.peek = c + return r.peek +} + +// nextByte is like peekByte but advances beyond the returned byte. +func (r *importReader) nextByte(skipSpace bool) byte { + c := r.peekByte(skipSpace) + r.peek = 0 + return c +} + +// readKeyword reads the given keyword from the input. +// If the keyword is not present, readKeyword records a syntax error. +func (r *importReader) readKeyword(kw string) { + r.peekByte(true) + for i := 0; i < len(kw); i++ { + if r.nextByte(false) != kw[i] { + r.syntaxError() + return + } + } + if isIdent(r.peekByte(false)) { + r.syntaxError() + } +} + +// readIdent reads an identifier from the input. +// If an identifier is not present, readIdent records a syntax error. +func (r *importReader) readIdent() { + c := r.peekByte(true) + if !isIdent(c) { + r.syntaxError() + return + } + for isIdent(r.peekByte(false)) { + r.peek = 0 + } +} + +// readString reads a quoted string literal from the input. +// If an identifier is not present, readString records a syntax error. +func (r *importReader) readString(save *[]string) { + switch r.nextByte(true) { + case '`': + start := len(r.buf) - 1 + for r.err == nil { + if r.nextByte(false) == '`' { + if save != nil { + *save = append(*save, string(r.buf[start:])) + } + break + } + if r.eof { + r.syntaxError() + } + } + case '"': + start := len(r.buf) - 1 + for r.err == nil { + c := r.nextByte(false) + if c == '"' { + if save != nil { + *save = append(*save, string(r.buf[start:])) + } + break + } + if r.eof || c == '\n' { + r.syntaxError() + } + if c == '\\' { + r.nextByte(false) + } + } + default: + r.syntaxError() + } +} + +// readImport reads an import clause - optional identifier followed by quoted string - +// from the input. +func (r *importReader) readImport(imports *[]string) { + c := r.peekByte(true) + if c == '.' { + r.peek = 0 + } else if isIdent(c) { + r.readIdent() + } + r.readString(imports) +} + +// ReadComments is like io.ReadAll, except that it only reads the leading +// block of comments in the file. +func ReadComments(f io.Reader) ([]byte, error) { + r := &importReader{b: bufio.NewReader(f)} + r.peekByte(true) + if r.err == nil && !r.eof { + // Didn't reach EOF, so must have found a non-space byte. Remove it. + r.buf = r.buf[:len(r.buf)-1] + } + return r.buf, r.err +} + +// ReadImports is like io.ReadAll, except that it expects a Go file as input +// and stops reading the input once the imports have completed. +func ReadImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) { + r := &importReader{b: bufio.NewReader(f)} + + r.readKeyword("package") + r.readIdent() + for r.peekByte(true) == 'i' { + r.readKeyword("import") + if r.peekByte(true) == '(' { + r.nextByte(false) + for r.peekByte(true) != ')' && r.err == nil { + r.readImport(imports) + } + r.nextByte(false) + } else { + r.readImport(imports) + } + } + + // If we stopped successfully before EOF, we read a byte that told us we were done. + // Return all but that last byte, which would cause a syntax error if we let it through. + if r.err == nil && !r.eof { + return r.buf[:len(r.buf)-1], nil + } + + // If we stopped for a syntax error, consume the whole file so that + // we are sure we don't change the errors that go/parser returns. + if r.err == errSyntax && !reportSyntaxError { + r.err = nil + for r.err == nil && !r.eof { + r.readByte() + } + } + + return r.buf, r.err +} diff --git a/src/cmd/go/internal/imports/read_test.go b/src/cmd/go/internal/imports/read_test.go new file mode 100644 index 0000000..6ea356f --- /dev/null +++ b/src/cmd/go/internal/imports/read_test.go @@ -0,0 +1,228 @@ +// Copyright 2012 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. + +// Copied from Go distribution src/go/build/read.go. + +package imports + +import ( + "io" + "strings" + "testing" +) + +const quote = "`" + +type readTest struct { + // Test input contains ℙ where readImports should stop. + in string + err string +} + +var readImportsTests = []readTest{ + { + `package p`, + "", + }, + { + `package p; import "x"`, + "", + }, + { + `package p; import . "x"`, + "", + }, + { + `package p; import "x";ℙvar x = 1`, + "", + }, + { + `package p + + // comment + + import "x" + import _ "x" + import a "x" + + /* comment */ + + import ( + "x" /* comment */ + _ "x" + a "x" // comment + ` + quote + `x` + quote + ` + _ /*comment*/ ` + quote + `x` + quote + ` + a ` + quote + `x` + quote + ` + ) + import ( + ) + import () + import()import()import() + import();import();import() + + ℙvar x = 1 + `, + "", + }, +} + +var readCommentsTests = []readTest{ + { + `ℙpackage p`, + "", + }, + { + `ℙpackage p; import "x"`, + "", + }, + { + `ℙpackage p; import . "x"`, + "", + }, + { + `// foo + + /* bar */ + + /* quux */ // baz + + /*/ zot */ + + // asdf + ℙHello, world`, + "", + }, +} + +func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, error)) { + for i, tt := range tests { + var in, testOut string + j := strings.Index(tt.in, "ℙ") + if j < 0 { + in = tt.in + testOut = tt.in + } else { + in = tt.in[:j] + tt.in[j+len("ℙ"):] + testOut = tt.in[:j] + } + r := strings.NewReader(in) + buf, err := read(r) + if err != nil { + if tt.err == "" { + t.Errorf("#%d: err=%q, expected success (%q)", i, err, string(buf)) + continue + } + if !strings.Contains(err.Error(), tt.err) { + t.Errorf("#%d: err=%q, expected %q", i, err, tt.err) + continue + } + continue + } + if err == nil && tt.err != "" { + t.Errorf("#%d: success, expected %q", i, tt.err) + continue + } + + out := string(buf) + if out != testOut { + t.Errorf("#%d: wrong output:\nhave %q\nwant %q\n", i, out, testOut) + } + } +} + +func TestReadImports(t *testing.T) { + testRead(t, readImportsTests, func(r io.Reader) ([]byte, error) { return ReadImports(r, true, nil) }) +} + +func TestReadComments(t *testing.T) { + testRead(t, readCommentsTests, ReadComments) +} + +var readFailuresTests = []readTest{ + { + `package`, + "syntax error", + }, + { + "package p\n\x00\nimport `math`\n", + "unexpected NUL in input", + }, + { + `package p; import`, + "syntax error", + }, + { + `package p; import "`, + "syntax error", + }, + { + "package p; import ` \n\n", + "syntax error", + }, + { + `package p; import "x`, + "syntax error", + }, + { + `package p; import _`, + "syntax error", + }, + { + `package p; import _ "`, + "syntax error", + }, + { + `package p; import _ "x`, + "syntax error", + }, + { + `package p; import .`, + "syntax error", + }, + { + `package p; import . "`, + "syntax error", + }, + { + `package p; import . "x`, + "syntax error", + }, + { + `package p; import (`, + "syntax error", + }, + { + `package p; import ("`, + "syntax error", + }, + { + `package p; import ("x`, + "syntax error", + }, + { + `package p; import ("x"`, + "syntax error", + }, +} + +func TestReadFailures(t *testing.T) { + // Errors should be reported (true arg to readImports). + testRead(t, readFailuresTests, func(r io.Reader) ([]byte, error) { return ReadImports(r, true, nil) }) +} + +func TestReadFailuresIgnored(t *testing.T) { + // Syntax errors should not be reported (false arg to readImports). + // Instead, entire file should be the output and no error. + // Convert tests not to return syntax errors. + tests := make([]readTest, len(readFailuresTests)) + copy(tests, readFailuresTests) + for i := range tests { + tt := &tests[i] + if !strings.Contains(tt.err, "NUL") { + tt.err = "" + } + } + testRead(t, tests, func(r io.Reader) ([]byte, error) { return ReadImports(r, false, nil) }) +} 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 +} diff --git a/src/cmd/go/internal/imports/scan_test.go b/src/cmd/go/internal/imports/scan_test.go new file mode 100644 index 0000000..2d245ee --- /dev/null +++ b/src/cmd/go/internal/imports/scan_test.go @@ -0,0 +1,94 @@ +// 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 ( + "bytes" + "internal/testenv" + "os" + "path" + "path/filepath" + "runtime" + "strings" + "testing" +) + +func TestScan(t *testing.T) { + testenv.MustHaveGoBuild(t) + + imports, testImports, err := ScanDir(filepath.Join(runtime.GOROOT(), "src/encoding/json"), Tags()) + if err != nil { + t.Fatal(err) + } + foundBase64 := false + for _, p := range imports { + if p == "encoding/base64" { + foundBase64 = true + } + if p == "encoding/binary" { + // A dependency but not an import + t.Errorf("json reported as importing encoding/binary but does not") + } + if p == "net/http" { + // A test import but not an import + t.Errorf("json reported as importing encoding/binary but does not") + } + } + if !foundBase64 { + t.Errorf("json missing import encoding/base64 (%q)", imports) + } + + foundHTTP := false + for _, p := range testImports { + if p == "net/http" { + foundHTTP = true + } + if p == "unicode/utf16" { + // A package import but not a test import + t.Errorf("json reported as test-importing unicode/utf16 but does not") + } + } + if !foundHTTP { + t.Errorf("json missing test import net/http (%q)", testImports) + } +} +func TestScanDir(t *testing.T) { + testenv.MustHaveGoBuild(t) + + dirs, err := os.ReadDir("testdata") + if err != nil { + t.Fatal(err) + } + for _, dir := range dirs { + if !dir.IsDir() || strings.HasPrefix(dir.Name(), ".") { + continue + } + t.Run(dir.Name(), func(t *testing.T) { + tagsData, err := os.ReadFile(filepath.Join("testdata", dir.Name(), "tags.txt")) + if err != nil { + t.Fatalf("error reading tags: %v", err) + } + tags := make(map[string]bool) + for _, t := range strings.Fields(string(tagsData)) { + tags[t] = true + } + + wantData, err := os.ReadFile(filepath.Join("testdata", dir.Name(), "want.txt")) + if err != nil { + t.Fatalf("error reading want: %v", err) + } + want := string(bytes.TrimSpace(wantData)) + + imports, _, err := ScanDir(path.Join("testdata", dir.Name()), tags) + if err != nil { + t.Fatal(err) + } + got := strings.Join(imports, "\n") + if got != want { + t.Errorf("ScanDir: got imports:\n%s\n\nwant:\n%s", got, want) + } + }) + } +} diff --git a/src/cmd/go/internal/imports/tags.go b/src/cmd/go/internal/imports/tags.go new file mode 100644 index 0000000..01b448b --- /dev/null +++ b/src/cmd/go/internal/imports/tags.go @@ -0,0 +1,58 @@ +// 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 ( + "cmd/go/internal/cfg" + "sync" +) + +var ( + tags map[string]bool + tagsOnce sync.Once +) + +// Tags returns a set of build tags that are true for the target platform. +// It includes GOOS, GOARCH, the compiler, possibly "cgo", +// release tags like "go1.13", and user-specified build tags. +func Tags() map[string]bool { + tagsOnce.Do(func() { + tags = loadTags() + }) + return tags +} + +func loadTags() map[string]bool { + tags := map[string]bool{ + cfg.BuildContext.GOOS: true, + cfg.BuildContext.GOARCH: true, + cfg.BuildContext.Compiler: true, + } + if cfg.BuildContext.CgoEnabled { + tags["cgo"] = true + } + for _, tag := range cfg.BuildContext.BuildTags { + tags[tag] = true + } + for _, tag := range cfg.BuildContext.ReleaseTags { + tags[tag] = true + } + return tags +} + +var ( + anyTags map[string]bool + anyTagsOnce sync.Once +) + +// AnyTags returns a special set of build tags that satisfy nearly all +// build tag expressions. Only "ignore" and malformed build tag requirements +// are considered false. +func AnyTags() map[string]bool { + anyTagsOnce.Do(func() { + anyTags = map[string]bool{"*": true} + }) + return anyTags +} diff --git a/src/cmd/go/internal/imports/testdata/android/.h.go b/src/cmd/go/internal/imports/testdata/android/.h.go new file mode 100644 index 0000000..53c529e --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/.h.go @@ -0,0 +1,3 @@ +package android + +import _ "h" diff --git a/src/cmd/go/internal/imports/testdata/android/a_android.go b/src/cmd/go/internal/imports/testdata/android/a_android.go new file mode 100644 index 0000000..2ed972e --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/a_android.go @@ -0,0 +1,3 @@ +package android + +import _ "a" diff --git a/src/cmd/go/internal/imports/testdata/android/b_android_arm64.go b/src/cmd/go/internal/imports/testdata/android/b_android_arm64.go new file mode 100644 index 0000000..ee9c312 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/b_android_arm64.go @@ -0,0 +1,3 @@ +package android + +import _ "b" diff --git a/src/cmd/go/internal/imports/testdata/android/c_linux.go b/src/cmd/go/internal/imports/testdata/android/c_linux.go new file mode 100644 index 0000000..91624ce --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/c_linux.go @@ -0,0 +1,3 @@ +package android + +import _ "c" diff --git a/src/cmd/go/internal/imports/testdata/android/d_linux_arm64.go b/src/cmd/go/internal/imports/testdata/android/d_linux_arm64.go new file mode 100644 index 0000000..34e07df --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/d_linux_arm64.go @@ -0,0 +1,3 @@ +package android + +import _ "d" diff --git a/src/cmd/go/internal/imports/testdata/android/e.go b/src/cmd/go/internal/imports/testdata/android/e.go new file mode 100644 index 0000000..d9b2db7 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/e.go @@ -0,0 +1,5 @@ +// +build android + +package android + +import _ "e" diff --git a/src/cmd/go/internal/imports/testdata/android/f.go b/src/cmd/go/internal/imports/testdata/android/f.go new file mode 100644 index 0000000..281e4dd --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/f.go @@ -0,0 +1,5 @@ +// +build linux + +package android + +import _ "f" diff --git a/src/cmd/go/internal/imports/testdata/android/g.go b/src/cmd/go/internal/imports/testdata/android/g.go new file mode 100644 index 0000000..66a789c --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/g.go @@ -0,0 +1,5 @@ +// +build !android + +package android + +import _ "g" diff --git a/src/cmd/go/internal/imports/testdata/android/tags.txt b/src/cmd/go/internal/imports/testdata/android/tags.txt new file mode 100644 index 0000000..aaf5a6b --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/tags.txt @@ -0,0 +1 @@ +android arm64
\ No newline at end of file diff --git a/src/cmd/go/internal/imports/testdata/android/want.txt b/src/cmd/go/internal/imports/testdata/android/want.txt new file mode 100644 index 0000000..0fdf397 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/android/want.txt @@ -0,0 +1,6 @@ +a +b +c +d +e +f diff --git a/src/cmd/go/internal/imports/testdata/illumos/.h.go b/src/cmd/go/internal/imports/testdata/illumos/.h.go new file mode 100644 index 0000000..53c529e --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/.h.go @@ -0,0 +1,3 @@ +package android + +import _ "h" diff --git a/src/cmd/go/internal/imports/testdata/illumos/a_illumos.go b/src/cmd/go/internal/imports/testdata/illumos/a_illumos.go new file mode 100644 index 0000000..2e6cb50 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/a_illumos.go @@ -0,0 +1,3 @@ +package illumos + +import _ "a" diff --git a/src/cmd/go/internal/imports/testdata/illumos/b_illumos_amd64.go b/src/cmd/go/internal/imports/testdata/illumos/b_illumos_amd64.go new file mode 100644 index 0000000..2834d80 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/b_illumos_amd64.go @@ -0,0 +1,3 @@ +package illumos + +import _ "b" diff --git a/src/cmd/go/internal/imports/testdata/illumos/c_solaris.go b/src/cmd/go/internal/imports/testdata/illumos/c_solaris.go new file mode 100644 index 0000000..d7f9462 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/c_solaris.go @@ -0,0 +1,3 @@ +package illumos + +import _ "c" diff --git a/src/cmd/go/internal/imports/testdata/illumos/d_solaris_amd64.go b/src/cmd/go/internal/imports/testdata/illumos/d_solaris_amd64.go new file mode 100644 index 0000000..0f52c2b --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/d_solaris_amd64.go @@ -0,0 +1,3 @@ +package illumos + +import _ "d" diff --git a/src/cmd/go/internal/imports/testdata/illumos/e.go b/src/cmd/go/internal/imports/testdata/illumos/e.go new file mode 100644 index 0000000..5e1ed3c --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/e.go @@ -0,0 +1,5 @@ +// +build illumos + +package illumos + +import _ "e" diff --git a/src/cmd/go/internal/imports/testdata/illumos/f.go b/src/cmd/go/internal/imports/testdata/illumos/f.go new file mode 100644 index 0000000..f3e3f72 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/f.go @@ -0,0 +1,5 @@ +// +build solaris + +package illumos + +import _ "f" diff --git a/src/cmd/go/internal/imports/testdata/illumos/g.go b/src/cmd/go/internal/imports/testdata/illumos/g.go new file mode 100644 index 0000000..b30f1eb --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/g.go @@ -0,0 +1,5 @@ +// +build !illumos + +package illumos + +import _ "g" diff --git a/src/cmd/go/internal/imports/testdata/illumos/tags.txt b/src/cmd/go/internal/imports/testdata/illumos/tags.txt new file mode 100644 index 0000000..b6386a3 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/tags.txt @@ -0,0 +1 @@ +illumos amd64 diff --git a/src/cmd/go/internal/imports/testdata/illumos/want.txt b/src/cmd/go/internal/imports/testdata/illumos/want.txt new file mode 100644 index 0000000..0fdf397 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/illumos/want.txt @@ -0,0 +1,6 @@ +a +b +c +d +e +f diff --git a/src/cmd/go/internal/imports/testdata/star/tags.txt b/src/cmd/go/internal/imports/testdata/star/tags.txt new file mode 100644 index 0000000..f59ec20 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/star/tags.txt @@ -0,0 +1 @@ +*
\ No newline at end of file diff --git a/src/cmd/go/internal/imports/testdata/star/want.txt b/src/cmd/go/internal/imports/testdata/star/want.txt new file mode 100644 index 0000000..139f5f4 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/star/want.txt @@ -0,0 +1,4 @@ +import1 +import2 +import3 +import4 diff --git a/src/cmd/go/internal/imports/testdata/star/x.go b/src/cmd/go/internal/imports/testdata/star/x.go new file mode 100644 index 0000000..98f9191 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/star/x.go @@ -0,0 +1,3 @@ +package x + +import "import1" diff --git a/src/cmd/go/internal/imports/testdata/star/x1.go b/src/cmd/go/internal/imports/testdata/star/x1.go new file mode 100644 index 0000000..6a9594a --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/star/x1.go @@ -0,0 +1,9 @@ +// +build blahblh +// +build linux +// +build !linux +// +build windows +// +build darwin + +package x + +import "import4" diff --git a/src/cmd/go/internal/imports/testdata/star/x_darwin.go b/src/cmd/go/internal/imports/testdata/star/x_darwin.go new file mode 100644 index 0000000..a0c3fdd --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/star/x_darwin.go @@ -0,0 +1,3 @@ +package xxxx + +import "import3" diff --git a/src/cmd/go/internal/imports/testdata/star/x_windows.go b/src/cmd/go/internal/imports/testdata/star/x_windows.go new file mode 100644 index 0000000..63c5082 --- /dev/null +++ b/src/cmd/go/internal/imports/testdata/star/x_windows.go @@ -0,0 +1,3 @@ +package x + +import "import2" |