// 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.

package main

import (
	"fmt"
	"go/token"

	"golang.org/x/tools/cmd/guru/serial"
	"golang.org/x/tools/go/callgraph"
	"golang.org/x/tools/go/callgraph/static"
	"golang.org/x/tools/go/loader"
	"golang.org/x/tools/go/ssa"
	"golang.org/x/tools/go/ssa/ssautil"
)

// The callstack function displays an arbitrary path from a root of the callgraph
// to the function at the current position.
//
// The information may be misleading in a context-insensitive
// analysis. e.g. the call path X->Y->Z might be infeasible if Y never
// calls Z when it is called from X.  TODO(adonovan): think about UI.
//
// TODO(adonovan): permit user to specify a starting point other than
// the analysis root.
//
func callstack(q *Query) error {
	fset := token.NewFileSet()
	lconf := loader.Config{Fset: fset, Build: q.Build}

	if err := setPTAScope(&lconf, q.Scope); err != nil {
		return err
	}

	// Load/parse/type-check the program.
	lprog, err := loadWithSoftErrors(&lconf)
	if err != nil {
		return err
	}

	qpos, err := parseQueryPos(lprog, q.Pos, false)
	if err != nil {
		return err
	}

	prog := ssautil.CreateProgram(lprog, 0)

	ptaConfig, err := setupPTA(prog, lprog, q.PTALog, q.Reflection)
	if err != nil {
		return err
	}

	pkg := prog.Package(qpos.info.Pkg)
	if pkg == nil {
		return fmt.Errorf("no SSA package")
	}

	if !ssa.HasEnclosingFunction(pkg, qpos.path) {
		return fmt.Errorf("this position is not inside a function")
	}

	// Defer SSA construction till after errors are reported.
	prog.Build()

	target := ssa.EnclosingFunction(pkg, qpos.path)
	if target == nil {
		return fmt.Errorf("no SSA function built for this location (dead code?)")
	}

	var callpath []*callgraph.Edge
	isEnd := func(n *callgraph.Node) bool { return n.Func == target }

	// First, build a callgraph containing only static call edges,
	// and search for an arbitrary path from a root to the target function.
	// This is quick, and the user wants a static path if one exists.
	cg := static.CallGraph(prog)
	cg.DeleteSyntheticNodes()
	for _, ep := range entryPoints(ptaConfig.Mains) {
		callpath = callgraph.PathSearch(cg.CreateNode(ep), isEnd)
		if callpath != nil {
			break
		}
	}

	// No fully static path found.
	// Run the pointer analysis and build a complete call graph.
	if callpath == nil {
		ptaConfig.BuildCallGraph = true
		cg := ptrAnalysis(ptaConfig).CallGraph
		cg.DeleteSyntheticNodes()
		callpath = callgraph.PathSearch(cg.Root, isEnd)
		if callpath != nil {
			callpath = callpath[1:] // remove synthetic edge from <root>
		}
	}

	q.Output(fset, &callstackResult{
		qpos:     qpos,
		target:   target,
		callpath: callpath,
	})
	return nil
}

type callstackResult struct {
	qpos     *queryPos
	target   *ssa.Function
	callpath []*callgraph.Edge
}

func (r *callstackResult) PrintPlain(printf printfFunc) {
	if r.callpath != nil {
		printf(r.qpos, "Found a call path from root to %s", r.target)
		printf(r.target, "%s", r.target)
		for i := len(r.callpath) - 1; i >= 0; i-- {
			edge := r.callpath[i]
			printf(edge, "%s from %s", edge.Description(), edge.Caller.Func)
		}
	} else {
		printf(r.target, "%s is unreachable in this analysis scope", r.target)
	}
}

func (r *callstackResult) JSON(fset *token.FileSet) []byte {
	var callers []serial.Caller
	for i := len(r.callpath) - 1; i >= 0; i-- { // (innermost first)
		edge := r.callpath[i]
		callers = append(callers, serial.Caller{
			Pos:    fset.Position(edge.Pos()).String(),
			Caller: edge.Caller.Func.String(),
			Desc:   edge.Description(),
		})
	}
	return toJSON(&serial.CallStack{
		Pos:     fset.Position(r.target.Pos()).String(),
		Target:  r.target.String(),
		Callers: callers,
	})
}
