// Copyright 2022 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 checker_test

import (
	"bytes"
	"flag"
	"fmt"
	"go/ast"
	"go/token"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"runtime"
	"slices"
	"strings"
	"testing"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/checker"
	"golang.org/x/tools/go/analysis/multichecker"
	"golang.org/x/tools/go/analysis/passes/inspect"
	"golang.org/x/tools/go/ast/inspector"
	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/internal/diff"
	"golang.org/x/tools/internal/expect"
	"golang.org/x/tools/internal/testenv"
	"golang.org/x/tools/internal/testfiles"
	"golang.org/x/tools/txtar"
)

func TestMain(m *testing.M) {
	// If the CHECKER_TEST_CHILD environment variable is set,
	// this process should behave like a multichecker.
	// Analyzers are selected by flags.
	if _, ok := os.LookupEnv("CHECKER_TEST_CHILD"); ok {
		multichecker.Main(
			markerAnalyzer,
			noendAnalyzer,
			renameAnalyzer,
			relatedAnalyzer,
		)
		panic("unreachable")
	}

	// ordinary test
	flag.Parse()
	os.Exit(m.Run())
}

const (
	exitCodeSuccess     = 0 // success (no diagnostics, or successful -fix)
	exitCodeFailed      = 1 // analysis failed to run
	exitCodeDiagnostics = 3 // diagnostics were reported (and no -fix)
)

// TestReportInvalidDiagnostic tests that a call to pass.Report with
// certain kind of invalid diagnostic (e.g. conflicting fixes)
// promptly results in a panic.
func TestReportInvalidDiagnostic(t *testing.T) {
	testenv.NeedsGoPackages(t)

	// Load the errors package.
	cfg := &packages.Config{Mode: packages.LoadAllSyntax}
	initial, err := packages.Load(cfg, "errors")
	if err != nil {
		t.Fatal(err)
	}

	for _, test := range []struct {
		name string
		want string
		diag func(pos token.Pos) analysis.Diagnostic
	}{
		// Diagnostic has two alternative fixes with the same Message.
		{
			"duplicate message",
			`analyzer "a" suggests two fixes with same Message \(fix\)`,
			func(pos token.Pos) analysis.Diagnostic {
				return analysis.Diagnostic{
					Pos:     pos,
					Message: "oops",
					SuggestedFixes: []analysis.SuggestedFix{
						{Message: "fix"},
						{Message: "fix"},
					},
				}
			},
		},
		// TextEdit has invalid Pos.
		{
			"bad Pos",
			`analyzer "a" suggests invalid fix .*: no token.File for TextEdit.Pos .0.`,
			func(pos token.Pos) analysis.Diagnostic {
				return analysis.Diagnostic{
					Pos:     pos,
					Message: "oops",
					SuggestedFixes: []analysis.SuggestedFix{
						{
							Message:   "fix",
							TextEdits: []analysis.TextEdit{{}},
						},
					},
				}
			},
		},
		// TextEdit has invalid End.
		{
			"End < Pos",
			`analyzer "a" suggests invalid fix .*: TextEdit.Pos .* > TextEdit.End .*`,
			func(pos token.Pos) analysis.Diagnostic {
				return analysis.Diagnostic{
					Pos:     pos,
					Message: "oops",
					SuggestedFixes: []analysis.SuggestedFix{
						{
							Message: "fix",
							TextEdits: []analysis.TextEdit{{
								Pos: pos + 2,
								End: pos,
							}},
						},
					},
				}
			},
		},
		// Two TextEdits overlap.
		{
			"overlapping edits",
			`analyzer "a" suggests invalid fix .*: overlapping edits to .*errors.go \(1:1-1:3 and 1:2-1:4\)`,
			func(pos token.Pos) analysis.Diagnostic {
				return analysis.Diagnostic{
					Pos:     pos,
					Message: "oops",
					SuggestedFixes: []analysis.SuggestedFix{
						{
							Message: "fix",
							TextEdits: []analysis.TextEdit{
								{Pos: pos, End: pos + 2},
								{Pos: pos + 1, End: pos + 3},
							},
						},
					},
				}
			},
		},
	} {
		t.Run(test.name, func(t *testing.T) {
			reached := false
			a := &analysis.Analyzer{Name: "a", Doc: "doc", Run: func(pass *analysis.Pass) (any, error) {
				reached = true
				panics(t, test.want, func() {
					pos := pass.Files[0].FileStart
					pass.Report(test.diag(pos))
				})
				return nil, nil
			}}
			if _, err := checker.Analyze([]*analysis.Analyzer{a}, initial, &checker.Options{}); err != nil {
				t.Fatalf("Analyze failed: %v", err)
			}
			if !reached {
				t.Error("analyzer was never invoked")
			}
		})
	}
}

