// Copyright 2020 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 unusedvariable defines an analyzer that checks for unused variables.
package unusedvariable

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

	"golang.org/x/tools/go/analysis"
	"golang.org/x/tools/go/ast/astutil"
)

const Doc = `check for unused variables and suggest fixes`

var Analyzer = &analysis.Analyzer{
	Name:             "unusedvariable",
	Doc:              Doc,
	Requires:         []*analysis.Analyzer{},
	Run:              run,
	RunDespiteErrors: true, // an unusedvariable diagnostic is a compile error
	URL:              "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/unusedvariable",
}

// The suffix for this error message changed in Go 1.20.
var unusedVariableSuffixes = []string{" declared and not used", " declared but not used"}

func run(pass *analysis.Pass) (interface{}, error) {
	for _, typeErr := range pass.TypeErrors {
		for _, suffix := range unusedVariableSuffixes {
			if strings.HasSuffix(typeErr.Msg, suffix) {
				varName := strings.TrimSuffix(typeErr.Msg, suffix)
				// Beginning in Go 1.23, go/types began quoting vars as `v'.
				varName = strings.Trim(varName, "'`'")

				err := runForError(pass, typeErr, varName)
				if err != nil {
					return nil, err
				}
			}
		}
	}

	return nil, nil
}

func runForError(pass *analysis.Pass, err types.Error, name string) error {
	var file *ast.File
	for _, f := range pass.Files {
		if f.Pos() <= err.Pos && err.Pos < f.End() {
			file = f
			break
		}
	}
	if file == nil {
		return nil
	}

	path, _ := astutil.PathEnclosingInterval(file, err.Pos, err.Pos)
	if len(path) < 2 {
		return nil
	}

	ident, ok := path[0].(*ast.Ident)
	if !ok || ident.Name != name {
		return nil
	}

	diag := analysis.Diagnostic{
		Pos:     ident.Pos(),
		End:     ident.End(),
		Message: err.Msg,
	}

	for i := range path {
		switch stmt := path[i].(type) {
		case *ast.ValueSpec:
			// Find GenDecl to which offending ValueSpec belongs.
			if decl, ok := path[i+1].(*ast.GenDecl); ok {
				fixes := removeVariableFromSpec(pass, path, stmt, decl, ident)
				// fixes may be nil
				if len(fixes) > 0 {
					diag.SuggestedFixes = fixes
					pass.Report(diag)
				}
			}

		case *ast.AssignStmt:
			if stmt.Tok != token.DEFINE {
				continue
			}

			containsIdent := false
			for _, expr := range stmt.Lhs {
				if expr == ident {
					containsIdent = true
				}
			}
			if !containsIdent {
				continue
			}

			fixes := removeVariableFromAssignment(path, stmt, ident)
			// fixes may be nil
			if len(fixes) > 0 {
				diag.SuggestedFixes = fixes
				pass.Report(diag)
			}
		}
	}

	return nil
}

func removeVariableFromSpec(pass *analysis.Pass, path []ast.Node, stmt *ast.ValueSpec, decl *ast.GenDecl, ident *ast.Ident) []analysis.SuggestedFix {
	newDecl := new(ast.GenDecl)
	*newDecl = *decl
	newDecl.Specs = nil

	for _, spec := range decl.Specs {
		if spec != stmt {
			newDecl.Specs = append(newDecl.Specs, spec)
			continue
		}

		newSpec := new(ast.ValueSpec)
		*newSpec = *stmt
		newSpec.Names = nil

		for _, n := range stmt.Names {
			if n != ident {
				newSpec.Names = append(newSpec.Names, n)
			}
		}

		if len(newSpec.Names) > 0 {
			newDecl.Specs = append(newDecl.Specs, newSpec)
		}
	}

	// decl.End() does not include any comments, so if a comment is present we
	// need to account for it when we delete the statement
	end := decl.End()
	if stmt.Comment != nil && stmt.Comment.End() > end {
		end = stmt.Comment.End()
	}

	// There are no other specs left in the declaration, the whole statement can
	// be deleted
	if len(newDecl.Specs) == 0 {
		// Find parent DeclStmt and delete it
		for _, node := range path {
			if declStmt, ok := node.(*ast.DeclStmt); ok {
				edits := deleteStmtFromBlock(path, declStmt)
				if len(edits) == 0 {
					return nil // can this happen?
				}
				return []analysis.SuggestedFix{
					{
						Message:   suggestedFixMessage(ident.Name),
						TextEdits: edits,
					},
				}
			}
		}
	}

	var b bytes.Buffer
	if err := format.Node(&b, pass.Fset, newDecl); err != nil {
		return nil
	}

	return []analysis.SuggestedFix{
		{
			Message: suggestedFixMessage(ident.Name),
			TextEdits: []analysis.TextEdit{
				{
					Pos: decl.Pos(),
					// Avoid adding a new empty line
					End:     end + 1,
					NewText: b.Bytes(),
				},
			},
		},
	}
}

