// doQuery poses query q to the guru and writes its response and
// error (if any) to out.
func doQuery(out io.Writer, q *query, useJson bool) {
	fmt.Fprintf(out, "-------- @%s %s --------\n", q.verb, q.id)

	var buildContext = build.Default
	buildContext.GOPATH = "testdata"
	query := guru.Query{
		Mode:       q.verb,
		Pos:        q.queryPos,
		Build:      &buildContext,
		Scope:      []string{q.filename},
		Reflection: true,
	}
	if err := guru.Run(&query); err != nil {
		fmt.Fprintf(out, "\nError: %s\n", err)
		return
	}

	if useJson {
		// JSON output
		b, err := json.MarshalIndent(query.Serial(), "", "\t")
		if err != nil {
			fmt.Fprintf(out, "JSON error: %s\n", err.Error())
			return
		}
		out.Write(b)
		fmt.Fprintln(out)
	} else {
		// "plain" (compiler diagnostic format) output
		WriteResult(out, &query)
	}
}
Example #2
0
// doQuery poses query q to the guru and writes its response and
// error (if any) to out.
func doQuery(out io.Writer, q *query, json bool) {
	fmt.Fprintf(out, "-------- @%s %s --------\n", q.verb, q.id)

	var buildContext = build.Default
	buildContext.GOPATH = "testdata"
	pkg := filepath.Dir(strings.TrimPrefix(q.filename, "testdata/src/"))

	gopathAbs, _ := filepath.Abs(buildContext.GOPATH)

	var outputMu sync.Mutex // guards outputs
	var outputs []string    // JSON objects or lines of text
	outputFn := func(fset *token.FileSet, qr guru.QueryResult) {
		outputMu.Lock()
		defer outputMu.Unlock()
		if json {
			jsonstr := string(qr.JSON(fset))
			// Sanitize any absolute filenames that creep in.
			jsonstr = strings.Replace(jsonstr, gopathAbs, "$GOPATH", -1)
			outputs = append(outputs, jsonstr)
		} else {
			// suppress position information
			qr.PrintPlain(func(_ interface{}, format string, args ...interface{}) {
				outputs = append(outputs, fmt.Sprintf(format, args...))
			})
		}
	}

	query := guru.Query{
		Pos:        q.queryPos,
		Build:      &buildContext,
		Scope:      []string{pkg},
		Reflection: true,
		Output:     outputFn,
	}

	if err := guru.Run(q.verb, &query); err != nil {
		fmt.Fprintf(out, "\nError: %s\n", err)
		return
	}

	// In a "referrers" query, references are sorted within each
	// package but packages are visited in arbitrary order,
	// so for determinism we sort them.  Line 0 is a caption.
	if q.verb == "referrers" {
		sort.Strings(outputs[1:])
	}

	for _, output := range outputs {
		fmt.Fprintf(out, "%s\n", output)
	}

	if !json {
		io.WriteString(out, "\n")
	}
}
Example #3
0
func TestIssue14684(t *testing.T) {
	var buildContext = build.Default
	buildContext.GOPATH = "testdata"
	query := guru.Query{
		Pos:   "testdata/src/README.txt:#1",
		Build: &buildContext,
	}
	err := guru.Run("freevars", &query)
	if err == nil {
		t.Fatal("guru query succeeded unexpectedly")
	}
	if got, want := err.Error(), "testdata/src/README.txt is not a Go source file"; got != want {
		t.Errorf("query error was %q, want %q", got, want)
	}
}