// TestScript runs script-driven tests in testdata/*.txt.
// Each file is a txtar archive, expanded to a temporary directory.
//
// The comment section of the archive is a script, with the following
// commands:
//
//	# comment
//		ignored
//	blank line
//		ignored
//	skip k=v...
//		Skip the test if any k=v string is a substring of the string
//		"GOOS=darwin GOARCH=arm64" appropriate to the current build.
//	checker args...
//		Run the checker command with the specified space-separated
//		arguments; this fork+execs the [TestMain] function above.
//		If the archive has a "stdout" section, its contents must
//		match the stdout output of the checker command.
//		Do NOT use this for testing -diff: tests should not
//		rely on the particulars of the diff algorithm.
//	exit int
//		Assert that previous checker command had this exit code.
//	stderr regexp
//		Assert that stderr output from previous checker run matches this pattern.
//
// The script must include at least one 'checker' command.
func TestScript(t *testing.T) {
	testenv.NeedsExec(t)
	testenv.NeedsGoPackages(t)

	txtfiles, err := filepath.Glob("testdata/*.txt")
	if err != nil {
		t.Fatal(err)
	}
	for _, txtfile := range txtfiles {
		t.Run(txtfile, func(t *testing.T) {
			t.Parallel()

			// Expand archive into tmp tree.
			ar, err := txtar.ParseFile(txtfile)
			if err != nil {
				t.Fatal(err)
			}
			fs, err := txtar.FS(ar)
			if err != nil {
				t.Fatal(err)
			}
			dir := testfiles.CopyToTmp(t, fs)

			// Parse txtar comment as a script.
			const noExitCode = -999
			var (
				// state variables operated on by script
				lastExitCode = noExitCode
				lastStderr   string
			)
			for i, line := range strings.Split(string(ar.Comment), "\n") {
				line = strings.TrimSpace(line)
				if line == "" || line[0] == '#' {
					continue // skip blanks and comments
				}

				command, rest, _ := strings.Cut(line, " ")
				prefix := fmt.Sprintf("%s:%d: %s", txtfile, i+1, command) // for error messages
				switch command {
				case "checker":
					cmd := exec.Command(os.Args[0], strings.Fields(rest)...)
					cmd.Dir = dir
					cmd.Stdout = new(strings.Builder)
					cmd.Stderr = new(strings.Builder)
					cmd.Env = append(os.Environ(), "CHECKER_TEST_CHILD=1", "GOPROXY=off")
					if err := cmd.Run(); err != nil {
						if err, ok := err.(*exec.ExitError); ok {
							lastExitCode = err.ExitCode()
							// fall through
						} else {
							t.Fatalf("%s: failed to execute checker: %v (%s)", prefix, err, cmd)
						}
					} else {
						lastExitCode = 0 // success
					}

					// Eliminate nondeterministic strings from the output.
					clean := func(x any) string {
						s := fmt.Sprint(x)
						pwd, _ := os.Getwd()
						if realDir, err := filepath.EvalSymlinks(dir); err == nil {
							// Work around checker's packages.Load failing to
							// set Config.Dir to dir, causing the filenames
							// of loaded packages not to be a subdir of dir.
							s = strings.ReplaceAll(s, realDir, dir)
						}
						s = strings.ReplaceAll(s, dir, string(os.PathSeparator)+"TMP")
						s = strings.ReplaceAll(s, pwd, string(os.PathSeparator)+"PWD")
						s = strings.ReplaceAll(s, cmd.Path, filepath.Base(cmd.Path))
						return s
					}

					lastStderr = clean(cmd.Stderr)
					stdout := clean(cmd.Stdout)

					// Detect bad markers out of band:
					// though they cause a non-zero exit,
					// that may be expected.
					if strings.Contains(lastStderr, badMarker) {
						t.Errorf("marker analyzer encountered errors; stderr=%s", lastStderr)
					}

					// debugging
					if false {
						t.Logf("%s: $ %s\nstdout:\n%s\nstderr:\n%s", prefix, clean(cmd), stdout, lastStderr)
					}

					// Keep error reporting logic below consistent with
					// applyDiffsAndCompare in ../../analysistest/analysistest.go!

					unified := func(xlabel, ylabel string, x, y []byte) string {
						x = append(slices.Clip(bytes.TrimSpace(x)), '\n')
						y = append(slices.Clip(bytes.TrimSpace(y)), '\n')
						return diff.Unified(xlabel, ylabel, string(x), string(y))
					}

					// Check stdout, if there's a section of that name.
					//
					// Do not use this for testing -diff! It exposes tests to the
					// internals of our (often suboptimal) diff algorithm.
					// Instead, use the want/ mechanism.
					if f := section(ar, "stdout"); f != nil {
						got, want := []byte(stdout), f.Data
						if diff := unified("got", "want", got, want); diff != "" {
							t.Errorf("%s: unexpected stdout: -- got --\n%s-- want --\n%s-- diff --\n%s",
								prefix,
								got, want, diff)
						}
					}

					for _, f := range ar.Files {
						// For each file named want/X, assert that the
						// current content of X now equals want/X.
						if filename, ok := strings.CutPrefix(f.Name, "want/"); ok {
							fixed, err := os.ReadFile(filepath.Join(dir, filename))
							if err != nil {
								t.Errorf("reading %s: %v", filename, err)
								continue
							}
							var original []byte
							if f := section(ar, filename); f != nil {
								original = f.Data
							}
							want := f.Data
							if diff := unified(filename+" (fixed)", filename+" (want)", fixed, want); diff != "" {
								t.Errorf("%s: unexpected %s content:\n"+
									"-- original --\n%s\n"+
									"-- fixed --\n%s\n"+
									"-- want --\n%s\n"+
									"-- diff original fixed --\n%s\n"+
									"-- diff fixed want --\n%s",
									prefix, filename,
									original,
									fixed,
									want,
									unified(filename+" (original)", filename+" (fixed)", original, fixed),
									diff)
							}
						}
					}

				case "skip":
					config := fmt.Sprintf("GOOS=%s GOARCH=%s", runtime.GOOS, runtime.GOARCH)
					for word := range strings.FieldsSeq(rest) {
						if strings.Contains(config, word) {
							t.Skip(word)
						}
					}

				case "exit":
					if lastExitCode == noExitCode {
						t.Fatalf("%s: no prior 'checker' command", prefix)
					}
					var want int
					if _, err := fmt.Sscanf(rest, "%d", &want); err != nil {
						t.Fatalf("%s: requires one numeric operand", prefix)
					}
					if want != lastExitCode {
						// plan9 ExitCode() currently only returns 0 for success or 1 for failure
						if !(runtime.GOOS == "plan9" && want != exitCodeSuccess && lastExitCode != exitCodeSuccess) {
							t.Errorf("%s: exit code was %d, want %d", prefix, lastExitCode, want)
						}
					}

				case "stderr":
					if lastExitCode == noExitCode {
						t.Fatalf("%s: no prior 'checker' command", prefix)
					}
					if matched, err := regexp.MatchString(rest, lastStderr); err != nil {
						t.Fatalf("%s: invalid regexp: %v", prefix, err)
					} else if !matched {
						t.Errorf("%s: output didn't match pattern %q:\n%s", prefix, rest, lastStderr)
					}

				default:
					t.Errorf("%s: unknown command", prefix)
				}
			}
			if lastExitCode == noExitCode {
				t.Errorf("test script contains no 'checker' command")
			}
		})
	}
}

