// 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 simplifycompositelit defines an Analyzer that simplifies composite literals.
// https://github.com/golang/go/blob/master/src/cmd/gofmt/simplify.go
// https://golang.org/cmd/gofmt/#hdr-The_simplify_command
package simplifycompositelit

import (
	"bytes"
	_ "embed"
	"fmt"
	"go/ast"
	"go/printer"
	"go/token"
	"reflect"

	"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"
)

//go:embed doc.go
var doc string

var Analyzer = &analysis.Analyzer{
	Name:     "simplifycompositelit",
	Doc:      analysisinternal.MustExtractDoc(doc, "simplifycompositelit"),
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run:      run,
	URL:      "https://pkg.go.dev/golang.org/x/tools/gopls/internal/analysis/simplifycompositelit",
}

func run(pass *analysis.Pass) (any, error) {
	// Gather information whether file is generated or not
	generated := make(map[*token.File]bool)
	for _, file := range pass.Files {
		if ast.IsGenerated(file) {
			generated[pass.Fset.File(file.FileStart)] = true
		}
	}

	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
	nodeFilter := []ast.Node{(*ast.CompositeLit)(nil)}
	inspect.Preorder(nodeFilter, func(n ast.Node) {
		if _, ok := generated[pass.Fset.File(n.Pos())]; ok {
			return // skip checking if it's generated code
		}

		expr := n.(*ast.CompositeLit)

		outer := expr
		var keyType, eltType ast.Expr
		switch typ := outer.Type.(type) {
		case *ast.ArrayType:
			eltType = typ.Elt
		case *ast.MapType:
			keyType = typ.Key
			eltType = typ.Value
		}

		if eltType == nil {
			return
		}
		var ktyp reflect.Value
		if keyType != nil {
			ktyp = reflect.ValueOf(keyType)
		}
		typ := reflect.ValueOf(eltType)
		for _, x := range outer.Elts {
			// look at value of indexed/named elements
			if t, ok := x.(*ast.KeyValueExpr); ok {
				if keyType != nil {
					simplifyLiteral(pass, ktyp, keyType, t.Key)
				}
				x = t.Value
			}
			simplifyLiteral(pass, typ, eltType, x)
		}
	})
	return nil, nil
}

func simplifyLiteral(pass *analysis.Pass, typ reflect.Value, astType, x ast.Expr) {
	// if the element is a composite literal and its literal type
	// matches the outer literal's element type exactly, the inner
	// literal type may be omitted
	if inner, ok := x.(*ast.CompositeLit); ok && match(typ, reflect.ValueOf(inner.Type)) {
		var b bytes.Buffer
		printer.Fprint(&b, pass.Fset, inner.Type) // ignore error
		createDiagnostic(pass, inner.Type.Pos(), inner.Type.End(), b.String())
	}
	// if the outer literal's element type is a pointer type *T
	// and the element is & of a composite literal of type T,
	// the inner &T may be omitted.
	if ptr, ok := astType.(*ast.StarExpr); ok {
		if addr, ok := x.(*ast.UnaryExpr); ok && addr.Op == token.AND {
			if inner, ok := addr.X.(*ast.CompositeLit); ok {
				if match(reflect.ValueOf(ptr.X), reflect.ValueOf(inner.Type)) {
					var b bytes.Buffer
					printer.Fprint(&b, pass.Fset, inner.Type) // ignore error
					// Account for the & by subtracting 1 from typ.Pos().
					createDiagnostic(pass, inner.Type.Pos()-1, inner.Type.End(), "&"+b.String())
				}
			}
		}
	}
}

func createDiagnostic(pass *analysis.Pass, start, end token.Pos, typ string) {
	pass.Report(analysis.Diagnostic{
		Pos:     start,
		End:     end,
		Message: "redundant type from array, slice, or map composite literal",
		SuggestedFixes: []analysis.SuggestedFix{{
			Message: fmt.Sprintf("Remove '%s'", typ),
			TextEdits: []analysis.TextEdit{{
				Pos:     start,
				End:     end,
				NewText: []byte{},
			}},
		}},
	})
}

// match reports whether pattern matches val,
// recording wildcard submatches in m.
// If m == nil, match checks whether pattern == val.
// from https://github.com/golang/go/blob/26154f31ad6c801d8bad5ef58df1e9263c6beec7/src/cmd/gofmt/rewrite.go#L160
func match(pattern, val reflect.Value) bool {
	// Otherwise, pattern and val must match recursively.
	if !pattern.IsValid() || !val.IsValid() {
		return !pattern.IsValid() && !val.IsValid()
	}
	if pattern.Type() != val.Type() {
		return false
	}

	// Special cases.
	switch pattern.Type() {
	case identType:
		// For identifiers, only the names need to match
		// (and none of the other *ast.Object information).
		// This is a common case, handle it all here instead
		// of recursing down any further via reflection.
		p := pattern.Interface().(*ast.Ident)
		v := val.Interface().(*ast.Ident)
		return p == nil && v == nil || p != nil && v != nil && p.Name == v.Name
	case objectPtrType, positionType:
		// object pointers and token positions always match
		return true
	case callExprType:
		// For calls, the Ellipsis fields (token.Position) must
		// match since that is how f(x) and f(x...) are different.
		// Check them here but fall through for the remaining fields.
		p := pattern.Interface().(*ast.CallExpr)
		v := val.Interface().(*ast.CallExpr)
		if p.Ellipsis.IsValid() != v.Ellipsis.IsValid() {
			return false
		}
	}

	p := reflect.Indirect(pattern)
	v := reflect.Indirect(val)
	if !p.IsValid() || !v.IsValid() {
		return !p.IsValid() && !v.IsValid()
	}

	switch p.Kind() {
	case reflect.Slice:
		if p.Len() != v.Len() {
			return false
		}
		for i := 0; i < p.Len(); i++ {
			if !match(p.Index(i), v.Index(i)) {
				return false
			}
		}
		return true

	case reflect.Struct:
		for i := 0; i < p.NumField(); i++ {
			if !match(p.Field(i), v.Field(i)) {
				return false
			}
		}
		return true

	case reflect.Interface:
		return match(p.Elem(), v.Elem())
	}

	// Handle token integers, etc.
	return p.Interface() == v.Interface()
}

// Values/types for special cases.
var (
	identType     = reflect.TypeOf((*ast.Ident)(nil))
	objectPtrType = reflect.TypeOf((*ast.Object)(nil))
	positionType  = reflect.TypeOf(token.NoPos)
	callExprType  = reflect.TypeOf((*ast.CallExpr)(nil))
)
