2013-08-27 16:49:13 -06:00
|
|
|
// Copyright 2013 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.
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
// oracle: a tool for answering questions about Go source code.
|
|
|
|
//
|
2013-09-04 12:35:24 -06:00
|
|
|
// With -format=plain, the oracle prints query results to the standard
|
|
|
|
// output in an editor-friendly format in which every line of output
|
|
|
|
// is of the form "pos: text", where pos = "-" if unknown.
|
2013-08-27 15:58:26 -06:00
|
|
|
//
|
2013-09-04 12:35:24 -06:00
|
|
|
// With -format=json, the oracle prints structured data in JSON syntax.
|
2013-08-27 15:58:26 -06:00
|
|
|
//
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2013-09-03 13:29:02 -06:00
|
|
|
"bytes"
|
|
|
|
"encoding/json"
|
2013-08-27 15:58:26 -06:00
|
|
|
"flag"
|
|
|
|
"fmt"
|
2013-09-04 11:15:49 -06:00
|
|
|
"go/build"
|
2013-08-27 15:58:26 -06:00
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"os"
|
|
|
|
"runtime"
|
|
|
|
"runtime/pprof"
|
|
|
|
|
|
|
|
"code.google.com/p/go.tools/oracle"
|
|
|
|
)
|
|
|
|
|
|
|
|
var posFlag = flag.String("pos", "",
|
2013-09-04 12:35:24 -06:00
|
|
|
"Filename and byte offset or extent of a syntax element about which to query, "+
|
|
|
|
"e.g. foo.go:#123-#456, bar.go:#123.")
|
2013-08-27 15:58:26 -06:00
|
|
|
|
|
|
|
var modeFlag = flag.String("mode", "",
|
2013-09-04 12:35:24 -06:00
|
|
|
"Mode of query to perform: e.g. callers, describe, etc.")
|
2013-08-27 15:58:26 -06:00
|
|
|
|
2013-08-29 19:32:49 -06:00
|
|
|
var ptalogFlag = flag.String("ptalog", "",
|
2013-08-27 15:58:26 -06:00
|
|
|
"Location of the points-to analysis log file, or empty to disable logging.")
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
var formatFlag = flag.String("format", "plain", "Output format: 'plain' or 'json'.")
|
|
|
|
|
2013-08-27 15:58:26 -06:00
|
|
|
const usage = `Go source code oracle.
|
|
|
|
Usage: oracle [<flag> ...] [<file.go> ...] [<arg> ...]
|
|
|
|
Use -help flag to display options.
|
|
|
|
|
|
|
|
Examples:
|
2013-09-04 12:35:24 -06:00
|
|
|
% oracle -pos=hello.go:#123 hello.go
|
|
|
|
% oracle -pos=hello.go:#123-#456 hello.go
|
2013-08-27 15:58:26 -06:00
|
|
|
`
|
|
|
|
|
|
|
|
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file")
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
// If $GOMAXPROCS isn't set, use the full capacity of the machine.
|
|
|
|
// For small machines, use at least 4 threads.
|
|
|
|
if os.Getenv("GOMAXPROCS") == "" {
|
|
|
|
n := runtime.NumCPU()
|
|
|
|
if n < 4 {
|
|
|
|
n = 4
|
|
|
|
}
|
|
|
|
runtime.GOMAXPROCS(n)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
flag.Parse()
|
|
|
|
args := flag.Args()
|
|
|
|
|
|
|
|
if len(args) == 0 {
|
|
|
|
fmt.Fprint(os.Stderr, usage)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Set up points-to analysis log file.
|
|
|
|
var ptalog io.Writer
|
|
|
|
if *ptalogFlag != "" {
|
|
|
|
if f, err := os.Create(*ptalogFlag); err != nil {
|
|
|
|
log.Fatalf(err.Error())
|
|
|
|
} else {
|
|
|
|
buf := bufio.NewWriter(f)
|
|
|
|
ptalog = buf
|
|
|
|
defer func() {
|
|
|
|
buf.Flush()
|
|
|
|
f.Close()
|
|
|
|
}()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Profiling support.
|
|
|
|
if *cpuprofile != "" {
|
|
|
|
f, err := os.Create(*cpuprofile)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
pprof.StartCPUProfile(f)
|
|
|
|
defer pprof.StopCPUProfile()
|
|
|
|
}
|
|
|
|
|
2013-09-03 13:29:02 -06:00
|
|
|
// -format flag
|
|
|
|
if *formatFlag != "json" && *formatFlag != "plain" {
|
2013-09-04 13:20:38 -06:00
|
|
|
fmt.Fprintf(os.Stderr, "Error: illegal -format value: %q", *formatFlag)
|
2013-09-03 13:29:02 -06:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ask the oracle.
|
2013-09-04 11:15:49 -06:00
|
|
|
res, err := oracle.Query(args, *modeFlag, *posFlag, ptalog, &build.Default)
|
2013-09-03 13:29:02 -06:00
|
|
|
if err != nil {
|
2013-09-04 13:20:38 -06:00
|
|
|
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
|
2013-08-27 15:58:26 -06:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
2013-09-03 13:29:02 -06:00
|
|
|
|
|
|
|
// Print the result.
|
|
|
|
switch *formatFlag {
|
|
|
|
case "json":
|
|
|
|
b, err := json.Marshal(res)
|
|
|
|
if err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "JSON error: %s\n", err.Error())
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
var buf bytes.Buffer
|
|
|
|
if err := json.Indent(&buf, b, "", "\t"); err != nil {
|
|
|
|
fmt.Fprintf(os.Stderr, "json.Indent failed: %s", err)
|
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
os.Stdout.Write(buf.Bytes())
|
|
|
|
|
|
|
|
case "plain":
|
|
|
|
res.WriteTo(os.Stdout)
|
|
|
|
}
|
2013-08-27 15:58:26 -06:00
|
|
|
}
|