// Copyright 2011-2015 visualfc . All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. package oracle import ( "fmt" "go/build" "log" "os" "runtime" "github.com/visualfc/gotools/command" "golang.org/x/tools/oracle" ) //The mode argument determines the query to perform: // callees show possible targets of selected function call // callers show possible callers of selected function // callgraph show complete callgraph of program // callstack show path from callgraph root to selected function // describe describe selected syntax: definition, methods, etc // freevars show free variables of selection // implements show 'implements' relation for selected type // peers show send/receive corresponding to selected channel op // referrers show all refs to entity denoted by selected identifier // what show basic information about the selected syntax node var Command = &command.Command{ Run: runOracle, UsageLine: "oracle", Short: "golang oracle util", Long: `golang oracle util.`, } var ( oraclePos string oracleReflect bool ) func init() { Command.Flag.StringVar(&oraclePos, "pos", "", "filename:#offset") Command.Flag.BoolVar(&oracleReflect, "reflect", false, "Analyze reflection soundly (slow).") } func runOracle(cmd *command.Command, args []string) error { if len(args) < 2 { cmd.Usage() return os.ErrInvalid } if os.Getenv("GOMAXPROCS") == "" { n := runtime.NumCPU() if n < 4 { n = 4 } runtime.GOMAXPROCS(n) } mode := args[0] args = args[1:] if args[0] == "." { pkgPath, err := os.Getwd() if err != nil { log.Fatalln(err) } pkg, err := build.Default.ImportDir(pkgPath, 0) if err != nil { log.Fatalln(err) } args = pkg.GoFiles //log.Println(pkg.ImportPath) if pkg.ImportPath != "." && pkg.ImportPath != "" { args = []string{pkg.ImportPath} } } query := oracle.Query{ Mode: mode, Pos: oraclePos, Build: &build.Default, Scope: args, PTALog: nil, Reflection: oracleReflect, } if err := oracle.Run(&query); err != nil { fmt.Fprintf(os.Stderr, "oracle: %s.\n", err) return err } if mode == "referrers" { ref := query.Serial().Referrers if ref != nil { fmt.Fprintln(os.Stdout, ref.Desc) fmt.Fprintln(os.Stdout, ref.ObjPos) for _, v := range ref.Refs { fmt.Fprintln(os.Stdout, v) } } } else { query.WriteTo(os.Stdout) } return nil }