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