本文整理匯總了Golang中golang.org/x/tools/go/loader.Config.TypeCheckFuncBodies方法的典型用法代碼示例。如果您正苦於以下問題:Golang Config.TypeCheckFuncBodies方法的具體用法?Golang Config.TypeCheckFuncBodies怎麽用?Golang Config.TypeCheckFuncBodies使用的例子?那麽, 這裏精選的方法代碼示例或許可以為您提供幫助。您也可以進一步了解該方法所在類golang.org/x/tools/go/loader.Config
的用法示例。
在下文中一共展示了Config.TypeCheckFuncBodies方法的10個代碼示例,這些例子默認根據受歡迎程度排序。您可以為喜歡或者感覺有用的代碼點讚,您的評價將有助於係統推薦出更棒的Golang代碼示例。
示例1: loadProgram
// loadProgram loads the specified set of packages (plus their tests)
// and all their dependencies, from source, through the specified build
// context. Only packages in pkgs will have their functions bodies typechecked.
func loadProgram(ctxt *build.Context, pkgs map[string]bool) (*loader.Program, error) {
conf := loader.Config{
Build: ctxt,
SourceImports: true,
ParserMode: parser.ParseComments,
// TODO(adonovan): enable this. Requires making a lot of code more robust!
AllowErrors: false,
}
// Optimization: don't type-check the bodies of functions in our
// dependencies, since we only need exported package members.
conf.TypeCheckFuncBodies = func(p string) bool {
return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
}
if Verbose {
var list []string
for pkg := range pkgs {
list = append(list, pkg)
}
sort.Strings(list)
for _, pkg := range list {
fmt.Fprintf(os.Stderr, "Loading package: %s\n", pkg)
}
}
for pkg := range pkgs {
if err := conf.ImportWithTests(pkg); err != nil {
return nil, err
}
}
return conf.Load()
}
示例2: Parse
func (p *Parser) Parse(path string) error {
dir := filepath.Dir(path)
files, err := ioutil.ReadDir(dir)
if err != nil {
fmt.Printf("// [ERROR] Parse(%s) -> ioutil.ReadDir(%#v) -> err=<%#v>\n", path, dir, err)
return err
}
var astFiles []*ast.File
var conf loader.Config
conf.TypeCheckFuncBodies = func(_ string) bool { return false }
conf.TypeChecker.DisableUnusedImportCheck = true
conf.TypeChecker.Importer = importer.Default()
for _, fi := range files {
if filepath.Ext(fi.Name()) != ".go" {
continue
}
fpath := filepath.Join(dir, fi.Name())
f, err := conf.ParseFile(fpath, nil)
if err != nil {
fmt.Printf("// [ERROR] Parse(%s) -> conf.ParseFile(%#v) -> err=<%#v>\n", path, fpath, err)
return err
}
if fi.Name() == filepath.Base(path) {
p.file = f
}
astFiles = append(astFiles, f)
}
abs, err := filepath.Abs(path)
if err != nil {
fmt.Printf("// [ERROR] Parse(%s) -> filepath.Abs(%#v) -> err=<%#v>\n", path, path, err)
return err
}
// Type-check a package consisting of this file.
// Type information for the imported packages
// comes from $GOROOT/pkg/$GOOS_$GOOARCH/fmt.a.
conf.CreateFromFiles(abs, astFiles...)
prog, err := conf.Load()
if err != nil {
fmt.Printf("// [ERROR] Parse(%s) -> conf.Load() -> err=<%#v>\n", path, err)
return err
} else if len(prog.Created) != 1 {
panic("expected only one Created package")
}
p.path = abs
p.pkg = prog.Created[0].Pkg
return nil
}
示例3: reduceScope
// reduceScope is called for one-shot queries that need only a single
// typed package. It attempts to guess the query package from pos and
// reduce the analysis scope (set of loaded packages) to just that one
// plus (the exported parts of) its dependencies. It leaves its
// arguments unchanged on failure.
//
// TODO(adonovan): this is a real mess... but it's fast.
//
func reduceScope(pos string, conf *loader.Config) {
fqpos, err := fastQueryPos(pos)
if err != nil {
return // bad query
}
// TODO(adonovan): fix: this gives the wrong results for files
// in non-importable packages such as tests and ad-hoc packages
// specified as a list of files (incl. the oracle's tests).
_, importPath, err := guessImportPath(fqpos.fset.File(fqpos.start).Name(), conf.Build)
if err != nil {
return // can't find GOPATH dir
}
if importPath == "" {
return
}
// Check that it's possible to load the queried package.
// (e.g. oracle tests contain different 'package' decls in same dir.)
// Keep consistent with logic in loader/util.go!
cfg2 := *conf.Build
cfg2.CgoEnabled = false
bp, err := cfg2.Import(importPath, "", 0)
if err != nil {
return // no files for package
}
// Check that the queried file appears in the package:
// it might be a '// +build ignore' from an ad-hoc main
// package, e.g. $GOROOT/src/net/http/triv.go.
if !pkgContainsFile(bp, fqpos.fset.File(fqpos.start).Name()) {
return // not found
}
conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
// Ignore packages specified on command line.
conf.CreatePkgs = nil
conf.ImportPkgs = nil
// Instead load just the one containing the query position
// (and possibly its corresponding tests/production code).
// TODO(adonovan): set 'augment' based on which file list
// contains
_ = conf.ImportWithTests(importPath) // ignore error
}
示例4: importQueryPackage
// importQueryPackage finds the package P containing the
// query position and tells conf to import it.
// It returns the package's path.
func importQueryPackage(pos string, conf *loader.Config) (string, error) {
fqpos, err := fastQueryPos(pos)
if err != nil {
return "", err // bad query
}
filename := fqpos.fset.File(fqpos.start).Name()
// This will not work for ad-hoc packages
// such as $GOROOT/src/net/http/triv.go.
// TODO(adonovan): ensure we report a clear error.
_, importPath, err := guessImportPath(filename, conf.Build)
if err != nil {
return "", err // can't find GOPATH dir
}
if importPath == "" {
return "", fmt.Errorf("can't guess import path from %s", filename)
}
// Check that it's possible to load the queried package.
// (e.g. oracle tests contain different 'package' decls in same dir.)
// Keep consistent with logic in loader/util.go!
cfg2 := *conf.Build
cfg2.CgoEnabled = false
bp, err := cfg2.Import(importPath, "", 0)
if err != nil {
return "", err // no files for package
}
switch pkgContainsFile(bp, filename) {
case 'T':
conf.ImportWithTests(importPath)
case 'X':
conf.ImportWithTests(importPath)
importPath += "_test" // for TypeCheckFuncBodies
case 'G':
conf.Import(importPath)
default:
return "", fmt.Errorf("package %q doesn't contain file %s",
importPath, filename)
}
conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
return importPath, nil
}
示例5: importQueryPackage
// importQueryPackage finds the package P containing the
// query position and tells conf to import it.
// It returns the package's path.
func importQueryPackage(pos string, conf *loader.Config) (string, error) {
fqpos, err := fastQueryPos(conf.Build, pos)
if err != nil {
return "", err // bad query
}
filename := fqpos.fset.File(fqpos.start).Name()
_, importPath, err := guessImportPath(filename, conf.Build)
if err != nil {
// Can't find GOPATH dir.
// Treat the query file as its own package.
importPath = "command-line-arguments"
conf.CreateFromFilenames(importPath, filename)
} else {
// Check that it's possible to load the queried package.
// (e.g. guru tests contain different 'package' decls in same dir.)
// Keep consistent with logic in loader/util.go!
cfg2 := *conf.Build
cfg2.CgoEnabled = false
bp, err := cfg2.Import(importPath, "", 0)
if err != nil {
return "", err // no files for package
}
switch pkgContainsFile(bp, filename) {
case 'T':
conf.ImportWithTests(importPath)
case 'X':
conf.ImportWithTests(importPath)
importPath += "_test" // for TypeCheckFuncBodies
case 'G':
conf.Import(importPath)
default:
// This happens for ad-hoc packages like
// $GOROOT/src/net/http/triv.go.
return "", fmt.Errorf("package %q doesn't contain file %s",
importPath, filename)
}
}
conf.TypeCheckFuncBodies = func(p string) bool { return p == importPath }
return importPath, nil
}
示例6: loadProgram
func (u *Unexporter) loadProgram(pkgPath string) (err error) {
wd, err := os.Getwd()
if err != nil {
return err
}
bpkg, err := u.ctxt.Import(pkgPath, wd, build.ImportComment)
if err != nil {
return err
}
_, rev, _ := importgraph.Build(u.ctxt)
pkgs := rev.Search(bpkg.ImportPath)
conf := loader.Config{
Build: u.ctxt,
ParserMode: parser.ParseComments,
AllowErrors: false,
}
// Optimization: don't type-check the bodies of functions in our
// dependencies, since we only need exported package members.
conf.TypeCheckFuncBodies = func(p string) bool {
return pkgs[p] || pkgs[strings.TrimSuffix(p, "_test")]
}
for pkg := range pkgs {
conf.ImportWithTests(pkg)
}
u.prog, err = conf.Load()
if err != nil {
return
}
for p, info := range u.prog.AllPackages {
if p.Path() == bpkg.ImportPath {
u.pkgInfo = info
break
}
}
return
}
示例7: globalReferrers
// globalReferrers reports references throughout the entire workspace to the
// object at the specified source position. Its defining package is defpkg,
// and the query package is qpkg. isPkgLevel indicates whether the object
// is defined at package-level.
func globalReferrers(q *Query, qpkg, defpkg string, objposn token.Position, isPkgLevel bool) error {
// Scan the workspace and build the import graph.
// Ignore broken packages.
_, rev, _ := importgraph.Build(q.Build)
// Find the set of packages that depend on defpkg.
// Only function bodies in those packages need type-checking.
var users map[string]bool
if isPkgLevel {
users = rev[defpkg] // direct importers
if users == nil {
users = make(map[string]bool)
}
users[defpkg] = true // plus the defining package itself
} else {
users = rev.Search(defpkg) // transitive importers
}
// Prepare to load the larger program.
fset := token.NewFileSet()
lconf := loader.Config{
Fset: fset,
Build: q.Build,
TypeCheckFuncBodies: func(p string) bool {
return users[strings.TrimSuffix(p, "_test")]
},
}
allowErrors(&lconf)
// The importgraph doesn't treat external test packages
// as separate nodes, so we must use ImportWithTests.
for path := range users {
lconf.ImportWithTests(path)
}
// The remainder of this function is somewhat tricky because it
// operates on the concurrent stream of packages observed by the
// loader's AfterTypeCheck hook. Most of guru's helper
// functions assume the entire program has already been loaded,
// so we can't use them here.
// TODO(adonovan): smooth things out once the other changes have landed.
// Results are reported concurrently from within the
// AfterTypeCheck hook. The program may provide a useful stream
// of information even if the user doesn't let the program run
// to completion.
var (
mu sync.Mutex
qobj types.Object
qinfo *loader.PackageInfo // info for qpkg
)
// For efficiency, we scan each package for references
// just after it has been type-checked. The loader calls
// AfterTypeCheck (concurrently), providing us with a stream of
// packages.
lconf.AfterTypeCheck = func(info *loader.PackageInfo, files []*ast.File) {
// AfterTypeCheck may be called twice for the same package due to augmentation.
// Only inspect packages that depend on the declaring package
// (and thus were type-checked).
if lconf.TypeCheckFuncBodies(info.Pkg.Path()) {
// Record the query object and its package when we see it.
mu.Lock()
if qobj == nil && info.Pkg.Path() == defpkg {
// Find the object by its position (slightly ugly).
qobj = findObject(fset, &info.Info, objposn)
if qobj == nil {
// It really ought to be there;
// we found it once already.
log.Fatalf("object at %s not found in package %s",
objposn, defpkg)
}
// Object found.
qinfo = info
q.Output(fset, &referrersInitialResult{
qinfo: qinfo,
obj: qobj,
})
}
obj := qobj
mu.Unlock()
// Look for references to the query object.
if obj != nil {
outputUses(q, fset, usesOf(obj, info), info.Pkg)
}
}
clearInfoFields(info) // save memory
}
lconf.Load() // ignore error
//.........這裏部分代碼省略.........
示例8: packageReferrers
// packageReferrers reports all references to the specified package
// throughout the workspace.
func packageReferrers(q *Query, path string) error {
// Scan the workspace and build the import graph.
// Ignore broken packages.
_, rev, _ := importgraph.Build(q.Build)
// Find the set of packages that directly import the query package.
// Only those packages need typechecking of function bodies.
users := rev[path]
// Load the larger program.
fset := token.NewFileSet()
lconf := loader.Config{
Fset: fset,
Build: q.Build,
TypeCheckFuncBodies: func(p string) bool {
return users[strings.TrimSuffix(p, "_test")]
},
}
allowErrors(&lconf)
// The importgraph doesn't treat external test packages
// as separate nodes, so we must use ImportWithTests.
for path := range users {
lconf.ImportWithTests(path)
}
// Subtle! AfterTypeCheck needs no mutex for qpkg because the
// topological import order gives us the necessary happens-before edges.
// TODO(adonovan): what about import cycles?
var qpkg *types.Package
// For efficiency, we scan each package for references
// just after it has been type-checked. The loader calls
// AfterTypeCheck (concurrently), providing us with a stream of
// packages.
lconf.AfterTypeCheck = func(info *loader.PackageInfo, files []*ast.File) {
// AfterTypeCheck may be called twice for the same package due to augmentation.
if info.Pkg.Path() == path && qpkg == nil {
// Found the package of interest.
qpkg = info.Pkg
fakepkgname := types.NewPkgName(token.NoPos, qpkg, qpkg.Name(), qpkg)
q.Output(fset, &referrersInitialResult{
qinfo: info,
obj: fakepkgname, // bogus
})
}
// Only inspect packages that directly import the
// declaring package (and thus were type-checked).
if lconf.TypeCheckFuncBodies(info.Pkg.Path()) {
// Find PkgNames that refer to qpkg.
// TODO(adonovan): perhaps more useful would be to show imports
// of the package instead of qualified identifiers.
var refs []*ast.Ident
for id, obj := range info.Uses {
if obj, ok := obj.(*types.PkgName); ok && obj.Imported() == qpkg {
refs = append(refs, id)
}
}
outputUses(q, fset, refs, info.Pkg)
}
clearInfoFields(info) // save memory
}
lconf.Load() // ignore error
if qpkg == nil {
log.Fatalf("query package %q not found during reloading", path)
}
return nil
}
示例9: bundle
func bundle(w io.Writer, initialPkg, dest, prefix string) error {
// Load the initial package.
conf := loader.Config{ParserMode: parser.ParseComments, Build: ctxt}
conf.TypeCheckFuncBodies = func(p string) bool { return p == initialPkg }
conf.Import(initialPkg)
lprog, err := conf.Load()
if err != nil {
log.Fatal(err)
}
info := lprog.Package(initialPkg)
objsToUpdate := make(map[types.Object]bool)
var rename func(from types.Object)
rename = func(from types.Object) {
if !objsToUpdate[from] {
objsToUpdate[from] = true
// Renaming a type that is used as an embedded field
// requires renaming the field too. e.g.
// type T int // if we rename this to U..
// var s struct {T}
// print(s.T) // ...this must change too
if _, ok := from.(*types.TypeName); ok {
for id, obj := range info.Uses {
if obj == from {
if field := info.Defs[id]; field != nil {
rename(field)
}
}
}
}
}
}
// Rename each package-level object.
scope := info.Pkg.Scope()
for _, name := range scope.Names() {
rename(scope.Lookup(name))
}
var out bytes.Buffer
fmt.Fprintf(&out, "// Code generated by golang.org/x/tools/cmd/bundle command:\n")
fmt.Fprintf(&out, "// $ bundle %s %s %s\n\n", initialPkg, dest, prefix)
// Concatenate package comments from of all files.
for _, f := range info.Files {
if doc := f.Doc.Text(); strings.TrimSpace(doc) != "" {
for _, line := range strings.Split(doc, "\n") {
fmt.Fprintf(&out, "// %s\n", line)
}
}
}
// TODO(adonovan): don't assume pkg.name == basename(pkg.path).
fmt.Fprintf(&out, "package %s\n\n", filepath.Base(dest))
// Print a single declaration that imports all necessary packages.
// TODO(adonovan):
// - support renaming imports.
// - preserve comments from the original import declarations.
for _, f := range info.Files {
for _, imp := range f.Imports {
if imp.Name != nil {
log.Fatalf("%s: renaming imports not supported",
lprog.Fset.Position(imp.Pos()))
}
}
}
fmt.Fprintln(&out, "import (")
for _, p := range info.Pkg.Imports() {
if p.Path() == dest {
continue
}
fmt.Fprintf(&out, "\t%q\n", p.Path())
}
fmt.Fprintln(&out, ")\n")
// Modify and print each file.
for _, f := range info.Files {
// Update renamed identifiers.
for id, obj := range info.Defs {
if objsToUpdate[obj] {
id.Name = prefix + obj.Name()
}
}
for id, obj := range info.Uses {
if objsToUpdate[obj] {
id.Name = prefix + obj.Name()
}
}
// For each qualified identifier that refers to the
// destination package, remove the qualifier.
// The "@@@." strings are removed in postprocessing.
ast.Inspect(f, func(n ast.Node) bool {
if sel, ok := n.(*ast.SelectorExpr); ok {
if id, ok := sel.X.(*ast.Ident); ok {
//.........這裏部分代碼省略.........
示例10: bundle
func bundle(src, dst, dstpkg, prefix string) ([]byte, error) {
// Load the initial package.
conf := loader.Config{ParserMode: parser.ParseComments, Build: ctxt}
conf.TypeCheckFuncBodies = func(p string) bool { return p == src }
conf.Import(src)
lprog, err := conf.Load()
if err != nil {
return nil, err
}
info := lprog.Package(src)
if prefix == "" {
pkgName := info.Files[0].Name.Name
prefix = pkgName + "_"
}
objsToUpdate := make(map[types.Object]bool)
var rename func(from types.Object)
rename = func(from types.Object) {
if !objsToUpdate[from] {
objsToUpdate[from] = true
// Renaming a type that is used as an embedded field
// requires renaming the field too. e.g.
// type T int // if we rename this to U..
// var s struct {T}
// print(s.T) // ...this must change too
if _, ok := from.(*types.TypeName); ok {
for id, obj := range info.Uses {
if obj == from {
if field := info.Defs[id]; field != nil {
rename(field)
}
}
}
}
}
}
// Rename each package-level object.
scope := info.Pkg.Scope()
for _, name := range scope.Names() {
rename(scope.Lookup(name))
}
var out bytes.Buffer
fmt.Fprintf(&out, "// Code generated by golang.org/x/tools/cmd/bundle.\n")
if *outputFile != "" {
fmt.Fprintf(&out, "//go:generate bundle %s\n", strings.Join(os.Args[1:], " "))
} else {
fmt.Fprintf(&out, "// $ bundle %s\n", strings.Join(os.Args[1:], " "))
}
fmt.Fprintf(&out, "\n")
// Concatenate package comments from all files...
for _, f := range info.Files {
if doc := f.Doc.Text(); strings.TrimSpace(doc) != "" {
for _, line := range strings.Split(doc, "\n") {
fmt.Fprintf(&out, "// %s\n", line)
}
}
}
// ...but don't let them become the actual package comment.
fmt.Fprintln(&out)
fmt.Fprintf(&out, "package %s\n\n", dstpkg)
// BUG(adonovan,shurcooL): bundle may generate incorrect code
// due to shadowing between identifiers and imported package names.
//
// The generated code will either fail to compile or
// (unlikely) compile successfully but have different behavior
// than the original package. The risk of this happening is higher
// when the original package has renamed imports (they're typically
// renamed in order to resolve a shadow inside that particular .go file).
// TODO(adonovan,shurcooL):
// - detect shadowing issues, and either return error or resolve them
// - preserve comments from the original import declarations.
// pkgStd and pkgExt are sets of printed import specs. This is done
// to deduplicate instances of the same import name and path.
var pkgStd = make(map[string]bool)
var pkgExt = make(map[string]bool)
for _, f := range info.Files {
for _, imp := range f.Imports {
path, err := strconv.Unquote(imp.Path.Value)
if err != nil {
log.Fatalf("invalid import path string: %v", err) // Shouldn't happen here since conf.Load succeeded.
}
if path == dst {
continue
}
if newPath, ok := importMap[path]; ok {
path = newPath
}
var name string
//.........這裏部分代碼省略.........