go.tools/oracle: support -format=xml (for Eclipse)
This CL is mostly a renaming s/json/serial/, abstracting the oracle package away from any particular data syntax. (The encoding/* machinery is very clean; clearly I should have structured it this way from the outset.) Supporting XML then becomes a one-liner in cmd/oracle/main.go. Also: call MarshalIndent(), not Marshall() then Indent(). R=crawshaw CC=golang-dev https://golang.org/cl/13858046
This commit is contained in:
parent
84cae5a52d
commit
37f76edde8
|
@ -14,8 +14,8 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"encoding/xml"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
|
@ -39,7 +39,7 @@ var modeFlag = flag.String("mode", "",
|
||||||
var ptalogFlag = flag.String("ptalog", "",
|
var ptalogFlag = flag.String("ptalog", "",
|
||||||
"Location of the points-to analysis log file, or empty to disable logging.")
|
"Location of the points-to analysis log file, or empty to disable logging.")
|
||||||
|
|
||||||
var formatFlag = flag.String("format", "plain", "Output format: 'plain' or 'json'.")
|
var formatFlag = flag.String("format", "plain", "Output format. One of {plain,json,xml}.")
|
||||||
|
|
||||||
// TODO(adonovan): eliminate or flip this flag after PTA presolver is implemented.
|
// TODO(adonovan): eliminate or flip this flag after PTA presolver is implemented.
|
||||||
var reflectFlag = flag.Bool("reflect", true, "Analyze reflection soundly (slow).")
|
var reflectFlag = flag.Bool("reflect", true, "Analyze reflection soundly (slow).")
|
||||||
|
@ -53,6 +53,7 @@ The -format flag controls the output format:
|
||||||
plain an editor-friendly format in which every line of output
|
plain an editor-friendly format in which every line of output
|
||||||
is of the form "pos: text", where pos is "-" if unknown.
|
is of the form "pos: text", where pos is "-" if unknown.
|
||||||
json structured data in JSON syntax.
|
json structured data in JSON syntax.
|
||||||
|
xml structured data in XML syntax.
|
||||||
|
|
||||||
The -pos flag is required in all modes except 'callgraph'.
|
The -pos flag is required in all modes except 'callgraph'.
|
||||||
|
|
||||||
|
@ -140,7 +141,10 @@ func main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// -format flag
|
// -format flag
|
||||||
if *formatFlag != "json" && *formatFlag != "plain" {
|
switch *formatFlag {
|
||||||
|
case "json", "plain", "xml":
|
||||||
|
// ok
|
||||||
|
default:
|
||||||
fmt.Fprintf(os.Stderr, "Error: illegal -format value: %q\n"+useHelp, *formatFlag)
|
fmt.Fprintf(os.Stderr, "Error: illegal -format value: %q\n"+useHelp, *formatFlag)
|
||||||
os.Exit(2)
|
os.Exit(2)
|
||||||
}
|
}
|
||||||
|
@ -161,17 +165,20 @@ func main() {
|
||||||
// Print the result.
|
// Print the result.
|
||||||
switch *formatFlag {
|
switch *formatFlag {
|
||||||
case "json":
|
case "json":
|
||||||
b, err := json.Marshal(res)
|
b, err := json.MarshalIndent(res.Serial(), "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "JSON error: %s\n", err)
|
fmt.Fprintf(os.Stderr, "JSON error: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
os.Stdout.Write(b)
|
||||||
if err := json.Indent(&buf, b, "", "\t"); err != nil {
|
|
||||||
fmt.Fprintf(os.Stderr, "json.Indent failed: %s", err)
|
case "xml":
|
||||||
|
b, err := xml.MarshalIndent(res.Serial(), "", "\t")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(os.Stderr, "XML error: %s\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
os.Stdout.Write(buf.Bytes())
|
os.Stdout.Write(b)
|
||||||
|
|
||||||
case "plain":
|
case "plain":
|
||||||
res.WriteTo(os.Stdout)
|
res.WriteTo(os.Stdout)
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
"code.google.com/p/go.tools/ssa"
|
"code.google.com/p/go.tools/ssa"
|
||||||
)
|
)
|
||||||
|
@ -113,13 +113,13 @@ func (r *calleesResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *calleesResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *calleesResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
j := &json.Callees{
|
j := &serial.Callees{
|
||||||
Pos: fset.Position(r.site.Pos()).String(),
|
Pos: fset.Position(r.site.Pos()).String(),
|
||||||
Desc: r.site.Description(),
|
Desc: r.site.Description(),
|
||||||
}
|
}
|
||||||
for _, callee := range r.funcs {
|
for _, callee := range r.funcs {
|
||||||
j.Callees = append(j.Callees, &json.CalleesItem{
|
j.Callees = append(j.Callees, &serial.CalleesItem{
|
||||||
Name: callee.String(),
|
Name: callee.String(),
|
||||||
Pos: fset.Position(callee.Pos()).String(),
|
Pos: fset.Position(callee.Pos()).String(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -7,7 +7,7 @@ package oracle
|
||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
"code.google.com/p/go.tools/ssa"
|
"code.google.com/p/go.tools/ssa"
|
||||||
)
|
)
|
||||||
|
@ -73,10 +73,10 @@ func (r *callersResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callersResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *callersResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var callers []json.Caller
|
var callers []serial.Caller
|
||||||
for _, site := range r.calls {
|
for _, site := range r.calls {
|
||||||
var c json.Caller
|
var c serial.Caller
|
||||||
c.Caller = site.Caller().Func().String()
|
c.Caller = site.Caller().Func().String()
|
||||||
if site.Caller() == r.root {
|
if site.Caller() == r.root {
|
||||||
c.Desc = "synthetic call"
|
c.Desc = "synthetic call"
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -90,8 +90,8 @@ Some nodes may appear multiple times due to context-sensitive
|
||||||
print(r.root, 0)
|
print(r.root, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callgraphResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *callgraphResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
cg := make([]json.CallGraph, len(r.numbering))
|
cg := make([]serial.CallGraph, len(r.numbering))
|
||||||
for n, i := range r.numbering {
|
for n, i := range r.numbering {
|
||||||
j := &cg[i]
|
j := &cg[i]
|
||||||
fn := n.Func()
|
fn := n.Func()
|
||||||
|
|
|
@ -7,7 +7,7 @@ package oracle
|
||||||
import (
|
import (
|
||||||
"go/token"
|
"go/token"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
"code.google.com/p/go.tools/ssa"
|
"code.google.com/p/go.tools/ssa"
|
||||||
)
|
)
|
||||||
|
@ -98,16 +98,16 @@ func (r *callstackResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *callstackResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *callstackResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var callers []json.Caller
|
var callers []serial.Caller
|
||||||
for _, site := range r.callstack {
|
for _, site := range r.callstack {
|
||||||
callers = append(callers, json.Caller{
|
callers = append(callers, serial.Caller{
|
||||||
Pos: fset.Position(site.Pos()).String(),
|
Pos: fset.Position(site.Pos()).String(),
|
||||||
Caller: site.Caller().Func().String(),
|
Caller: site.Caller().Func().String(),
|
||||||
Desc: site.Description(),
|
Desc: site.Description(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
res.Callstack = &json.CallStack{
|
res.Callstack = &serial.CallStack{
|
||||||
Pos: fset.Position(r.target.Pos()).String(),
|
Pos: fset.Position(r.target.Pos()).String(),
|
||||||
Target: r.target.String(),
|
Target: r.target.String(),
|
||||||
Callers: callers,
|
Callers: callers,
|
||||||
|
|
|
@ -17,7 +17,7 @@ import (
|
||||||
"code.google.com/p/go.tools/go/exact"
|
"code.google.com/p/go.tools/go/exact"
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/importer"
|
"code.google.com/p/go.tools/importer"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
"code.google.com/p/go.tools/ssa"
|
"code.google.com/p/go.tools/ssa"
|
||||||
)
|
)
|
||||||
|
@ -70,8 +70,8 @@ func (r *describeUnknownResult) display(printf printfFunc) {
|
||||||
printf(r.node, "%s", importer.NodeDescription(r.node))
|
printf(r.node, "%s", importer.NodeDescription(r.node))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *describeUnknownResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *describeUnknownResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
res.Describe = &json.Describe{
|
res.Describe = &serial.Describe{
|
||||||
Desc: importer.NodeDescription(r.node),
|
Desc: importer.NodeDescription(r.node),
|
||||||
Pos: fset.Position(r.node.Pos()).String(),
|
Pos: fset.Position(r.node.Pos()).String(),
|
||||||
}
|
}
|
||||||
|
@ -553,7 +553,7 @@ func (r *describeValueResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *describeValueResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *describeValueResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var value, objpos, ptaerr string
|
var value, objpos, ptaerr string
|
||||||
if r.constVal != nil {
|
if r.constVal != nil {
|
||||||
value = r.constVal.String()
|
value = r.constVal.String()
|
||||||
|
@ -565,31 +565,31 @@ func (r *describeValueResult) toJSON(res *json.Result, fset *token.FileSet) {
|
||||||
ptaerr = r.ptaErr.Error()
|
ptaerr = r.ptaErr.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
var pts []*json.DescribePointer
|
var pts []*serial.DescribePointer
|
||||||
for _, ptr := range r.ptrs {
|
for _, ptr := range r.ptrs {
|
||||||
var namePos string
|
var namePos string
|
||||||
if nt, ok := deref(ptr.typ).(*types.Named); ok {
|
if nt, ok := deref(ptr.typ).(*types.Named); ok {
|
||||||
namePos = fset.Position(nt.Obj().Pos()).String()
|
namePos = fset.Position(nt.Obj().Pos()).String()
|
||||||
}
|
}
|
||||||
var labels []json.DescribePTALabel
|
var labels []serial.DescribePTALabel
|
||||||
for _, l := range ptr.labels {
|
for _, l := range ptr.labels {
|
||||||
labels = append(labels, json.DescribePTALabel{
|
labels = append(labels, serial.DescribePTALabel{
|
||||||
Pos: fset.Position(l.Pos()).String(),
|
Pos: fset.Position(l.Pos()).String(),
|
||||||
Desc: l.String(),
|
Desc: l.String(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
pts = append(pts, &json.DescribePointer{
|
pts = append(pts, &serial.DescribePointer{
|
||||||
Type: ptr.typ.String(),
|
Type: ptr.typ.String(),
|
||||||
NamePos: namePos,
|
NamePos: namePos,
|
||||||
Labels: labels,
|
Labels: labels,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
res.Describe = &json.Describe{
|
res.Describe = &serial.Describe{
|
||||||
Desc: importer.NodeDescription(r.expr),
|
Desc: importer.NodeDescription(r.expr),
|
||||||
Pos: fset.Position(r.expr.Pos()).String(),
|
Pos: fset.Position(r.expr.Pos()).String(),
|
||||||
Detail: "value",
|
Detail: "value",
|
||||||
Value: &json.DescribeValue{
|
Value: &serial.DescribeValue{
|
||||||
Type: r.typ.String(),
|
Type: r.typ.String(),
|
||||||
Value: value,
|
Value: value,
|
||||||
ObjPos: objpos,
|
ObjPos: objpos,
|
||||||
|
@ -689,21 +689,21 @@ func (r *describeTypeResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *describeTypeResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *describeTypeResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var namePos, nameDef string
|
var namePos, nameDef string
|
||||||
if nt, ok := r.typ.(*types.Named); ok {
|
if nt, ok := r.typ.(*types.Named); ok {
|
||||||
namePos = fset.Position(nt.Obj().Pos()).String()
|
namePos = fset.Position(nt.Obj().Pos()).String()
|
||||||
nameDef = nt.Underlying().String()
|
nameDef = nt.Underlying().String()
|
||||||
}
|
}
|
||||||
res.Describe = &json.Describe{
|
res.Describe = &serial.Describe{
|
||||||
Desc: r.description,
|
Desc: r.description,
|
||||||
Pos: fset.Position(r.node.Pos()).String(),
|
Pos: fset.Position(r.node.Pos()).String(),
|
||||||
Detail: "type",
|
Detail: "type",
|
||||||
Type: &json.DescribeType{
|
Type: &serial.DescribeType{
|
||||||
Type: r.typ.String(),
|
Type: r.typ.String(),
|
||||||
NamePos: namePos,
|
NamePos: namePos,
|
||||||
NameDef: nameDef,
|
NameDef: nameDef,
|
||||||
Methods: methodsToJSON(r.methods, fset),
|
Methods: methodsToSerial(r.methods, fset),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -831,8 +831,8 @@ func formatMember(obj types.Object, maxname int) string {
|
||||||
return buf.String()
|
return buf.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *describePackageResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *describePackageResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var members []*json.DescribeMember
|
var members []*serial.DescribeMember
|
||||||
for _, mem := range r.members {
|
for _, mem := range r.members {
|
||||||
typ := mem.obj.Type()
|
typ := mem.obj.Type()
|
||||||
var val string
|
var val string
|
||||||
|
@ -842,20 +842,20 @@ func (r *describePackageResult) toJSON(res *json.Result, fset *token.FileSet) {
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
typ = typ.Underlying()
|
typ = typ.Underlying()
|
||||||
}
|
}
|
||||||
members = append(members, &json.DescribeMember{
|
members = append(members, &serial.DescribeMember{
|
||||||
Name: mem.obj.Name(),
|
Name: mem.obj.Name(),
|
||||||
Type: typ.String(),
|
Type: typ.String(),
|
||||||
Value: val,
|
Value: val,
|
||||||
Pos: fset.Position(mem.obj.Pos()).String(),
|
Pos: fset.Position(mem.obj.Pos()).String(),
|
||||||
Kind: tokenOf(mem.obj),
|
Kind: tokenOf(mem.obj),
|
||||||
Methods: methodsToJSON(mem.methods, fset),
|
Methods: methodsToSerial(mem.methods, fset),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
res.Describe = &json.Describe{
|
res.Describe = &serial.Describe{
|
||||||
Desc: r.description,
|
Desc: r.description,
|
||||||
Pos: fset.Position(r.node.Pos()).String(),
|
Pos: fset.Position(r.node.Pos()).String(),
|
||||||
Detail: "package",
|
Detail: "package",
|
||||||
Package: &json.DescribePackage{
|
Package: &serial.DescribePackage{
|
||||||
Path: r.pkg.Path(),
|
Path: r.pkg.Path(),
|
||||||
Members: members,
|
Members: members,
|
||||||
},
|
},
|
||||||
|
@ -907,8 +907,8 @@ func (r *describeStmtResult) display(printf printfFunc) {
|
||||||
printf(r.node, "%s", r.description)
|
printf(r.node, "%s", r.description)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *describeStmtResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *describeStmtResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
res.Describe = &json.Describe{
|
res.Describe = &serial.Describe{
|
||||||
Desc: r.description,
|
Desc: r.description,
|
||||||
Pos: fset.Position(r.node.Pos()).String(),
|
Pos: fset.Position(r.node.Pos()).String(),
|
||||||
Detail: "unknown",
|
Detail: "unknown",
|
||||||
|
@ -946,10 +946,10 @@ func isAccessibleFrom(obj types.Object, pkg *types.Package) bool {
|
||||||
return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
|
return ast.IsExported(obj.Name()) || obj.Pkg() == pkg
|
||||||
}
|
}
|
||||||
|
|
||||||
func methodsToJSON(methods []*types.Selection, fset *token.FileSet) []json.DescribeMethod {
|
func methodsToSerial(methods []*types.Selection, fset *token.FileSet) []serial.DescribeMethod {
|
||||||
var jmethods []json.DescribeMethod
|
var jmethods []serial.DescribeMethod
|
||||||
for _, meth := range methods {
|
for _, meth := range methods {
|
||||||
jmethods = append(jmethods, json.DescribeMethod{
|
jmethods = append(jmethods, serial.DescribeMethod{
|
||||||
Name: meth.String(),
|
Name: meth.String(),
|
||||||
Pos: fset.Position(meth.Obj().Pos()).String(),
|
Pos: fset.Position(meth.Obj().Pos()).String(),
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
// freevars displays the lexical (not package-level) free variables of
|
// freevars displays the lexical (not package-level) free variables of
|
||||||
|
@ -169,11 +169,11 @@ func (r *freevarsResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *freevarsResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *freevarsResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var refs []*json.FreeVar
|
var refs []*serial.FreeVar
|
||||||
for _, ref := range r.refs {
|
for _, ref := range r.refs {
|
||||||
refs = append(refs,
|
refs = append(refs,
|
||||||
&json.FreeVar{
|
&serial.FreeVar{
|
||||||
Pos: fset.Position(ref.obj.Pos()).String(),
|
Pos: fset.Position(ref.obj.Pos()).String(),
|
||||||
Kind: ref.kind,
|
Kind: ref.kind,
|
||||||
Ref: ref.ref,
|
Ref: ref.ref,
|
||||||
|
|
|
@ -8,7 +8,7 @@ import (
|
||||||
"go/token"
|
"go/token"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Implements displays the 'implements" relation among all
|
// Implements displays the 'implements" relation among all
|
||||||
|
@ -89,10 +89,10 @@ func (r *implementsResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *implementsResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *implementsResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
var facts []*json.Implements
|
var facts []*serial.Implements
|
||||||
for _, fact := range r.facts {
|
for _, fact := range r.facts {
|
||||||
facts = append(facts, &json.Implements{
|
facts = append(facts, &serial.Implements{
|
||||||
I: fact.iface.String(),
|
I: fact.iface.String(),
|
||||||
IPos: fset.Position(fact.iface.Obj().Pos()).String(),
|
IPos: fset.Position(fact.iface.Obj().Pos()).String(),
|
||||||
C: fact.conc.String(),
|
C: fact.conc.String(),
|
||||||
|
|
|
@ -18,7 +18,6 @@ package oracle
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
encjson "encoding/json"
|
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
|
@ -34,7 +33,7 @@ import (
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/importer"
|
"code.google.com/p/go.tools/importer"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
"code.google.com/p/go.tools/ssa"
|
"code.google.com/p/go.tools/ssa"
|
||||||
)
|
)
|
||||||
|
@ -97,7 +96,7 @@ type printfFunc func(pos interface{}, format string, args ...interface{})
|
||||||
|
|
||||||
// queryResult is the interface of each query-specific result type.
|
// queryResult is the interface of each query-specific result type.
|
||||||
type queryResult interface {
|
type queryResult interface {
|
||||||
toJSON(res *json.Result, fset *token.FileSet)
|
toSerial(res *serial.Result, fset *token.FileSet)
|
||||||
display(printf printfFunc)
|
display(printf printfFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,9 +118,6 @@ type QueryPos struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A Result encapsulates the result of an oracle.Query.
|
// A Result encapsulates the result of an oracle.Query.
|
||||||
//
|
|
||||||
// Result instances implement the json.Marshaler interface, i.e. they
|
|
||||||
// can be JSON-serialized.
|
|
||||||
type Result struct {
|
type Result struct {
|
||||||
fset *token.FileSet
|
fset *token.FileSet
|
||||||
// fprintf is a closure over the oracle's fileset and start/end position.
|
// fprintf is a closure over the oracle's fileset and start/end position.
|
||||||
|
@ -131,16 +127,20 @@ type Result struct {
|
||||||
warnings []warning // pointer analysis warnings
|
warnings []warning // pointer analysis warnings
|
||||||
}
|
}
|
||||||
|
|
||||||
func (res *Result) MarshalJSON() ([]byte, error) {
|
// Serial returns an instance of serial.Result, which implements the
|
||||||
resj := &json.Result{Mode: res.mode}
|
// {xml,json}.Marshaler interfaces so that query results can be
|
||||||
res.q.toJSON(resj, res.fset)
|
// serialized as JSON or XML.
|
||||||
|
//
|
||||||
|
func (res *Result) Serial() *serial.Result {
|
||||||
|
resj := &serial.Result{Mode: res.mode}
|
||||||
|
res.q.toSerial(resj, res.fset)
|
||||||
for _, w := range res.warnings {
|
for _, w := range res.warnings {
|
||||||
resj.Warnings = append(resj.Warnings, json.PTAWarning{
|
resj.Warnings = append(resj.Warnings, serial.PTAWarning{
|
||||||
Pos: res.fset.Position(w.pos).String(),
|
Pos: res.fset.Position(w.pos).String(),
|
||||||
Message: fmt.Sprintf(w.format, w.args...),
|
Message: fmt.Sprintf(w.format, w.args...),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return encjson.Marshal(resj)
|
return resj
|
||||||
}
|
}
|
||||||
|
|
||||||
// Query runs a single oracle query.
|
// Query runs a single oracle query.
|
||||||
|
|
|
@ -175,17 +175,12 @@ func doQuery(out io.Writer, q *query, useJson bool) {
|
||||||
|
|
||||||
if useJson {
|
if useJson {
|
||||||
// JSON output
|
// JSON output
|
||||||
b, err := json.Marshal(res)
|
b, err := json.MarshalIndent(res.Serial(), "", "\t")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintf(out, "JSON error: %s\n", err.Error())
|
fmt.Fprintf(out, "JSON error: %s\n", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var buf bytes.Buffer
|
out.Write(b)
|
||||||
if err := json.Indent(&buf, b, "", "\t"); err != nil {
|
|
||||||
fmt.Fprintf(out, "json.Indent failed: %s", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
out.Write(buf.Bytes())
|
|
||||||
} else {
|
} else {
|
||||||
// "plain" (compiler diagnostic format) output
|
// "plain" (compiler diagnostic format) output
|
||||||
capture := new(bytes.Buffer) // capture standard output
|
capture := new(bytes.Buffer) // capture standard output
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
"code.google.com/p/go.tools/pointer"
|
"code.google.com/p/go.tools/pointer"
|
||||||
"code.google.com/p/go.tools/ssa"
|
"code.google.com/p/go.tools/ssa"
|
||||||
)
|
)
|
||||||
|
@ -174,8 +174,8 @@ func (r *peersResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *peersResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *peersResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
peers := &json.Peers{
|
peers := &serial.Peers{
|
||||||
Pos: fset.Position(r.queryPos).String(),
|
Pos: fset.Position(r.queryPos).String(),
|
||||||
Type: r.queryType.String(),
|
Type: r.queryType.String(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
"code.google.com/p/go.tools/go/types"
|
"code.google.com/p/go.tools/go/types"
|
||||||
"code.google.com/p/go.tools/oracle/json"
|
"code.google.com/p/go.tools/oracle/serial"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Referrers reports all identifiers that resolve to the same object
|
// Referrers reports all identifiers that resolve to the same object
|
||||||
|
@ -84,8 +84,8 @@ func (r *referrersResult) display(printf printfFunc) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *referrersResult) toJSON(res *json.Result, fset *token.FileSet) {
|
func (r *referrersResult) toSerial(res *serial.Result, fset *token.FileSet) {
|
||||||
referrers := &json.Referrers{
|
referrers := &serial.Referrers{
|
||||||
Pos: fset.Position(r.query).String(),
|
Pos: fset.Position(r.query).String(),
|
||||||
Desc: r.obj.String(),
|
Desc: r.obj.String(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
// Package json defines the oracle's JSON schema.
|
// Package serial defines the oracle's schema for structured data
|
||||||
package json
|
// serialization using JSON, XML, etc.
|
||||||
|
package serial
|
||||||
|
|
||||||
// All 'pos' strings are of the form "file:line:col".
|
// All 'pos' strings are of the form "file:line:col".
|
||||||
// TODO(adonovan): improve performance by sharing filename strings.
|
// TODO(adonovan): improve performance by sharing filename strings.
|
Loading…
Reference in New Issue