// 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"
	"io/ioutil"
	"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{analyzer})

	contents, err := ioutil.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 analyzer = &analysis.Analyzer{
	Name:     "rename",
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run:      run,
}

var other = &analysis.Analyzer{ // like analyzer but with a different Name.
	Name:     "other",
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run:      run,
}

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{analyzer}, 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{analyzer, noop}, code: 1},
		// non-existing package error
		{name: "no-package", pattern: []string{"xyz"}, analyzers: []*analysis.Analyzer{analyzer}, 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{analyzer, noop}, code: 1},
		// non existing dir error
		{name: "no-match-dir", pattern: []string{"file=non/existing/dir"}, analyzers: []*analysis.Analyzer{analyzer, noop}, code: 1},
		// no errors
		{name: "no-errors", pattern: []string{"sort"}, analyzers: []*analysis.Analyzer{analyzer, 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)
	}
}