const badMarker = "[bad marker]"

// The marker analyzer generates fixes from @marker annotations in the
// source. Each marker is of the form:
//
//	@message("pattern", "replacement)
//
// The "message" is used for both the Diagnostic.Message and
// SuggestedFix.Message field. Multiple markers with the same
// message form a single diagnostic and fix with a list of textedits.
//
// The "pattern" is a regular expression that must match on the
// current line (though it may extend beyond if the pattern starts
// with "(?s)"), and whose extent forms the TextEdit.{Pos,End}
// deletion. If the pattern contains one subgroup, its range will be
// used; this allows contextual matching.
//
// The "replacement" is a literal string that forms the
// TextEdit.NewText.
//
// Fixes are applied in the order they are first mentioned in the
// source.
var markerAnalyzer = &analysis.Analyzer{
	Name:     "marker",
	Doc:      "doc",
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run: func(pass *analysis.Pass) (_ any, err error) {
		// Errors returned by this analyzer cause the
		// checker command to exit non-zero, but that
		// may be the expected outcome for other reasons
		// (e.g. there were diagnostics).
		//
		// So, we report these errors out of band by logging
		// them with a special badMarker string that the
		// TestScript harness looks for, to ensure that the
		// test fails in that case.
		defer func() {
			if err != nil {
				log.Printf("%s: %v", badMarker, err)
			}
		}()

		// Parse all notes in the files.
		var keys []string
		edits := make(map[string][]analysis.TextEdit)
		for _, file := range pass.Files {
			tokFile := pass.Fset.File(file.FileStart)
			content, err := pass.ReadFile(tokFile.Name())
			if err != nil {
				return nil, err
			}
			notes, err := expect.ExtractGo(tokFile, file)
			if err != nil {
				return nil, err
			}
			for _, note := range notes {
				edit, err := markerEdit(tokFile, content, note)
				if err != nil {
					return nil, fmt.Errorf("%s: %v", tokFile.Position(note.Pos), err)
				}
				// Preserve note order as it determines fix order.
				if edits[note.Name] == nil {
					keys = append(keys, note.Name)
				}
				edits[note.Name] = append(edits[note.Name], edit)
			}
		}

		// Report each fix in its own Diagnostic.
		for _, key := range keys {
			edits := edits[key]
			// debugging
			if false {
				log.Printf("%s: marker: @%s: %+v", pass.Fset.Position(edits[0].Pos), key, edits)
			}
			pass.Report(analysis.Diagnostic{
				Pos:     edits[0].Pos,
				End:     edits[0].Pos,
				Message: key,
				SuggestedFixes: []analysis.SuggestedFix{{
					Message:   key,
					TextEdits: edits,
				}},
			})
		}
		return nil, nil
	},
}

