// Copyright 2016 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 cfg_test

import (
	"bytes"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"testing"

	"golang.org/x/tools/go/cfg"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/testenv"
)

const src = `package main

import "log"

func f1() {
	live()
	return
	dead()
}

func f2() {
	for {
		live()
	}
	dead()
}

func f3() {
	if true { // even known values are ignored
		return
	}
	for true { // even known values are ignored
		live()
	}
	for {
		live()
	}
	dead()
}

func f4(x int) {
	switch x {
	case 1:
		live()
		fallthrough
	case 2:
		live()
		log.Fatal()
	default:
		panic("oops")
	}
	dead()
}

func f4(ch chan int) {
	select {
	case <-ch:
		live()
		return
	default:
		live()
		panic("oops")
	}
	dead()
}

func f5(unknown bool) {
	for {
		if unknown {
			break
		}
		continue
		dead()
	}
	live()
}

func f6(unknown bool) {
outer:
	for {
		for {
			break outer
			dead()
		}
		dead()
	}
	live()
}

func f7() {
	for {
		break nosuchlabel
		dead()
	}
	dead()
}

func f8() {
	select{}
	dead()
}

func f9(ch chan int) {
	select {
	case <-ch:
		return
	}
	dead()
}

func f10(ch chan int) {
	select {
	case <-ch:
		return
		dead()
	default:
	}
	live()
}

func f11() {
	goto; // mustn't crash
	dead()
}

`

func TestDeadCode(t *testing.T) {
	t.Skip("broken on release-branch.0.24 for unknown reasons")
	// We'll use dead code detection to verify the CFG.

	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, "dummy.go", src, parser.Mode(0))
	if err != nil {
		t.Fatal(err)
	}
	for _, decl := range f.Decls {
		if decl, ok := decl.(*ast.FuncDecl); ok {
			g := cfg.New(decl.Body, mayReturn)

			// Print statements in unreachable blocks
			// (in order determined by builder).
			var buf bytes.Buffer
			for _, b := range g.Blocks {
				if !b.Live {
					for _, n := range b.Nodes {
						fmt.Fprintf(&buf, "\t%s\n", formatNode(fset, n))
					}
				}
			}

			// Check that the result contains "dead" at least once but not "live".
			if !bytes.Contains(buf.Bytes(), []byte("dead")) ||
				bytes.Contains(buf.Bytes(), []byte("live")) {
				t.Errorf("unexpected dead statements in function %s:\n%s",
					decl.Name.Name,
					&buf)
				t.Logf("control flow graph:\n%s", g.Format(fset))
			}
		}
	}
}

// TestSmoke runs the CFG builder on every FuncDecl in the standard
// library and x/tools. (This is all well-typed code, but it gives
// some coverage.)
func TestSmoke(t *testing.T) {
	if testing.Short() {
		t.Skip("skipping in short mode")
	}
	testenv.NeedsTool(t, "go")

	// The Mode API is just hateful.
	// https://github.com/golang/go/issues/48226#issuecomment-1948792315
	mode := packages.NeedDeps | packages.NeedImports | packages.NeedSyntax | packages.NeedTypes
	pkgs, err := packages.Load(&packages.Config{Mode: mode}, "std", "golang.org/x/tools/...")
	if err != nil {
		t.Fatal(err)
	}

	for _, pkg := range pkgs {
		for _, file := range pkg.Syntax {
			for _, decl := range file.Decls {
				if decl, ok := decl.(*ast.FuncDecl); ok && decl.Body != nil {
					g := cfg.New(decl.Body, mayReturn)

					// Run a few quick sanity checks.
					failed := false
					for i, b := range g.Blocks {
						errorf := func(format string, args ...any) {
							if !failed {
								t.Errorf("%s\n%s", pkg.Fset.Position(decl.Pos()), g.Format(pkg.Fset))
								failed = true
							}
							msg := fmt.Sprintf(format, args...)
							t.Errorf("block %d: %s", i, msg)
						}

						if b.Kind == cfg.KindInvalid {
							errorf("invalid Block.Kind %v", b.Kind)
						}
						if b.Stmt == nil && b.Kind != cfg.KindLabel {
							errorf("nil Block.Stmt (Kind=%v)", b.Kind)
						}
						if i != int(b.Index) {
							errorf("invalid Block.Index")
						}
					}
				}
			}
		}
	}
}

// A trivial mayReturn predicate that looks only at syntax, not types.
func mayReturn(call *ast.CallExpr) bool {
	switch fun := call.Fun.(type) {
	case *ast.Ident:
		return fun.Name != "panic"
	case *ast.SelectorExpr:
		return fun.Sel.Name != "Fatal"
	}
	return true
}

func formatNode(fset *token.FileSet, n ast.Node) string {
	var buf bytes.Buffer
	format.Node(&buf, fset, n)
	// Indent secondary lines by a tab.
	return string(bytes.Replace(buf.Bytes(), []byte("\n"), []byte("\n\t"), -1))
}
