type Context … // joinPath calls ctxt.JoinPath (if not nil) or else filepath.Join. func (ctxt *Context) joinPath(elem ...string) string { … } // splitPathList calls ctxt.SplitPathList (if not nil) or else filepath.SplitList. func (ctxt *Context) splitPathList(s string) []string { … } // isAbsPath calls ctxt.IsAbsPath (if not nil) or else filepath.IsAbs. func (ctxt *Context) isAbsPath(path string) bool { … } // isDir calls ctxt.IsDir (if not nil) or else uses os.Stat. func (ctxt *Context) isDir(path string) bool { … } // hasSubdir calls ctxt.HasSubdir (if not nil) or else uses // the local file system to answer the question. func (ctxt *Context) hasSubdir(root, dir string) (rel string, ok bool) { … } // hasSubdir reports if dir is within root by performing lexical analysis only. func hasSubdir(root, dir string) (rel string, ok bool) { … } // readDir calls ctxt.ReadDir (if not nil) or else os.ReadDir. func (ctxt *Context) readDir(path string) ([]fs.DirEntry, error) { … } // openFile calls ctxt.OpenFile (if not nil) or else os.Open. func (ctxt *Context) openFile(path string) (io.ReadCloser, error) { … } // isFile determines whether path is a file by trying to open it. // It reuses openFile instead of adding another function to the // list in Context. func (ctxt *Context) isFile(path string) bool { … } // gopath returns the list of Go path directories. func (ctxt *Context) gopath() []string { … } // SrcDirs returns a list of package source root directories. // It draws from the current Go root and Go path but omits directories // that do not exist. func (ctxt *Context) SrcDirs() []string { … } var Default … // Keep consistent with cmd/go/internal/cfg.defaultGOPATH. func defaultGOPATH() string { … } var defaultToolTags … var defaultReleaseTags … func defaultContext() Context { … } func envOr(name, def string) string { … } type ImportMode … const FindOnly … const AllowBinary … const ImportComment … const IgnoreVendor … type Package … type Directive … // IsCommand reports whether the package is considered a // command to be installed (not just a library). // Packages named "main" are treated as commands. func (p *Package) IsCommand() bool { … } // ImportDir is like [Import] but processes the Go package found in // the named directory. func (ctxt *Context) ImportDir(dir string, mode ImportMode) (*Package, error) { … } type NoGoError … func (e *NoGoError) Error() string { … } type MultiplePackageError … func (e *MultiplePackageError) Error() string { … } func nameExt(name string) string { … } var installgoroot … // Import returns details about the Go package named by the import path, // interpreting local import paths relative to the srcDir directory. // If the path is a local import path naming a package that can be imported // using a standard import path, the returned package will set p.ImportPath // to that path. // // In the directory containing the package, .go, .c, .h, and .s files are // considered part of the package except for: // // - .go files in package documentation // - files starting with _ or . (likely editor temporary files) // - files with build constraints not satisfied by the context // // If an error occurs, Import returns a non-nil error and a non-nil // *[Package] containing partial information. func (ctxt *Context) Import(path string, srcDir string, mode ImportMode) (*Package, error) { … } func fileListForExt(p *Package, ext string) *[]string { … } func uniq(list []string) []string { … } var errNoModules … // importGo checks whether it can use the go command to find the directory for path. // If using the go command is not appropriate, importGo returns errNoModules. // Otherwise, importGo tries using the go command and reports whether that succeeded. // Using the go command lets build.Import and build.Context.Import find code // in Go modules. In the long term we want tools to use go/packages (currently golang.org/x/tools/go/packages), // which will also use the go command. // Invoking the go command here is not very efficient in that it computes information // about the requested package and all dependencies and then only reports about the requested package. // Then we reinvoke it for every dependency. But this is still better than not working at all. // See golang.org/issue/26504. func (ctxt *Context) importGo(p *Package, path, srcDir string, mode ImportMode) error { … } func equal(x, y []string) bool { … } // hasGoFiles reports whether dir contains any files with names ending in .go. // For a vendor check we must exclude directories that contain no .go files. // Otherwise it is not possible to vendor just a/b/c and still import the // non-vendored a/b. See golang.org/issue/13832. func hasGoFiles(ctxt *Context, dir string) bool { … } func findImportComment(data []byte) (s string, line int) { … } var slashSlash … var slashStar … var starSlash … var newline … // skipSpaceOrComment returns data with any leading spaces or comments removed. func skipSpaceOrComment(data []byte) []byte { … } // parseWord skips any leading spaces or comments in data // and then parses the beginning of data as an identifier or keyword, // returning that word and what remains after the word. func parseWord(data []byte) (word, rest []byte) { … } // MatchFile reports whether the file with the given name in the given directory // matches the context and would be included in a [Package] created by [ImportDir] // of that directory. // // MatchFile considers the name of the file and may use ctxt.OpenFile to // read some or all of the file's content. func (ctxt *Context) MatchFile(dir, name string) (match bool, err error) { … } var dummyPkg … type fileInfo … type fileImport … type fileEmbed … // matchFile determines whether the file with the given name in the given directory // should be included in the package being constructed. // If the file should be included, matchFile returns a non-nil *fileInfo (and a nil error). // Non-nil errors are reserved for unexpected problems. // // If name denotes a Go program, matchFile reads until the end of the // imports and returns that section of the file in the fileInfo's header field, // even though it only considers text until the first non-comment // for go:build lines. // // If allTags is non-nil, matchFile records any encountered build tag // by setting allTags[tag] = true. func (ctxt *Context) matchFile(dir, name string, allTags map[string]bool, binaryOnly *bool, fset *token.FileSet) (*fileInfo, error) { … } func cleanDecls(m map[string][]token.Position) ([]string, map[string][]token.Position) { … } // Import is shorthand for Default.Import. func Import(path, srcDir string, mode ImportMode) (*Package, error) { … } // ImportDir is shorthand for Default.ImportDir. func ImportDir(dir string, mode ImportMode) (*Package, error) { … } var plusBuild … var goBuildComment … var errMultipleGoBuild … func isGoBuildComment(line []byte) bool { … } var binaryOnlyComment … // 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 '//go:build' are taken as build directives. // // The file is accepted only if each such line lists something // matching the file. For example: // // //go:build windows linux // // marks the file as applicable only on Windows and Linux. // // For each build tag it consults, shouldBuild sets allTags[tag] = true. // // shouldBuild reports whether the file should be built // and whether a //go:binary-only-package comment was found. func (ctxt *Context) shouldBuild(content []byte, allTags map[string]bool) (shouldBuild, binaryOnly bool, err error) { … } // parseFileHeader should be an internal detail, // but widely used packages access it using linkname. // Notable members of the hall of shame include: // - github.com/bazelbuild/bazel-gazelle // // Do not remove or change the type signature. // See go.dev/issue/67401. // //go:linkname parseFileHeader func parseFileHeader(content []byte) (trimmed, goBuild []byte, sawBinaryOnly bool, err error) { … } // saveCgo saves the information from the #cgo lines in the import "C" comment. // These lines set CFLAGS, CPPFLAGS, CXXFLAGS and LDFLAGS and pkg-config directives // that affect the way cgo's C code is built. func (ctxt *Context) saveCgo(filename string, di *Package, cg *ast.CommentGroup) error { … } // expandSrcDir expands any occurrence of ${SRCDIR}, making sure // the result is safe for the shell. func expandSrcDir(str string, srcdir string) (string, bool) { … } // makePathsAbsolute looks for compiler options that take paths and // makes them absolute. We do this because through the 1.8 release we // ran the compiler in the package directory, so any relative -I or -L // options would be relative to that directory. In 1.9 we changed to // running the compiler in the build directory, to get consistent // build results (issue #19964). To keep builds working, we change any // relative -I or -L options to be absolute. // // Using filepath.IsAbs and filepath.Join here means the results will be // different on different systems, but that's OK: -I and -L options are // inherently system-dependent. func (ctxt *Context) makePathsAbsolute(args []string, srcDir string) { … } const safeString … func safeCgoName(s string) bool { … } // splitQuoted splits the string s around each instance of one or more consecutive // white space characters while taking into account quotes and escaping, and // returns an array of substrings of s or an empty list if s contains only white space. // Single quotes and double quotes are recognized to prevent splitting within the // quoted region, and are removed from the resulting substrings. If a quote in s // isn't closed err will be set and r will have the unclosed argument as the // last element. The backslash is used for escaping. // // For example, the following string: // // a b:"c d" 'e''f' "g\"" // // Would be parsed as: // // []string{"a", "b:c d", "ef", `g"`} func splitQuoted(s string) (r []string, err error) { … } // matchAuto interprets text as either a +build or //go:build expression (whichever works), // reporting whether the expression matches the build context. // // matchAuto is only used for testing of tag evaluation // and in #cgo lines, which accept either syntax. func (ctxt *Context) matchAuto(text string, allTags map[string]bool) bool { … } func (ctxt *Context) eval(x constraint.Expr, allTags map[string]bool) bool { … } // matchTag reports whether the name is one of: // // cgo (if cgo is enabled) // $GOOS // $GOARCH // ctxt.Compiler // linux (if GOOS = android) // solaris (if GOOS = illumos) // darwin (if GOOS = ios) // unix (if this is a Unix GOOS) // boringcrypto (if GOEXPERIMENT=boringcrypto is enabled) // tag (if tag is listed in ctxt.BuildTags, ctxt.ToolTags, or ctxt.ReleaseTags) // // It records all consulted tags in allTags. func (ctxt *Context) matchTag(name string, allTags map[string]bool) bool { … } // goodOSArchFile 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. func (ctxt *Context) goodOSArchFile(name string, allTags map[string]bool) bool { … } var ToolDir … // IsLocalImport reports whether the import path is // a local import path, like ".", "..", "./foo", or "../foo". func IsLocalImport(path string) bool { … } // ArchChar returns "?" and an error. // In earlier versions of Go, the returned string was used to derive // the compiler and linker tool names, the default object file suffix, // and the default linker output name. As of Go 1.5, those strings // no longer vary by architecture; they are compile, link, .o, and a.out, respectively. func ArchChar(goarch string) (string, error) { … }