// 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)
				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 {
				return []analysis.SuggestedFix{
					{
						Message:   suggestedFixMessage(ident.Name),
						TextEdits: deleteStmtFromBlock(path, declStmt),
					},
				}
			}
		}
	}

	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
		return []analysis.SuggestedFix{
			{
				Message:   suggestedFixMessage(ident.Name),
				TextEdits: deleteStmtFromBlock(path, stmt),
			},
		}
	}

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