LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2013 The Go Authors. All rights reserved. | 1 // Copyright 2013 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 // oracle: a tool for answering questions about Go source code. | 5 // oracle: a tool for answering questions about Go source code. |
6 // | 6 // |
7 // Each query prints its results to the standard output in an | 7 // Each query prints its results to the standard output in an |
8 // editor-friendly format. Currently this is just text in a generic | 8 // editor-friendly format. Currently this is just text in a generic |
9 // compiler diagnostic format, but in future we could provide | 9 // compiler diagnostic format, but in future we could provide |
10 // sexpr/json/python formats for the raw data so that editors can | 10 // sexpr/json/python formats for the raw data so that editors can |
11 // provide more sophisticated UIs. | 11 // provide more sophisticated UIs. |
12 // | 12 // |
13 // Every line of output is of the form "pos: text", where pos = "-" if unknown. | 13 // Every line of output is of the form "pos: text", where pos = "-" if unknown. |
14 // | 14 // |
15 package main | 15 package main |
16 | 16 |
17 import ( | 17 import ( |
18 "bufio" | 18 "bufio" |
| 19 "bytes" |
| 20 "encoding/json" |
19 "flag" | 21 "flag" |
20 "fmt" | 22 "fmt" |
21 "io" | 23 "io" |
22 "log" | 24 "log" |
23 "os" | 25 "os" |
24 "runtime" | 26 "runtime" |
25 "runtime/pprof" | 27 "runtime/pprof" |
26 | 28 |
27 "code.google.com/p/go.tools/oracle" | 29 "code.google.com/p/go.tools/oracle" |
28 ) | 30 ) |
29 | 31 |
30 var posFlag = flag.String("pos", "", | 32 var posFlag = flag.String("pos", "", |
31 "Filename and offset or extent of a syntax element about which to query,
"+ | 33 "Filename and offset or extent of a syntax element about which to query,
"+ |
32 "e.g. foo.go:123-456, bar.go:123.") | 34 "e.g. foo.go:123-456, bar.go:123.") |
33 | 35 |
34 var modeFlag = flag.String("mode", "", | 36 var modeFlag = flag.String("mode", "", |
35 "Mode of query to perform: callers, callees, callstack, callgraph, descr
ibe.") | 37 "Mode of query to perform: callers, callees, callstack, callgraph, descr
ibe.") |
36 | 38 |
37 var ptalogFlag = flag.String("ptalog", "", | 39 var ptalogFlag = flag.String("ptalog", "", |
38 "Location of the points-to analysis log file, or empty to disable loggin
g.") | 40 "Location of the points-to analysis log file, or empty to disable loggin
g.") |
| 41 |
| 42 var formatFlag = flag.String("format", "plain", "Output format: 'plain' or 'json
'.") |
39 | 43 |
40 const usage = `Go source code oracle. | 44 const usage = `Go source code oracle. |
41 Usage: oracle [<flag> ...] [<file.go> ...] [<arg> ...] | 45 Usage: oracle [<flag> ...] [<file.go> ...] [<arg> ...] |
42 Use -help flag to display options. | 46 Use -help flag to display options. |
43 | 47 |
44 Examples: | 48 Examples: |
45 % oracle -pos 'hello.go 123' hello.go | 49 % oracle -pos 'hello.go 123' hello.go |
46 % oracle -pos 'hello.go 123 456' hello.go | 50 % oracle -pos 'hello.go 123 456' hello.go |
47 ` | 51 ` |
48 | 52 |
49 var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") | 53 var cpuprofile = flag.String("cpuprofile", "", "write cpu profile to file") |
50 | 54 |
51 // TODO(adonovan): the caller must---before go/build.init | 55 // TODO(adonovan): the caller must---before go/build.init |
52 // runs---specify CGO_ENABLED=0, which entails the "!cgo" go/build | 56 // runs---specify CGO_ENABLED=0, which entails the "!cgo" go/build |
53 // tag, preferring (dummy) Go to native C implementations of | 57 // tag, preferring (dummy) Go to native C implementations of |
54 // cgoLookupHost et al. | 58 // cgoLookupHost et al. |
55 | 59 |
56 func init() { | 60 func init() { |
57 // If $GOMAXPROCS isn't set, use the full capacity of the machine. | 61 // If $GOMAXPROCS isn't set, use the full capacity of the machine. |
58 // For small machines, use at least 4 threads. | 62 // For small machines, use at least 4 threads. |
59 if os.Getenv("GOMAXPROCS") == "" { | 63 if os.Getenv("GOMAXPROCS") == "" { |
60 n := runtime.NumCPU() | 64 n := runtime.NumCPU() |
61 if n < 4 { | 65 if n < 4 { |
62 n = 4 | 66 n = 4 |
63 } | 67 } |
64 runtime.GOMAXPROCS(n) | 68 runtime.GOMAXPROCS(n) |
| 69 } |
| 70 |
| 71 // For now, caller must---before go/build.init runs---specify |
| 72 // CGO_ENABLED=0, which entails the "!cgo" go/build tag, |
| 73 // preferring (dummy) Go to native C implementations of |
| 74 // cgoLookupHost et al. |
| 75 // TODO(adonovan): make the importer do this. |
| 76 if os.Getenv("CGO_ENABLED") != "0" { |
| 77 fmt.Fprint(os.Stderr, "Warning: CGO_ENABLED=0 not specified; "+ |
| 78 "analysis of cgo code may be less precise.\n") |
65 } | 79 } |
66 } | 80 } |
67 | 81 |
68 func main() { | 82 func main() { |
69 flag.Parse() | 83 flag.Parse() |
70 args := flag.Args() | 84 args := flag.Args() |
71 | 85 |
72 if len(args) == 0 { | 86 if len(args) == 0 { |
73 fmt.Fprint(os.Stderr, usage) | 87 fmt.Fprint(os.Stderr, usage) |
74 os.Exit(1) | 88 os.Exit(1) |
(...skipping 17 matching lines...) Expand all Loading... |
92 // Profiling support. | 106 // Profiling support. |
93 if *cpuprofile != "" { | 107 if *cpuprofile != "" { |
94 f, err := os.Create(*cpuprofile) | 108 f, err := os.Create(*cpuprofile) |
95 if err != nil { | 109 if err != nil { |
96 log.Fatal(err) | 110 log.Fatal(err) |
97 } | 111 } |
98 pprof.StartCPUProfile(f) | 112 pprof.StartCPUProfile(f) |
99 defer pprof.StopCPUProfile() | 113 defer pprof.StopCPUProfile() |
100 } | 114 } |
101 | 115 |
102 » if err := oracle.Main(args, *modeFlag, *posFlag, ptalog, os.Stdout, nil)
; err != nil { | 116 » // -format flag |
103 » » fmt.Fprintln(os.Stderr, err.Error()) | 117 » if *formatFlag != "json" && *formatFlag != "plain" { |
| 118 » » fmt.Fprintf(os.Stderr, "illegal -format value: %q", *formatFlag) |
104 os.Exit(1) | 119 os.Exit(1) |
105 } | 120 } |
| 121 |
| 122 // Ask the oracle. |
| 123 res, err := oracle.Query(args, *modeFlag, *posFlag, ptalog, nil) |
| 124 if err != nil { |
| 125 fmt.Fprintln(os.Stderr, err) |
| 126 os.Exit(1) |
| 127 } |
| 128 |
| 129 // Print the result. |
| 130 switch *formatFlag { |
| 131 case "json": |
| 132 b, err := json.Marshal(res) |
| 133 if err != nil { |
| 134 fmt.Fprintf(os.Stderr, "JSON error: %s\n", err.Error()) |
| 135 os.Exit(1) |
| 136 } |
| 137 var buf bytes.Buffer |
| 138 if err := json.Indent(&buf, b, "", "\t"); err != nil { |
| 139 fmt.Fprintf(os.Stderr, "json.Indent failed: %s", err) |
| 140 os.Exit(1) |
| 141 } |
| 142 os.Stdout.Write(buf.Bytes()) |
| 143 |
| 144 case "plain": |
| 145 res.WriteTo(os.Stdout) |
| 146 } |
106 } | 147 } |
LEFT | RIGHT |