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

// The eg command performs example-based refactoring.
// For documentation, run the command, or see Help in
// golang.org/x/tools/refactor/eg.
package main // import "golang.org/x/tools/cmd/eg"

import (
	"flag"
	"fmt"
	"go/ast"
	"go/format"
	"go/parser"
	"go/token"
	"go/types"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/refactor/eg"
)

var (
	beforeeditFlag = flag.String("beforeedit", "", "A command to exec before each file is edited (e.g. chmod, checkout).  Whitespace delimits argument words.  The string '{}' is replaced by the file name.")
	helpFlag       = flag.Bool("help", false, "show detailed help message")
	templateFlag   = flag.String("t", "", "template.go file specifying the refactoring")
	transitiveFlag = flag.Bool("transitive", false, "apply refactoring to all dependencies too")
	writeFlag      = flag.Bool("w", false, "rewrite input files in place (by default, the results are printed to standard output)")
	verboseFlag    = flag.Bool("v", false, "show verbose matcher diagnostics")
)

const usage = `eg: an example-based refactoring tool.

Usage: eg -t template.go [-w] [-transitive] <packages>

-help            show detailed help message
-t template.go	 specifies the template file (use -help to see explanation)
-w          	 causes files to be re-written in place.
-transitive 	 causes all dependencies to be refactored too.
-v               show verbose matcher diagnostics
-beforeedit cmd  a command to exec before each file is modified.
                 "{}" represents the name of the file.
`

func main() {
	if err := doMain(); err != nil {
		fmt.Fprintf(os.Stderr, "eg: %s\n", err)
		os.Exit(1)
	}
}

func doMain() error {
	flag.Parse()
	args := flag.Args()

	if *helpFlag {
		help := eg.Help // hide %s from vet
		fmt.Fprint(os.Stderr, help)
		os.Exit(2)
	}

	if len(args) == 0 {
		fmt.Fprint(os.Stderr, usage)
		os.Exit(1)
	}

	if *templateFlag == "" {
		return fmt.Errorf("no -t template.go file specified")
	}

	tAbs, err := filepath.Abs(*templateFlag)
	if err != nil {
		return err
	}
	template, err := os.ReadFile(tAbs)
	if err != nil {
		return err
	}

	cfg := &packages.Config{
		Fset:  token.NewFileSet(),
		Mode:  packages.NeedTypesInfo | packages.NeedName | packages.NeedTypes | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps | packages.NeedCompiledGoFiles,
		Tests: true,
	}

	pkgs, err := packages.Load(cfg, args...)
	if err != nil {
		return err
	}

	tFile, err := parser.ParseFile(cfg.Fset, tAbs, template, parser.ParseComments)
	if err != nil {
		return err
	}

	// Type-check the template.
	tInfo := types.Info{
		Types:      make(map[ast.Expr]types.TypeAndValue),
		Defs:       make(map[*ast.Ident]types.Object),
		Uses:       make(map[*ast.Ident]types.Object),
		Implicits:  make(map[ast.Node]types.Object),
		Selections: make(map[*ast.SelectorExpr]*types.Selection),
		Scopes:     make(map[ast.Node]*types.Scope),
	}
	conf := types.Config{
		Importer: pkgsImporter(pkgs),
	}
	tPkg, err := conf.Check("egtemplate", cfg.Fset, []*ast.File{tFile}, &tInfo)
	if err != nil {
		return err
	}

	// Analyze the template.
	xform, err := eg.NewTransformer(cfg.Fset, tPkg, tFile, &tInfo, *verboseFlag)
	if err != nil {
		return err
	}

	// Apply it to the input packages.
	var all []*packages.Package
	if *transitiveFlag {
		packages.Visit(pkgs, nil, func(p *packages.Package) { all = append(all, p) })
	} else {
		all = pkgs
	}
	var hadErrors bool
	for _, pkg := range pkgs {
		for i, filename := range pkg.CompiledGoFiles {
			if filename == tAbs {
				// Don't rewrite the template file.
				continue
			}
			file := pkg.Syntax[i]
			n := xform.Transform(pkg.TypesInfo, pkg.Types, file)
			if n == 0 {
				continue
			}
			fmt.Fprintf(os.Stderr, "=== %s (%d matches)\n", filename, n)
			if *writeFlag {
				// Run the before-edit command (e.g. "chmod +w",  "checkout") if any.
				if *beforeeditFlag != "" {
					args := strings.Fields(*beforeeditFlag)
					// Replace "{}" with the filename, like find(1).
					for i := range args {
						if i > 0 {
							args[i] = strings.Replace(args[i], "{}", filename, -1)
						}
					}
					cmd := exec.Command(args[0], args[1:]...)
					cmd.Stdout = os.Stdout
					cmd.Stderr = os.Stderr
					if err := cmd.Run(); err != nil {
						fmt.Fprintf(os.Stderr, "Warning: edit hook %q failed (%s)\n",
							args, err)
					}
				}
				if err := eg.WriteAST(cfg.Fset, filename, file); err != nil {
					fmt.Fprintf(os.Stderr, "eg: %s\n", err)
					hadErrors = true
				}
			} else {
				format.Node(os.Stdout, cfg.Fset, file)
			}
		}
	}
	if hadErrors {
		os.Exit(1)
	}

	return nil
}

type pkgsImporter []*packages.Package

func (p pkgsImporter) Import(path string) (tpkg *types.Package, err error) {
	packages.Visit([]*packages.Package(p), func(pkg *packages.Package) bool {
		if pkg.PkgPath == path {
			tpkg = pkg.Types
			return false
		}
		return true
	}, nil)
	if tpkg != nil {
		return tpkg, nil
	}
	return nil, fmt.Errorf("package %q not found", path)
}