// markerEdit returns the TextEdit denoted by note.
func markerEdit(tokFile *token.File, content []byte, note *expect.Note) (analysis.TextEdit, error) {
	if len(note.Args) != 2 {
		return analysis.TextEdit{}, fmt.Errorf("got %d args, want @%s(pattern, replacement)", len(note.Args), note.Name)
	}

	pattern, ok := note.Args[0].(string)
	if !ok {
		return analysis.TextEdit{}, fmt.Errorf("got %T for pattern, want string", note.Args[0])
	}
	rx, err := regexp.Compile(pattern)
	if err != nil {
		return analysis.TextEdit{}, fmt.Errorf("invalid pattern regexp: %v", err)
	}

	// Match the pattern against the current line.
	lineStart := tokFile.LineStart(tokFile.Position(note.Pos).Line)
	lineStartOff := tokFile.Offset(lineStart)
	lineEndOff := tokFile.Offset(note.Pos)
	matches := rx.FindSubmatchIndex(content[lineStartOff:])
	if len(matches) == 0 {
		return analysis.TextEdit{}, fmt.Errorf("no match for regexp %q", rx)
	}
	var start, end int // line-relative offset
	switch len(matches) {
	case 2:
		// no subgroups: return the range of the regexp expression
		start, end = matches[0], matches[1]
	case 4:
		// one subgroup: return its range
		start, end = matches[2], matches[3]
	default:
		return analysis.TextEdit{}, fmt.Errorf("invalid location regexp %q: expect either 0 or 1 subgroups, got %d", rx, len(matches)/2-1)
	}
	if start > lineEndOff-lineStartOff {
		// The start of the match must be between the start of the line and the
		// marker position (inclusive).
		return analysis.TextEdit{}, fmt.Errorf("no matching range found starting on the current line")
	}

	replacement, ok := note.Args[1].(string)
	if !ok {
		return analysis.TextEdit{}, fmt.Errorf("second argument must be pattern, got %T", note.Args[1])
	}

	// debugging: show matched portion
	if false {
		log.Printf("%s: %s: r%q (%q) -> %q",
			tokFile.Position(note.Pos),
			note.Name,
			pattern,
			content[lineStartOff+start:lineStartOff+end],
			replacement)
	}

	return analysis.TextEdit{
		Pos:     lineStart + token.Pos(start),
		End:     lineStart + token.Pos(end),
		NewText: []byte(replacement),
	}, nil
}

