cmd/guru: support streaming plain and -json output

Visible changes:
- "referrers" queries now emit a stream of results,
  so they start appearing quickly even in large queries.
  We no longer report the total number of matches.
- packageReferrers now also uses AfterTypeCheck hook and streaming.
- XML support has been dropped.
- The -format flag has been replaced by -json.

JSON protocol changes:
- The enclosing Result struct has been removed.
- Likewise the 'mode' field (since the caller knows it already)
- "freevars" and "referrers" now emit a stream of objects
  In the case of referrers, the first object has a different from the rest.
- The "referrers" results include the text of the matching line
  (parity with -json=false)

Implementation details:
- the concurrency-safe q.Output function can be called
  many times, each with a queryResult to print.
- fset is no longer saved in Query (cleaner)
- queryResult methods renamed PrintPlain, JSON

Change-Id: I41a4e3f57f266fcf043ece4045bca82c6f6a356f
Reviewed-on: https://go-review.googlesource.com/21397
Reviewed-by: Michael Matloob <matloob@golang.org>
diff --git a/cmd/guru/implements.go b/cmd/guru/implements.go
index 07a617d..e852441 100644
--- a/cmd/guru/implements.go
+++ b/cmd/guru/implements.go
@@ -63,7 +63,6 @@
 	if err != nil {
 		return err
 	}
-	q.Fset = lprog.Fset
 
 	qpos, err := parseQueryPos(lprog, q.Pos, false)
 	if err != nil {
@@ -179,9 +178,9 @@
 		}
 	}
 
-	q.result = &implementsResult{
+	q.Output(lprog.Fset, &implementsResult{
 		qpos, T, pos, to, from, fromPtr, method, toMethod, fromMethod, fromPtrMethod,
-	}
+	})
 	return nil
 }
 
@@ -201,7 +200,7 @@
 	fromPtrMethod []*types.Selection // method of type fromPtrMethod[i], if any
 }
 
-func (r *implementsResult) display(printf printfFunc) {
+func (r *implementsResult) PrintPlain(printf printfFunc) {
 	relation := "is implemented by"
 
 	meth := func(sel *types.Selection) {
@@ -298,8 +297,15 @@
 	}
 }
 
-func (r *implementsResult) toSerial(res *serial.Result, fset *token.FileSet) {
-	res.Implements = &serial.Implements{
+func (r *implementsResult) JSON(fset *token.FileSet) []byte {
+	var method *serial.DescribeMethod
+	if r.method != nil {
+		method = &serial.DescribeMethod{
+			Name: r.qpos.objectString(r.method),
+			Pos:  fset.Position(r.method.Pos()).String(),
+		}
+	}
+	return toJSON(&serial.Implements{
 		T:                       makeImplementsType(r.t, fset),
 		AssignableTo:            makeImplementsTypes(r.to, fset),
 		AssignableFrom:          makeImplementsTypes(r.from, fset),
@@ -307,13 +313,9 @@
 		AssignableToMethod:      methodsToSerial(r.qpos.info.Pkg, r.toMethod, fset),
 		AssignableFromMethod:    methodsToSerial(r.qpos.info.Pkg, r.fromMethod, fset),
 		AssignableFromPtrMethod: methodsToSerial(r.qpos.info.Pkg, r.fromPtrMethod, fset),
-	}
-	if r.method != nil {
-		res.Implements.Method = &serial.DescribeMethod{
-			Name: r.qpos.objectString(r.method),
-			Pos:  fset.Position(r.method.Pos()).String(),
-		}
-	}
+		Method:                  method,
+	})
+
 }
 
 func makeImplementsTypes(tt []types.Type, fset *token.FileSet) []serial.ImplementsType {