// Copyright 2019 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 (
	"fmt"
	"go/ast"
	"os"
	"path/filepath"
	"reflect"
	"testing"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/analysistest"
	"golang.org/x/tools/go/analysis/internal/checker"
	"golang.org/x/tools/go/analysis/passes/inspect"
	"golang.org/x/tools/go/ast/inspector"
	"golang.org/x/tools/internal/testenv"
)

func TestApplyFixes(t *testing.T) {
	testenv.NeedsGoPackages(t)

	files := map[string]string{
		"rename/test.go": `package rename

func Foo() {
	bar := 12
	_ = bar
}

// the end
`}
	want := `package rename

func Foo() {
	baz := 12
	_ = baz
}

// the end
`

	testdata, cleanup, err := analysistest.WriteFiles(files)
	if err != nil {
		t.Fatal(err)
	}
	path := filepath.Join(testdata, "src/rename/test.go")
	checker.Fix = true
	checker.Run([]string{"file=" + path}, []*analysis.Analyzer{renameAnalyzer})

	contents, err := os.ReadFile(path)
	if err != nil {
		t.Fatal(err)
	}

	got := string(contents)
	if got != want {
		t.Errorf("contents of rewritten file\ngot: %s\nwant: %s", got, want)
	}

	defer cleanup()
}

var renameAnalyzer = &analysis.Analyzer{
	Name:     "rename",
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run:      run,
	Doc:      "renames symbols named bar to baz",
}

var otherAnalyzer = &analysis.Analyzer{ // like analyzer but with a different Name.
	Name:     "other",
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run:      run,
	Doc:      "renames symbols named bar to baz only in package 'other'",
}

func run(pass *analysis.Pass) (interface{}, error) {
	const (
		from      = "bar"
		to        = "baz"
		conflict  = "conflict"  // add conflicting edits to package conflict.
		duplicate = "duplicate" // add duplicate edits to package conflict.
		other     = "other"     // add conflicting edits to package other from different analyzers.
	)

	if pass.Analyzer.Name == other {
		if pass.Pkg.Name() != other {
			return nil, nil // only apply Analyzer other to packages named other
		}
	}

	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)
			edits := []analysis.TextEdit{
				{Pos: ident.Pos(), End: ident.End(), NewText: []byte(to)},
			}
			switch pass.Pkg.Name() {
			case conflict:
				edits = append(edits, []analysis.TextEdit{
					{Pos: ident.Pos() - 1, End: ident.End(), NewText: []byte(to)},
					{Pos: ident.Pos(), End: ident.End() - 1, NewText: []byte(to)},
					{Pos: ident.Pos(), End: ident.End(), NewText: []byte("lorem ipsum")},
				}...)
			case duplicate:
				edits = append(edits, edits...)
			case other:
				if pass.Analyzer.Name == other {
					edits[0].Pos = edits[0].Pos + 1 // shift by one to mismatch analyzer and other
				}
			}
			pass.Report(analysis.Diagnostic{
				Pos:            ident.Pos(),
				End:            ident.End(),
				Message:        msg,
				SuggestedFixes: []analysis.SuggestedFix{{Message: msg, TextEdits: edits}}})
		}
	})

	return nil, nil
}

