// 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 analyzer

import (
	"fmt"
	"go/ast"
	"go/token"
	"go/types"
	"os"
	"strings"

	"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/go/types/typeutil"
	"golang.org/x/tools/internal/diff"
	"golang.org/x/tools/internal/refactor/inline"
)

const Doc = `inline calls to functions with "inlineme" doc comment`

var Analyzer = &analysis.Analyzer{
	Name:      "inline",
	Doc:       Doc,
	URL:       "https://pkg.go.dev/golang.org/x/tools/internal/refactor/inline/analyzer",
	Run:       run,
	FactTypes: []analysis.Fact{new(inlineMeFact)},
	Requires:  []*analysis.Analyzer{inspect.Analyzer},
}

func run(pass *analysis.Pass) (interface{}, error) {
	// Memoize repeated calls for same file.
	// TODO(adonovan): the analysis.Pass should abstract this (#62292)
	// as the driver may not be reading directly from the file system.
	fileContent := make(map[string][]byte)
	readFile := func(node ast.Node) ([]byte, error) {
		filename := pass.Fset.File(node.Pos()).Name()
		content, ok := fileContent[filename]
		if !ok {
			var err error
			content, err = os.ReadFile(filename)
			if err != nil {
				return nil, err
			}
			fileContent[filename] = content
		}
		return content, nil
	}

	// Pass 1: find functions annotated with an "inlineme"
	// comment, and export a fact for each one.
	inlinable := make(map[*types.Func]*inline.Callee) // memoization of fact import (nil => no fact)
	for _, file := range pass.Files {
		for _, decl := range file.Decls {
			if decl, ok := decl.(*ast.FuncDecl); ok {
				// TODO(adonovan): this is just a placeholder.
				// Use the precise go:fix syntax in the proposal.
				// Beware that //go: comments are treated specially
				// by (*ast.CommentGroup).Text().
				// TODO(adonovan): alternatively, consider using
				// the universal annotation mechanism sketched in
				// https://go.dev/cl/489835 (which doesn't yet have
				// a proper proposal).
				if strings.Contains(decl.Doc.Text(), "inlineme") {
					content, err := readFile(file)
					if err != nil {
						pass.Reportf(decl.Doc.Pos(), "invalid inlining candidate: cannot read source file: %v", err)
						continue
					}
					callee, err := inline.AnalyzeCallee(discard, pass.Fset, pass.Pkg, pass.TypesInfo, decl, content)
					if err != nil {
						pass.Reportf(decl.Doc.Pos(), "invalid inlining candidate: %v", err)
						continue
					}
					fn := pass.TypesInfo.Defs[decl.Name].(*types.Func)
					pass.ExportObjectFact(fn, &inlineMeFact{callee})
					inlinable[fn] = callee
				}
			}
		}
	}

	// Pass 2. Inline each static call to an inlinable function.
	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
	nodeFilter := []ast.Node{
		(*ast.File)(nil),
		(*ast.CallExpr)(nil),
	}
	var currentFile *ast.File
	inspect.Preorder(nodeFilter, func(n ast.Node) {
		if file, ok := n.(*ast.File); ok {
			currentFile = file
			return
		}
		call := n.(*ast.CallExpr)
		if fn := typeutil.StaticCallee(pass.TypesInfo, call); fn != nil {
			// Inlinable?
			callee, ok := inlinable[fn]
			if !ok {
				var fact inlineMeFact
				if pass.ImportObjectFact(fn, &fact) {
					callee = fact.Callee
					inlinable[fn] = callee
				}
			}
			if callee == nil {
				return // nope
			}

			// Inline the call.
			content, err := readFile(call)
			if err != nil {
				pass.Reportf(call.Lparen, "invalid inlining candidate: cannot read source file: %v", err)
				return
			}
			caller := &inline.Caller{
				Fset:    pass.Fset,
				Types:   pass.Pkg,
				Info:    pass.TypesInfo,
				File:    currentFile,
				Call:    call,
				Content: content,
			}
			res, err := inline.Inline(caller, callee, &inline.Options{Logf: discard})
			if err != nil {
				pass.Reportf(call.Lparen, "%v", err)
				return
			}
			got := res.Content

			// Suggest the "fix".
			var textEdits []analysis.TextEdit
			for _, edit := range diff.Bytes(content, got) {
				textEdits = append(textEdits, analysis.TextEdit{
					Pos:     currentFile.FileStart + token.Pos(edit.Start),
					End:     currentFile.FileStart + token.Pos(edit.End),
					NewText: []byte(edit.New),
				})
			}
			msg := fmt.Sprintf("inline call of %v", callee)
			pass.Report(analysis.Diagnostic{
				Pos:     call.Pos(),
				End:     call.End(),
				Message: msg,
				SuggestedFixes: []analysis.SuggestedFix{{
					Message:   msg,
					TextEdits: textEdits,
				}},
			})
		}
	})

	return nil, nil
}

type inlineMeFact struct{ Callee *inline.Callee }

func (f *inlineMeFact) String() string { return "inlineme " + f.Callee.String() }
func (*inlineMeFact) AFact()           {}

func discard(string, ...any) {}
