// 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"
	"errors"
	"flag"
	"fmt"
	exec "internal/execabs"
	"log"
	"os"
	"path/filepath"
	"strings"

	"cmd/go/internal/base"
	"cmd/go/internal/cmdflag"
	"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() {
	work.AddBuildFlags(CmdVet, work.DefaultBuildFlags)
	CmdVet.Flag.StringVar(&vetTool, "vettool", "", "")
}

func parseVettoolFlag(args []string) {
	// 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 args {
		if arg == "-vettool" || arg == "--vettool" {
			if i+1 >= len(args) {
				log.Fatalf("%s requires a filename", arg)
			}
			vetTool = args[i+1]
			return
		} else if strings.HasPrefix(arg, "-vettool=") ||
			strings.HasPrefix(arg, "--vettool=") {
			vetTool = arg[strings.IndexByte(arg, '=')+1:]
			return
		}
	}
}

// vetFlags processes the command line, splitting it at the first non-flag
// into the list of flags and list of packages.
func vetFlags(args []string) (passToVet, packageNames []string) {
	parseVettoolFlag(args)

	// Query the vet command for its flags.
	var tool string
	if vetTool == "" {
		tool = base.Tool("vet")
	} else {
		var err error
		tool, err = filepath.Abs(vetTool)
		if err != nil {
			log.Fatal(err)
		}
	}
	out := new(bytes.Buffer)
	vetcmd := exec.Command(tool, "-flags")
	vetcmd.Stdout = out
	if err := vetcmd.Run(); err != nil {
		fmt.Fprintf(os.Stderr, "go: can't execute %s -flags: %v\n", tool, err)
		base.SetExitStatus(2)
		base.Exit()
	}
	var analysisFlags []struct {
		Name  string
		Bool  bool
		Usage string
	}
	if err := json.Unmarshal(out.Bytes(), &analysisFlags); err != nil {
		fmt.Fprintf(os.Stderr, "go: can't unmarshal JSON from %s -flags: %v", tool, err)
		base.SetExitStatus(2)
		base.Exit()
	}

	// Add vet's flags to CmdVet.Flag.
	//
	// Some flags, in particular -tags and -v, are known to vet but
	// also defined as build flags. This works fine, so we omit duplicates here.
	// However some, like -x, are known to the build but not to vet.
	isVetFlag := make(map[string]bool, len(analysisFlags))
	cf := CmdVet.Flag
	for _, f := range analysisFlags {
		isVetFlag[f.Name] = true
		if cf.Lookup(f.Name) == nil {
			if f.Bool {
				cf.Bool(f.Name, false, "")
			} else {
				cf.String(f.Name, "", "")
			}
		}
	}

	// Record the set of vet tool flags set by GOFLAGS. We want to pass them to
	// the vet tool, but only if they aren't overridden by an explicit argument.
	base.SetFromGOFLAGS(&CmdVet.Flag)
	addFromGOFLAGS := map[string]bool{}
	CmdVet.Flag.Visit(func(f *flag.Flag) {
		if isVetFlag[f.Name] {
			addFromGOFLAGS[f.Name] = true
		}
	})

	explicitFlags := make([]string, 0, len(args))
	for len(args) > 0 {
		f, remainingArgs, err := cmdflag.ParseOne(&CmdVet.Flag, args)

		if errors.Is(err, flag.ErrHelp) {
			exitWithUsage()
		}

		if errors.Is(err, cmdflag.ErrFlagTerminator) {
			// All remaining args must be package names, but the flag terminator is
			// not included.
			packageNames = remainingArgs
			break
		}

		if nf := (cmdflag.NonFlagError{}); errors.As(err, &nf) {
			// Everything from here on out — including the argument we just consumed —
			// must be a package name.
			packageNames = args
			break
		}

		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			exitWithUsage()
		}

		if isVetFlag[f.Name] {
			// Forward the raw arguments rather than cleaned equivalents, just in
			// case the vet tool parses them idiosyncratically.
			explicitFlags = append(explicitFlags, args[:len(args)-len(remainingArgs)]...)

			// This flag has been overridden explicitly, so don't forward its implicit
			// value from GOFLAGS.
			delete(addFromGOFLAGS, f.Name)
		}

		args = remainingArgs
	}

	// Prepend arguments from GOFLAGS before other arguments.
	CmdVet.Flag.Visit(func(f *flag.Flag) {
		if addFromGOFLAGS[f.Name] {
			passToVet = append(passToVet, fmt.Sprintf("-%s=%s", f.Name, f.Value))
		}
	})
	passToVet = append(passToVet, explicitFlags...)
	return passToVet, packageNames
}

func exitWithUsage() {
	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 a full list of flags and analyzers.\n", cmd)
	fmt.Fprintf(os.Stderr, "Run '%s -help' for an overview.\n", cmd)

	base.SetExitStatus(2)
	base.Exit()
}
