// Copyright 2023 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 inline_test

import (
	"flag"
	"fmt"
	"go/ast"
	"go/parser"
	"go/types"
	"log"
	"os"
	"path/filepath"
	"strings"
	"testing"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/go/types/typeutil"
	"golang.org/x/tools/internal/diff"
	"golang.org/x/tools/internal/refactor/inline"
	"golang.org/x/tools/internal/testenv"
)

var packagesFlag = flag.String("packages", "", "set of packages for TestEverything")

// TestEverything invokes the inliner on every single call site in a
// given package. and checks that it produces either a reasonable
// error, or output that parses and type-checks.
//
// It does nothing during ordinary testing, but may be used to find
// inlining bugs in large corpora.
//
// Use this command to inline everything in golang.org/x/tools:
//
// $ go test ./internal/refactor/inline/ -run=Everything -packages=../../../
//
// And these commands to inline everything in the kubernetes repository:
//
// $ go test -c -o /tmp/everything ./internal/refactor/inline/
// $ (cd kubernetes && /tmp/everything -test.run=Everything -packages=./...)
//
// TODO(adonovan):
//   - report counters (number of attempts, failed AnalyzeCallee, failed
//     Inline, etc.)
//   - Make a pretty log of the entire output so that we can peruse it
//     for opportunities for systematic improvement.
func TestEverything(t *testing.T) {
	testenv.NeedsGoPackages(t)
	if testing.Short() {
		t.Skipf("skipping slow test in -short mode")
	}
	if *packagesFlag == "" {
		return
	}

	// Load this package plus dependencies from typed syntax.
	cfg := &packages.Config{
		Mode: packages.LoadAllSyntax,
		Env: append(os.Environ(),
			"GO111MODULES=on",
			"GOPATH=",
			"GOWORK=off",
			"GOPROXY=off"),
	}
	pkgs, err := packages.Load(cfg, *packagesFlag)
	if err != nil {
		t.Errorf("Load: %v", err)
	}
	// Report parse/type errors.
	// Also, build transitive dependency mapping.
	deps := make(map[string]*packages.Package) // key is PkgPath
	packages.Visit(pkgs, nil, func(pkg *packages.Package) {
		deps[pkg.Types.Path()] = pkg
		for _, err := range pkg.Errors {
			t.Fatal(err)
		}
	})

	// Memoize repeated calls for same file.
	fileContent := make(map[string][]byte)
	readFile := func(filename string) ([]byte, error) {
		content, ok := fileContent[filename]
		if !ok {
			var err error
			content, err = os.ReadFile(filename)
			if err != nil {
				return nil, err
			}
			fileContent[filename] = content
		}
		return content, nil
	}

	for _, callerPkg := range pkgs {
		// Find all static function calls in the package.
		for _, callerFile := range callerPkg.Syntax {
			noMutCheck := checkNoMutation(callerFile)
			ast.Inspect(callerFile, func(n ast.Node) bool {
				call, ok := n.(*ast.CallExpr)
				if !ok {
					return true
				}
				fn := typeutil.StaticCallee(callerPkg.TypesInfo, call)
				if fn == nil {
					return true
				}

				// Prepare caller info.
				callPosn := callerPkg.Fset.PositionFor(call.Lparen, false)
				callerContent, err := readFile(callPosn.Filename)
				if err != nil {
					t.Fatal(err)
				}
				caller := &inline.Caller{
					Fset:    callerPkg.Fset,
					Types:   callerPkg.Types,
					Info:    callerPkg.TypesInfo,
					File:    callerFile,
					Call:    call,
					Content: callerContent,
				}

				// Analyze callee.
				calleePkg, ok := deps[fn.Pkg().Path()]
				if !ok {
					t.Fatalf("missing package for callee %v", fn)
				}
				calleePosn := callerPkg.Fset.PositionFor(fn.Pos(), false)
				calleeDecl, err := findFuncByPosition(calleePkg, calleePosn)
				if err != nil {
					t.Fatal(err)
				}
				calleeContent, err := readFile(calleePosn.Filename)
				if err != nil {
					t.Fatal(err)
				}

				// Create a subtest for each inlining operation.
				name := fmt.Sprintf("%s@%v", fn.Name(), filepath.Base(callPosn.String()))
				t.Run(name, func(t *testing.T) {
					// TODO(adonovan): add a panic handler.

					t.Logf("callee declared at %v",
						filepath.Base(calleePosn.String()))

					t.Logf("run this command to reproduce locally:\n$ gopls codeaction -kind=refactor.inline -exec -diff %s:#%d",
						callPosn.Filename, callPosn.Offset)

					callee, err := inline.AnalyzeCallee(
						t.Logf,
						calleePkg.Fset,
						calleePkg.Types,
						calleePkg.TypesInfo,
						calleeDecl,
						calleeContent)
					if err != nil {
						// Ignore the expected kinds of errors.
						for _, ignore := range []string{
							"has no body",
							"type parameters are not yet",
							"line directives",
							"cgo-generated",
						} {
							if strings.Contains(err.Error(), ignore) {
								return
							}
						}
						t.Fatalf("AnalyzeCallee: %v", err)
					}
					if err := checkTranscode(callee); err != nil {
						t.Fatal(err)
					}

					res, err := inline.Inline(caller, callee, &inline.Options{
						Logf: t.Logf,
					})
					if err != nil {
						// Write error to a log, but this ok.
						t.Log(err)
						return
					}
					got := res.Content

					// Print the diff.
					t.Logf("Got diff:\n%s",
						diff.Unified("old", "new", string(callerContent), string(res.Content)))

					// Parse and type-check the transformed source.
					f, err := parser.ParseFile(caller.Fset, callPosn.Filename, got, parser.SkipObjectResolution)
					if err != nil {
						t.Fatalf("transformed source does not parse: %v", err)
					}
					// Splice into original file list.
					syntax := append([]*ast.File(nil), callerPkg.Syntax...)
					for i := range callerPkg.Syntax {
						if syntax[i] == callerFile {
							syntax[i] = f
							break
						}
					}

					var typeErrors []string
					conf := &types.Config{
						Error: func(err error) {
							typeErrors = append(typeErrors, err.Error())
						},
						Importer: importerFunc(func(importPath string) (*types.Package, error) {
							// Note: deps is properly keyed by package path,
							// not import path, but we can't assume
							// Package.Imports[importPath] exists in the
							// case of newly added imports of indirect
							// dependencies. Seems not to matter to this test.
							dep, ok := deps[importPath]
							if ok {
								return dep.Types, nil
							}
							return nil, fmt.Errorf("missing package: %q", importPath)
						}),
					}
					if _, err := conf.Check("p", caller.Fset, syntax, nil); err != nil {
						t.Fatalf("transformed package has type errors:\n\n%s\n\nTransformed file:\n\n%s",
							strings.Join(typeErrors, "\n"),
							got)
					}
				})
				return true
			})
			noMutCheck()
		}
	}
	log.Printf("Analyzed %d packages", len(pkgs))
}

type importerFunc func(path string) (*types.Package, error)

func (f importerFunc) Import(path string) (*types.Package, error) {
	return f(path)
}