func removeVariableFromAssignment(path []ast.Node, stmt *ast.AssignStmt, ident *ast.Ident) []analysis.SuggestedFix {
	// The only variable in the assignment is unused
	if len(stmt.Lhs) == 1 {
		// If LHS has only one expression to be valid it has to have 1 expression
		// on RHS
		//
		// RHS may have side effects, preserve RHS
		if exprMayHaveSideEffects(stmt.Rhs[0]) {
			// Delete until RHS
			return []analysis.SuggestedFix{
				{
					Message: suggestedFixMessage(ident.Name),
					TextEdits: []analysis.TextEdit{
						{
							Pos: ident.Pos(),
							End: stmt.Rhs[0].Pos(),
						},
					},
				},
			}
		}

		// RHS does not have any side effects, delete the whole statement
		edits := deleteStmtFromBlock(path, stmt)
		if len(edits) == 0 {
			return nil // can this happen?
		}
		return []analysis.SuggestedFix{
			{
				Message:   suggestedFixMessage(ident.Name),
				TextEdits: edits,
			},
		}
	}

	// Otherwise replace ident with `_`
	return []analysis.SuggestedFix{
		{
			Message: suggestedFixMessage(ident.Name),
			TextEdits: []analysis.TextEdit{
				{
					Pos:     ident.Pos(),
					End:     ident.End(),
					NewText: []byte("_"),
				},
			},
		},
	}
}

func suggestedFixMessage(name string) string {
	return fmt.Sprintf("Remove variable %s", name)
}

func deleteStmtFromBlock(path []ast.Node, stmt ast.Stmt) []analysis.TextEdit {
	// Find innermost enclosing BlockStmt.
	var block *ast.BlockStmt
	for i := range path {
		if blockStmt, ok := path[i].(*ast.BlockStmt); ok {
			block = blockStmt
			break
		}
	}

	nodeIndex := -1
	for i, blockStmt := range block.List {
		if blockStmt == stmt {
			nodeIndex = i
			break
		}
	}

	// The statement we need to delete was not found in BlockStmt
	if nodeIndex == -1 {
		return nil
	}

	// Delete until the end of the block unless there is another statement after
	// the one we are trying to delete
	end := block.Rbrace
	if nodeIndex < len(block.List)-1 {
		end = block.List[nodeIndex+1].Pos()
	}

	return []analysis.TextEdit{
		{
			Pos: stmt.Pos(),
			End: end,
		},
	}
}

// exprMayHaveSideEffects reports whether the expression may have side effects
// (because it contains a function call or channel receive). We disregard
// runtime panics as well written programs should not encounter them.
func exprMayHaveSideEffects(expr ast.Expr) bool {
	var mayHaveSideEffects bool
	ast.Inspect(expr, func(n ast.Node) bool {
		switch n := n.(type) {
		case *ast.CallExpr: // possible function call
			mayHaveSideEffects = true
			return false
		case *ast.UnaryExpr:
			if n.Op == token.ARROW { // channel receive
				mayHaveSideEffects = true
				return false
			}
		case *ast.FuncLit:
			return false // evaluating what's inside a FuncLit has no effect
		}
		return true
	})

	return mayHaveSideEffects
}