var renameAnalyzer = &analysis.Analyzer{
	Name:             "rename",
	Requires:         []*analysis.Analyzer{inspect.Analyzer},
	Doc:              "renames symbols named bar to baz",
	RunDespiteErrors: true,
	Run: func(pass *analysis.Pass) (any, error) {
		const (
			from = "bar"
			to   = "baz"
		)
		inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
		nodeFilter := []ast.Node{(*ast.Ident)(nil)}
		inspect.Preorder(nodeFilter, func(n ast.Node) {
			ident := n.(*ast.Ident)
			if ident.Name == from {
				msg := fmt.Sprintf("renaming %q to %q", from, to)
				pass.Report(analysis.Diagnostic{
					Pos:     ident.Pos(),
					End:     ident.End(),
					Message: msg,
					SuggestedFixes: []analysis.SuggestedFix{{
						Message: msg,
						TextEdits: []analysis.TextEdit{{
							Pos:     ident.Pos(),
							End:     ident.End(),
							NewText: []byte(to),
						}},
					}},
				})
			}
		})
		return nil, nil
	},
}

var noendAnalyzer = &analysis.Analyzer{
	Name: "noend",
	Doc:  "inserts /*hello*/ before first decl",
	Run: func(pass *analysis.Pass) (any, error) {
		decl := pass.Files[0].Decls[0]
		pass.Report(analysis.Diagnostic{
			Pos:     decl.Pos(),
			End:     token.NoPos,
			Message: "say hello",
			SuggestedFixes: []analysis.SuggestedFix{{
				Message: "say hello",
				TextEdits: []analysis.TextEdit{{
					Pos:     decl.Pos(),
					End:     token.NoPos,
					NewText: []byte("/*hello*/"),
				}},
			}},
		})
		return nil, nil
	},
}

var relatedAnalyzer = &analysis.Analyzer{
	Name: "related",
	Doc:  "reports a Diagnostic with RelatedInformaiton",
	Run: func(pass *analysis.Pass) (any, error) {
		decl := pass.Files[0].Decls[0]
		pass.Report(analysis.Diagnostic{
			Pos:     decl.Pos(),
			End:     decl.Pos() + 1,
			Message: "decl starts here",
			Related: []analysis.RelatedInformation{{
				Message: "decl ends here",
				Pos:     decl.End() - 1,
				End:     decl.End(),
			}},
		})
		return nil, nil
	},
}

// panics asserts that f() panics with with a value whose printed form matches the regexp want.
func panics(t *testing.T, want string, f func()) {
	defer func() {
		if x := recover(); x == nil {
			t.Errorf("function returned normally, wanted panic")
		} else if m, err := regexp.MatchString(want, fmt.Sprint(x)); err != nil {
			t.Errorf("panics: invalid regexp %q", want)
		} else if !m {
			t.Errorf("function panicked with value %q, want match for %q", x, want)
		}
	}()
	f()
}

// section returns the named archive section, or nil.
func section(ar *txtar.Archive, name string) *txtar.File {
	for i, f := range ar.Files {
		if f.Name == name {
			return &ar.Files[i]
		}
	}
	return nil
}