func TestRunDespiteErrors(t *testing.T) {
	testenv.NeedsGoPackages(t)

	files := map[string]string{
		"rderr/test.go": `package rderr

// Foo deliberately has a type error
func Foo(s string) int {
	return s + 1
}
`}

	testdata, cleanup, err := analysistest.WriteFiles(files)
	if err != nil {
		t.Fatal(err)
	}
	path := filepath.Join(testdata, "src/rderr/test.go")

	// A no-op analyzer that should finish regardless of
	// parse or type errors in the code.
	noop := &analysis.Analyzer{
		Name:     "noop",
		Requires: []*analysis.Analyzer{inspect.Analyzer},
		Run: func(pass *analysis.Pass) (interface{}, error) {
			return nil, nil
		},
		RunDespiteErrors: true,
	}

	// A no-op analyzer that should finish regardless of
	// parse or type errors in the code.
	noopWithFact := &analysis.Analyzer{
		Name:     "noopfact",
		Requires: []*analysis.Analyzer{inspect.Analyzer},
		Run: func(pass *analysis.Pass) (interface{}, error) {
			return nil, nil
		},
		RunDespiteErrors: true,
		FactTypes:        []analysis.Fact{&EmptyFact{}},
	}

	for _, test := range []struct {
		name      string
		pattern   []string
		analyzers []*analysis.Analyzer
		code      int
	}{
		// parse/type errors
		{name: "skip-error", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{renameAnalyzer}, code: 1},
		// RunDespiteErrors allows a driver to run an Analyzer even after parse/type errors.
		//
		// The noop analyzer doesn't use facts, so the driver loads only the root
		// package from source. For the rest, it asks 'go list' for export data,
		// which fails because the compiler encounters the type error.  Since the
		// errors come from 'go list', the driver doesn't run the analyzer.
		{name: "despite-error", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{noop}, code: 1},
		// The noopfact analyzer does use facts, so the driver loads source for
		// all dependencies, does type checking itself, recognizes the error as a
		// type error, and runs the analyzer.
		{name: "despite-error-fact", pattern: []string{"file=" + path}, analyzers: []*analysis.Analyzer{noopWithFact}, code: 0},
		// combination of parse/type errors and no errors
		{name: "despite-error-and-no-error", pattern: []string{"file=" + path, "sort"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: 1},
		// non-existing package error
		{name: "no-package", pattern: []string{"xyz"}, analyzers: []*analysis.Analyzer{renameAnalyzer}, code: 1},
		{name: "no-package-despite-error", pattern: []string{"abc"}, analyzers: []*analysis.Analyzer{noop}, code: 1},
		{name: "no-multi-package-despite-error", pattern: []string{"xyz", "abc"}, analyzers: []*analysis.Analyzer{noop}, code: 1},
		// combination of type/parsing and different errors
		{name: "different-errors", pattern: []string{"file=" + path, "xyz"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: 1},
		// non existing dir error
		{name: "no-match-dir", pattern: []string{"file=non/existing/dir"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: 1},
		// no errors
		{name: "no-errors", pattern: []string{"sort"}, analyzers: []*analysis.Analyzer{renameAnalyzer, noop}, code: 0},
	} {
		if test.name == "despite-error" && testenv.Go1Point() < 20 {
			// The behavior in the comment on the despite-error test only occurs for Go 1.20+.
			continue
		}
		if got := checker.Run(test.pattern, test.analyzers); got != test.code {
			t.Errorf("got incorrect exit code %d for test %s; want %d", got, test.name, test.code)
		}
	}

	defer cleanup()
}

type EmptyFact struct{}

func (f *EmptyFact) AFact() {}

func TestURL(t *testing.T) {
	// TestURL test that URLs get forwarded to diagnostics by internal/checker.
	testenv.NeedsGoPackages(t)

	files := map[string]string{
		"p/test.go": `package p // want "package name is p"`,
	}
	pkgname := &analysis.Analyzer{
		Name: "pkgname",
		Doc:  "trivial analyzer that reports package names",
		URL:  "https://pkg.go.dev/golang.org/x/tools/go/analysis/internal/checker",
		Run: func(p *analysis.Pass) (interface{}, error) {
			for _, f := range p.Files {
				p.ReportRangef(f.Name, "package name is %s", f.Name.Name)
			}
			return nil, nil
		},
	}

	testdata, cleanup, err := analysistest.WriteFiles(files)
	if err != nil {
		t.Fatal(err)
	}
	defer cleanup()
	path := filepath.Join(testdata, "src/p/test.go")
	results := analysistest.Run(t, testdata, pkgname, "file="+path)

	var urls []string
	for _, r := range results {
		for _, d := range r.Diagnostics {
			urls = append(urls, d.URL)
		}
	}
	want := []string{"https://pkg.go.dev/golang.org/x/tools/go/analysis/internal/checker"}
	if !reflect.DeepEqual(urls, want) {
		t.Errorf("Expected Diagnostics.URLs %v. got %v", want, urls)
	}
}
