github.com/pankona/gometalinter@v2.0.11+incompatible/_linters/src/golang.org/x/tools/go/loader/doc.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // Package loader loads a complete Go program from source code, parsing 6 // and type-checking the initial packages plus their transitive closure 7 // of dependencies. The ASTs and the derived facts are retained for 8 // later use. 9 // 10 // THIS INTERFACE IS EXPERIMENTAL AND IS LIKELY TO CHANGE. 11 // 12 // The package defines two primary types: Config, which specifies a 13 // set of initial packages to load and various other options; and 14 // Program, which is the result of successfully loading the packages 15 // specified by a configuration. 16 // 17 // The configuration can be set directly, but *Config provides various 18 // convenience methods to simplify the common cases, each of which can 19 // be called any number of times. Finally, these are followed by a 20 // call to Load() to actually load and type-check the program. 21 // 22 // var conf loader.Config 23 // 24 // // Use the command-line arguments to specify 25 // // a set of initial packages to load from source. 26 // // See FromArgsUsage for help. 27 // rest, err := conf.FromArgs(os.Args[1:], wantTests) 28 // 29 // // Parse the specified files and create an ad hoc package with path "foo". 30 // // All files must have the same 'package' declaration. 31 // conf.CreateFromFilenames("foo", "foo.go", "bar.go") 32 // 33 // // Create an ad hoc package with path "foo" from 34 // // the specified already-parsed files. 35 // // All ASTs must have the same 'package' declaration. 36 // conf.CreateFromFiles("foo", parsedFiles) 37 // 38 // // Add "runtime" to the set of packages to be loaded. 39 // conf.Import("runtime") 40 // 41 // // Adds "fmt" and "fmt_test" to the set of packages 42 // // to be loaded. "fmt" will include *_test.go files. 43 // conf.ImportWithTests("fmt") 44 // 45 // // Finally, load all the packages specified by the configuration. 46 // prog, err := conf.Load() 47 // 48 // See examples_test.go for examples of API usage. 49 // 50 // 51 // CONCEPTS AND TERMINOLOGY 52 // 53 // The WORKSPACE is the set of packages accessible to the loader. The 54 // workspace is defined by Config.Build, a *build.Context. The 55 // default context treats subdirectories of $GOROOT and $GOPATH as 56 // packages, but this behavior may be overridden. 57 // 58 // An AD HOC package is one specified as a set of source files on the 59 // command line. In the simplest case, it may consist of a single file 60 // such as $GOROOT/src/net/http/triv.go. 61 // 62 // EXTERNAL TEST packages are those comprised of a set of *_test.go 63 // files all with the same 'package foo_test' declaration, all in the 64 // same directory. (go/build.Package calls these files XTestFiles.) 65 // 66 // An IMPORTABLE package is one that can be referred to by some import 67 // spec. Every importable package is uniquely identified by its 68 // PACKAGE PATH or just PATH, a string such as "fmt", "encoding/json", 69 // or "cmd/vendor/golang.org/x/arch/x86/x86asm". A package path 70 // typically denotes a subdirectory of the workspace. 71 // 72 // An import declaration uses an IMPORT PATH to refer to a package. 73 // Most import declarations use the package path as the import path. 74 // 75 // Due to VENDORING (https://golang.org/s/go15vendor), the 76 // interpretation of an import path may depend on the directory in which 77 // it appears. To resolve an import path to a package path, go/build 78 // must search the enclosing directories for a subdirectory named 79 // "vendor". 80 // 81 // ad hoc packages and external test packages are NON-IMPORTABLE. The 82 // path of an ad hoc package is inferred from the package 83 // declarations of its files and is therefore not a unique package key. 84 // For example, Config.CreatePkgs may specify two initial ad hoc 85 // packages, both with path "main". 86 // 87 // An AUGMENTED package is an importable package P plus all the 88 // *_test.go files with same 'package foo' declaration as P. 89 // (go/build.Package calls these files TestFiles.) 90 // 91 // The INITIAL packages are those specified in the configuration. A 92 // DEPENDENCY is a package loaded to satisfy an import in an initial 93 // package or another dependency. 94 // 95 package loader 96 97 // IMPLEMENTATION NOTES 98 // 99 // 'go test', in-package test files, and import cycles 100 // --------------------------------------------------- 101 // 102 // An external test package may depend upon members of the augmented 103 // package that are not in the unaugmented package, such as functions 104 // that expose internals. (See bufio/export_test.go for an example.) 105 // So, the loader must ensure that for each external test package 106 // it loads, it also augments the corresponding non-test package. 107 // 108 // The import graph over n unaugmented packages must be acyclic; the 109 // import graph over n-1 unaugmented packages plus one augmented 110 // package must also be acyclic. ('go test' relies on this.) But the 111 // import graph over n augmented packages may contain cycles. 112 // 113 // First, all the (unaugmented) non-test packages and their 114 // dependencies are imported in the usual way; the loader reports an 115 // error if it detects an import cycle. 116 // 117 // Then, each package P for which testing is desired is augmented by 118 // the list P' of its in-package test files, by calling 119 // (*types.Checker).Files. This arrangement ensures that P' may 120 // reference definitions within P, but P may not reference definitions 121 // within P'. Furthermore, P' may import any other package, including 122 // ones that depend upon P, without an import cycle error. 123 // 124 // Consider two packages A and B, both of which have lists of 125 // in-package test files we'll call A' and B', and which have the 126 // following import graph edges: 127 // B imports A 128 // B' imports A 129 // A' imports B 130 // This last edge would be expected to create an error were it not 131 // for the special type-checking discipline above. 132 // Cycles of size greater than two are possible. For example: 133 // compress/bzip2/bzip2_test.go (package bzip2) imports "io/ioutil" 134 // io/ioutil/tempfile_test.go (package ioutil) imports "regexp" 135 // regexp/exec_test.go (package regexp) imports "compress/bzip2" 136 // 137 // 138 // Concurrency 139 // ----------- 140 // 141 // Let us define the import dependency graph as follows. Each node is a 142 // list of files passed to (Checker).Files at once. Many of these lists 143 // are the production code of an importable Go package, so those nodes 144 // are labelled by the package's path. The remaining nodes are 145 // ad hoc packages and lists of in-package *_test.go files that augment 146 // an importable package; those nodes have no label. 147 // 148 // The edges of the graph represent import statements appearing within a 149 // file. An edge connects a node (a list of files) to the node it 150 // imports, which is importable and thus always labelled. 151 // 152 // Loading is controlled by this dependency graph. 153 // 154 // To reduce I/O latency, we start loading a package's dependencies 155 // asynchronously as soon as we've parsed its files and enumerated its 156 // imports (scanImports). This performs a preorder traversal of the 157 // import dependency graph. 158 // 159 // To exploit hardware parallelism, we type-check unrelated packages in 160 // parallel, where "unrelated" means not ordered by the partial order of 161 // the import dependency graph. 162 // 163 // We use a concurrency-safe non-blocking cache (importer.imported) to 164 // record the results of type-checking, whether success or failure. An 165 // entry is created in this cache by startLoad the first time the 166 // package is imported. The first goroutine to request an entry becomes 167 // responsible for completing the task and broadcasting completion to 168 // subsequent requestors, which block until then. 169 // 170 // Type checking occurs in (parallel) postorder: we cannot type-check a 171 // set of files until we have loaded and type-checked all of their 172 // immediate dependencies (and thus all of their transitive 173 // dependencies). If the input were guaranteed free of import cycles, 174 // this would be trivial: we could simply wait for completion of the 175 // dependencies and then invoke the typechecker. 176 // 177 // But as we saw in the 'go test' section above, some cycles in the 178 // import graph over packages are actually legal, so long as the 179 // cycle-forming edge originates in the in-package test files that 180 // augment the package. This explains why the nodes of the import 181 // dependency graph are not packages, but lists of files: the unlabelled 182 // nodes avoid the cycles. Consider packages A and B where B imports A 183 // and A's in-package tests AT import B. The naively constructed import 184 // graph over packages would contain a cycle (A+AT) --> B --> (A+AT) but 185 // the graph over lists of files is AT --> B --> A, where AT is an 186 // unlabelled node. 187 // 188 // Awaiting completion of the dependencies in a cyclic graph would 189 // deadlock, so we must materialize the import dependency graph (as 190 // importer.graph) and check whether each import edge forms a cycle. If 191 // x imports y, and the graph already contains a path from y to x, then 192 // there is an import cycle, in which case the processing of x must not 193 // wait for the completion of processing of y. 194 // 195 // When the type-checker makes a callback (doImport) to the loader for a 196 // given import edge, there are two possible cases. In the normal case, 197 // the dependency has already been completely type-checked; doImport 198 // does a cache lookup and returns it. In the cyclic case, the entry in 199 // the cache is still necessarily incomplete, indicating a cycle. We 200 // perform the cycle check again to obtain the error message, and return 201 // the error. 202 // 203 // The result of using concurrency is about a 2.5x speedup for stdlib_test. 204 205 // TODO(adonovan): overhaul the package documentation.