// Copyright 2023 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 deprecated

import (
	"bytes"
	"go/ast"
	"go/format"
	"go/token"
	"go/types"
	"strconv"
	"strings"

	_ "embed"

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/analysis/passes/inspect"
	"golang.org/x/tools/go/ast/inspector"
	"golang.org/x/tools/internal/analysisinternal"
	"golang.org/x/tools/internal/typeparams"
)

//go:embed doc.go
var doc string

var Analyzer = &analysis.Analyzer{
	Name:             "deprecated",
	Doc:              analysisinternal.MustExtractDoc(doc, "deprecated"),
	Requires:         []*analysis.Analyzer{inspect.Analyzer},
	Run:              checkDeprecated,
	FactTypes:        []analysis.Fact{(*deprecationFact)(nil)},
	RunDespiteErrors: true,
	URL:              "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/deprecated",
}

// checkDeprecated is a simplified copy of staticcheck.CheckDeprecated.
func checkDeprecated(pass *analysis.Pass) (interface{}, error) {
	inspector := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)

	deprs, err := collectDeprecatedNames(pass, inspector)
	if err != nil || (len(deprs.packages) == 0 && len(deprs.objects) == 0) {
		return nil, err
	}

	reportDeprecation := func(depr *deprecationFact, node ast.Node) {
		// TODO(hyangah): staticcheck.CheckDeprecated has more complex logic. Do we need it here?
		// TODO(hyangah): Scrub depr.Msg. depr.Msg may contain Go comments
		// markdown syntaxes but LSP diagnostics do not support markdown syntax.

		buf := new(bytes.Buffer)
		if err := format.Node(buf, pass.Fset, node); err != nil {
			// This shouldn't happen but let's be conservative.
			buf.Reset()
			buf.WriteString("declaration")
		}
		pass.ReportRangef(node, "%s is deprecated: %s", buf, depr.Msg)
	}

	nodeFilter := []ast.Node{(*ast.SelectorExpr)(nil)}
	inspector.Preorder(nodeFilter, func(node ast.Node) {
		// Caveat: this misses dot-imported objects
		sel, ok := node.(*ast.SelectorExpr)
		if !ok {
			return
		}

		obj := pass.TypesInfo.ObjectOf(sel.Sel)
		if obj_, ok := obj.(*types.Func); ok {
			obj = typeparams.OriginMethod(obj_)
		}
		if obj == nil || obj.Pkg() == nil {
			// skip invalid sel.Sel.
			return
		}

		if obj.Pkg() == pass.Pkg {
			// A package is allowed to use its own deprecated objects
			return
		}

		// A package "foo" has two related packages "foo_test" and "foo.test", for external tests and the package main
		// generated by 'go test' respectively. "foo_test" can import and use "foo", "foo.test" imports and uses "foo"
		// and "foo_test".

		if strings.TrimSuffix(pass.Pkg.Path(), "_test") == obj.Pkg().Path() {
			// foo_test (the external tests of foo) can use objects from foo.
			return
		}
		if strings.TrimSuffix(pass.Pkg.Path(), ".test") == obj.Pkg().Path() {
			// foo.test (the main package of foo's tests) can use objects from foo.
			return
		}
		if strings.TrimSuffix(pass.Pkg.Path(), ".test") == strings.TrimSuffix(obj.Pkg().Path(), "_test") {
			// foo.test (the main package of foo's tests) can use objects from foo's external tests.
			return
		}

		if depr, ok := deprs.objects[obj]; ok {
			reportDeprecation(depr, sel)
		}
	})

	for _, f := range pass.Files {
		for _, spec := range f.Imports {
			var imp *types.Package
			var obj types.Object
			if spec.Name != nil {
				obj = pass.TypesInfo.ObjectOf(spec.Name)
			} else {
				obj = pass.TypesInfo.Implicits[spec]
			}
			pkgName, ok := obj.(*types.PkgName)
			if !ok {
				continue
			}
			imp = pkgName.Imported()

			path, err := strconv.Unquote(spec.Path.Value)
			if err != nil {
				continue
			}
			pkgPath := pass.Pkg.Path()
			if strings.TrimSuffix(pkgPath, "_test") == path {
				// foo_test can import foo
				continue
			}
			if strings.TrimSuffix(pkgPath, ".test") == path {
				// foo.test can import foo
				continue
			}
			if strings.TrimSuffix(pkgPath, ".test") == strings.TrimSuffix(path, "_test") {
				// foo.test can import foo_test
				continue
			}
			if depr, ok := deprs.packages[imp]; ok {
				reportDeprecation(depr, spec.Path)
			}
		}
	}
	return nil, nil
}

