// Copyright 2017 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 vet

import (
	"bytes"
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"strings"

	"cmd/go/internal/base"
	"cmd/go/internal/cmdflag"
	"cmd/go/internal/str"
	"cmd/go/internal/work"
)

// go vet flag processing
//
// We query the flags of the tool specified by -vettool and accept any
// of those flags plus any flag valid for 'go build'. The tool must
// support -flags, which prints a description of its flags in JSON to
// stdout.

// vetTool specifies the vet command to run.
// Any tool that supports the (still unpublished) vet
// command-line protocol may be supplied; see
// golang.org/x/tools/go/analysis/unitchecker for one
// implementation. It is also used by tests.
//
// The default behavior (vetTool=="") runs 'go tool vet'.
//
var vetTool string // -vettool

func init() {
	// Extract -vettool by ad hoc flag processing:
	// its value is needed even before we can declare
	// the flags available during main flag processing.
	for i, arg := range os.Args {
		if arg == "-vettool" || arg == "--vettool" {
			if i+1 >= len(os.Args) {
				log.Fatalf("%s requires a filename", arg)
			}
			vetTool = os.Args[i+1]
			break
		} else if strings.HasPrefix(arg, "-vettool=") ||
			strings.HasPrefix(arg, "--vettool=") {
			vetTool = arg[strings.IndexByte(arg, '=')+1:]
			break
		}
	}
}

// vetFlags processes the command line, splitting it at the first non-flag
// into the list of flags and list of packages.
func vetFlags(usage func(), args []string) (passToVet, packageNames []string) {
	// Query the vet command for its flags.
	tool := vetTool
	if tool != "" {
		var err error
		tool, err = filepath.Abs(tool)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		tool = base.Tool("vet")
	}
	out := new(bytes.Buffer)
	vetcmd := exec.Command(tool, "-flags")
	vetcmd.Stdout = out
	if err := vetcmd.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "go vet: can't execute %s -flags: %v\n", tool, err)
		os.Exit(2)
	}
	var analysisFlags []struct {
		Name  string
		Bool  bool
		Usage string
	}
	if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil {
		fmt.Fprintf(os.Stderr, "go vet: can't unmarshal JSON from %s -flags: %v", tool, err)
		os.Exit(2)
	}

	// Add vet's flags to vetflagDefn.
	//
	// Some flags, in particular -tags and -v, are known to vet but
	// also defined as build flags. This works fine, so we don't
	// define them here but use AddBuildFlags to init them.
	// However some, like -x, are known to the build but not to vet.
	var vetFlagDefn []*cmdflag.Defn
	for _, f := range analysisFlags {
		switch f.Name {
		case "tags", "v":
			continue
		}
		defn := &cmdflag.Defn{
			Name:       f.Name,
			PassToTest: true,
		}
		if f.Bool {
			defn.BoolVar = new(bool)
		}
		vetFlagDefn = append(vetFlagDefn, defn)
	}

	// Add build flags to vetFlagDefn.
	var cmd base.Command
	work.AddBuildFlags(&cmd)
	// This flag declaration is a placeholder:
	// -vettool is actually parsed by the init function above.
	cmd.Flag.StringVar(new(string), "vettool", "", "path to vet tool binary")
	cmd.Flag.VisitAll(func(f *flag.Flag) {
		vetFlagDefn = append(vetFlagDefn, &cmdflag.Defn{
			Name:  f.Name,
			Value: f.Value,
		})
	})

	// Process args.
	args = str.StringList(cmdflag.FindGOFLAGS(vetFlagDefn), args)
	for i := 0; i < len(args); i++ {
		if !strings.HasPrefix(args[i], "-") {
			return args[:i], args[i:]
		}

		f, value, extraWord := cmdflag.Parse("vet", usage, vetFlagDefn, args, i)
		if f == nil {
			fmt.Fprintf(os.Stderr, "vet: flag %q not defined\n", args[i])
			fmt.Fprintf(os.Stderr, "Run \"go help vet\" for more information\n")
			os.Exit(2)
		}
		if f.Value != nil {
			if err := f.Value.Set(value); err != nil {
				base.Fatalf("invalid flag argument for -%s: %v", f.Name, err)
			}
			keep := f.PassToTest
			if !keep {
				// A build flag, probably one we don't want to pass to vet.
				// Can whitelist.
				switch f.Name {
				case "tags", "v":
					keep = true
				}
			}
			if !keep {
				// Flags known to the build but not to vet, so must be dropped.
				if extraWord {
					args = append(args[:i], args[i+2:]...)
					extraWord = false
				} else {
					args = append(args[:i], args[i+1:]...)
				}
				i--
			}
		}
		if extraWord {
			i++
		}
	}
	return args, nil
}

var vetUsage func()

func init() { vetUsage = usage } // break initialization cycle

func usage() {
	fmt.Fprintf(os.Stderr, "usage: %s\n", CmdVet.UsageLine)
	fmt.Fprintf(os.Stderr, "Run 'go help %s' for details.\n", CmdVet.LongName())

	// This part is additional to what (*Command).Usage does:
	cmd := "go tool vet"
	if vetTool != "" {
		cmd = vetTool
	}
	fmt.Fprintf(os.Stderr, "Run '%s -help' for the vet tool's flags.\n", cmd)

	os.Exit(2)
}
