// Copyright 2015 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. // +build go1.8,!go1.9 // TODO(adonovan) determine which versions we need to test here // +build !windows package loader_test import ( "fmt" "go/token" "log" "path/filepath" "runtime" "sort" "strings" "golang.org/x/tools/go/loader" ) func printProgram(prog *loader.Program) { // Created packages are the initial packages specified by a call // to CreateFromFilenames or CreateFromFiles. var names []string for _, info := range prog.Created { names = append(names, info.Pkg.Path()) } fmt.Printf("created: %s\n", names) // Imported packages are the initial packages specified by a // call to Import or ImportWithTests. names = nil for _, info := range prog.Imported { if strings.Contains(info.Pkg.Path(), "internal") { continue // skip, to reduce fragility } names = append(names, info.Pkg.Path()) } sort.Strings(names) fmt.Printf("imported: %s\n", names) // InitialPackages contains the union of created and imported. names = nil for _, info := range prog.InitialPackages() { names = append(names, info.Pkg.Path()) } sort.Strings(names) fmt.Printf("initial: %s\n", names) // AllPackages contains all initial packages and their dependencies. names = nil for pkg := range prog.AllPackages { names = append(names, pkg.Path()) } sort.Strings(names) fmt.Printf("all: %s\n", names) } func printFilenames(fset *token.FileSet, info *loader.PackageInfo) { var names []string for _, f := range info.Files { names = append(names, filepath.Base(fset.File(f.Pos()).Name())) } fmt.Printf("%s.Files: %s\n", info.Pkg.Path(), names) } // This example loads a set of packages and all of their dependencies // from a typical command-line. FromArgs parses a command line and // makes calls to the other methods of Config shown in the examples that // follow. func ExampleConfig_FromArgs() { args := []string{"mytool", "unicode/utf8", "errors", "runtime", "--", "foo", "bar"} const wantTests = false var conf loader.Config rest, err := conf.FromArgs(args[1:], wantTests) prog, err := conf.Load() if err != nil { log.Fatal(err) } fmt.Printf("rest: %s\n", rest) printProgram(prog) // Output: // rest: [foo bar] // created: [] // imported: [errors runtime unicode/utf8] // initial: [errors runtime unicode/utf8] // all: [errors runtime runtime/internal/atomic runtime/internal/sys unicode/utf8 unsafe] } // This example creates and type-checks a single package (without tests) // from a list of filenames, and loads all of its dependencies. // (The input files are actually only a small part of the math/cmplx package.) func ExampleConfig_CreateFromFilenames() { var conf loader.Config conf.CreateFromFilenames("math/cmplx", filepath.Join(runtime.GOROOT(), "src/math/cmplx/abs.go"), filepath.Join(runtime.GOROOT(), "src/math/cmplx/sin.go")) prog, err := conf.Load() if err != nil { log.Fatal(err) } printProgram(prog) // Output: // created: [math/cmplx] // imported: [] // initial: [math/cmplx] // all: [math math/cmplx unsafe] } // In the examples below, for stability, the chosen packages are // relatively small, platform-independent, and low-level (and thus // infrequently changing). // The strconv package has internal and external tests. const hello = `package main import "fmt" func main() { fmt.Println("Hello, world.") } ` // This example creates and type-checks a package from a list of // already-parsed files, and loads all its dependencies. func ExampleConfig_CreateFromFiles() { var conf loader.Config f, err := conf.ParseFile("hello.go", hello) if err != nil { log.Fatal(err) } conf.CreateFromFiles("hello", f) prog, err := conf.Load() if err != nil { log.Fatal(err) } printProgram(prog) printFilenames(prog.Fset, prog.Package("strconv")) // Output: // created: [hello] // imported: [] // initial: [hello] // all: [errors fmt hello internal/race io math os reflect runtime runtime/internal/atomic runtime/internal/sys strconv sync sync/atomic syscall time unicode/utf8 unsafe] // strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go] } // This example imports three packages, including the tests for one of // them, and loads all their dependencies. func ExampleConfig_Import() { // ImportWithTest("strconv") causes strconv to include // internal_test.go, and creates an external test package, // strconv_test. // (Compare with the example of CreateFromFiles.) var conf loader.Config conf.Import("unicode/utf8") conf.Import("errors") conf.ImportWithTests("strconv") prog, err := conf.Load() if err != nil { log.Fatal(err) } printProgram(prog) printFilenames(prog.Fset, prog.Package("strconv")) printFilenames(prog.Fset, prog.Package("strconv_test")) // Output: // created: [strconv_test] // imported: [errors strconv unicode/utf8] // initial: [errors strconv strconv_test unicode/utf8] // all: [bufio bytes errors flag fmt internal/race io log math math/rand os reflect runtime runtime/debug runtime/internal/atomic runtime/internal/sys runtime/trace sort strconv strconv_test strings sync sync/atomic syscall testing time unicode unicode/utf8 unsafe] // strconv.Files: [atob.go atof.go atoi.go decimal.go doc.go extfloat.go ftoa.go isprint.go itoa.go quote.go internal_test.go] // strconv_test.Files: [atob_test.go atof_test.go atoi_test.go decimal_test.go example_test.go fp_test.go ftoa_test.go itoa_test.go quote_test.go strconv_test.go] }