type deprecationFact struct{ Msg string }

func (*deprecationFact) AFact()           {}
func (d *deprecationFact) String() string { return "Deprecated: " + d.Msg }

type deprecatedNames struct {
	objects  map[types.Object]*deprecationFact
	packages map[*types.Package]*deprecationFact
}

// collectDeprecatedNames collects deprecated identifiers and publishes
// them both as Facts and the return value. This is a simplified copy
// of staticcheck's fact_deprecated analyzer.
func collectDeprecatedNames(pass *analysis.Pass, ins *inspector.Inspector) (deprecatedNames, error) {
	extractDeprecatedMessage := func(docs []*ast.CommentGroup) string {
		for _, doc := range docs {
			if doc == nil {
				continue
			}
			parts := strings.Split(doc.Text(), "\n\n")
			for _, part := range parts {
				if !strings.HasPrefix(part, "Deprecated: ") {
					continue
				}
				alt := part[len("Deprecated: "):]
				alt = strings.Replace(alt, "\n", " ", -1)
				return strings.TrimSpace(alt)
			}
		}
		return ""
	}

	doDocs := func(names []*ast.Ident, docs *ast.CommentGroup) {
		alt := extractDeprecatedMessage([]*ast.CommentGroup{docs})
		if alt == "" {
			return
		}

		for _, name := range names {
			obj := pass.TypesInfo.ObjectOf(name)
			pass.ExportObjectFact(obj, &deprecationFact{alt})
		}
	}

	var docs []*ast.CommentGroup
	for _, f := range pass.Files {
		docs = append(docs, f.Doc)
	}
	if alt := extractDeprecatedMessage(docs); alt != "" {
		// Don't mark package syscall as deprecated, even though
		// it is. A lot of people still use it for simple
		// constants like SIGKILL, and I am not comfortable
		// telling them to use x/sys for that.
		if pass.Pkg.Path() != "syscall" {
			pass.ExportPackageFact(&deprecationFact{alt})
		}
	}
	nodeFilter := []ast.Node{
		(*ast.GenDecl)(nil),
		(*ast.FuncDecl)(nil),
		(*ast.TypeSpec)(nil),
		(*ast.ValueSpec)(nil),
		(*ast.File)(nil),
		(*ast.StructType)(nil),
		(*ast.InterfaceType)(nil),
	}
	ins.Preorder(nodeFilter, func(node ast.Node) {
		var names []*ast.Ident
		var docs *ast.CommentGroup
		switch node := node.(type) {
		case *ast.GenDecl:
			switch node.Tok {
			case token.TYPE, token.CONST, token.VAR:
				docs = node.Doc
				for i := range node.Specs {
					switch n := node.Specs[i].(type) {
					case *ast.ValueSpec:
						names = append(names, n.Names...)
					case *ast.TypeSpec:
						names = append(names, n.Name)
					}
				}
			default:
				return
			}
		case *ast.FuncDecl:
			docs = node.Doc
			names = []*ast.Ident{node.Name}
		case *ast.TypeSpec:
			docs = node.Doc
			names = []*ast.Ident{node.Name}
		case *ast.ValueSpec:
			docs = node.Doc
			names = node.Names
		case *ast.StructType:
			for _, field := range node.Fields.List {
				doDocs(field.Names, field.Doc)
			}
		case *ast.InterfaceType:
			for _, field := range node.Methods.List {
				doDocs(field.Names, field.Doc)
			}
		}
		if docs != nil && len(names) > 0 {
			doDocs(names, docs)
		}
	})

	// Every identifier is potentially deprecated, so we will need
	// to look up facts a lot. Construct maps of all facts propagated
	// to this pass for fast lookup.
	out := deprecatedNames{
		objects:  map[types.Object]*deprecationFact{},
		packages: map[*types.Package]*deprecationFact{},
	}
	for _, fact := range pass.AllObjectFacts() {
		out.objects[fact.Object] = fact.Fact.(*deprecationFact)
	}
	for _, fact := range pass.AllPackageFacts() {
		out.packages[fact.Package] = fact.Fact.(*deprecationFact)
	}

	return out, nil
}
