// Copyright 2012 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 composite defines an Analyzer that checks for unkeyed
// composite literals.
package composite

import (
	"fmt"
	"go/ast"
	"go/types"
	"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/internal/typeparams"
)

const Doc = `check for unkeyed composite literals

This analyzer reports a diagnostic for composite literals of struct
types imported from another package that do not use the field-keyed
syntax. Such literals are fragile because the addition of a new field
(even if unexported) to the struct will cause compilation to fail.

As an example,

	err = &net.DNSConfigError{err}

should be replaced by:

	err = &net.DNSConfigError{Err: err}
`

var Analyzer = &analysis.Analyzer{
	Name:             "composites",
	Doc:              Doc,
	Requires:         []*analysis.Analyzer{inspect.Analyzer},
	RunDespiteErrors: true,
	Run:              run,
}

var whitelist = true

func init() {
	Analyzer.Flags.BoolVar(&whitelist, "whitelist", whitelist, "use composite white list; for testing only")
}

// runUnkeyedLiteral checks if a composite literal is a struct literal with
// unkeyed fields.
func run(pass *analysis.Pass) (interface{}, error) {
	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)

	nodeFilter := []ast.Node{
		(*ast.CompositeLit)(nil),
	}
	inspect.Preorder(nodeFilter, func(n ast.Node) {
		cl := n.(*ast.CompositeLit)

		typ := pass.TypesInfo.Types[cl].Type
		if typ == nil {
			// cannot determine composite literals' type, skip it
			return
		}
		typeName := typ.String()
		if whitelist && unkeyedLiteral[typeName] {
			// skip whitelisted types
			return
		}
		var structuralTypes []types.Type
		switch typ := typ.(type) {
		case *typeparams.TypeParam:
			terms, err := typeparams.StructuralTerms(typ)
			if err != nil {
				return // invalid type
			}
			for _, term := range terms {
				structuralTypes = append(structuralTypes, term.Type())
			}
		default:
			structuralTypes = append(structuralTypes, typ)
		}
		for _, typ := range structuralTypes {
			under := deref(typ.Underlying())
			strct, ok := under.(*types.Struct)
			if !ok {
				// skip non-struct composite literals
				continue
			}
			if isLocalType(pass, typ) {
				// allow unkeyed locally defined composite literal
				continue
			}

			// check if the struct contains an unkeyed field
			allKeyValue := true
			var suggestedFixAvailable = len(cl.Elts) == strct.NumFields()
			var missingKeys []analysis.TextEdit
			for i, e := range cl.Elts {
				if _, ok := e.(*ast.KeyValueExpr); !ok {
					allKeyValue = false
					if i >= strct.NumFields() {
						break
					}
					field := strct.Field(i)
					if !field.Exported() {
						// Adding unexported field names for structs not defined
						// locally will not work.
						suggestedFixAvailable = false
						break
					}
					missingKeys = append(missingKeys, analysis.TextEdit{
						Pos:     e.Pos(),
						End:     e.Pos(),
						NewText: []byte(fmt.Sprintf("%s: ", field.Name())),
					})
				}
			}
			if allKeyValue {
				// all the struct fields are keyed
				continue
			}

			diag := analysis.Diagnostic{
				Pos:     cl.Pos(),
				End:     cl.End(),
				Message: fmt.Sprintf("%s struct literal uses unkeyed fields", typeName),
			}
			if suggestedFixAvailable {
				diag.SuggestedFixes = []analysis.SuggestedFix{{
					Message:   "Add field names to struct literal",
					TextEdits: missingKeys,
				}}
			}
			pass.Report(diag)
			return
		}
	})
	return nil, nil
}

func deref(typ types.Type) types.Type {
	for {
		ptr, ok := typ.(*types.Pointer)
		if !ok {
			break
		}
		typ = ptr.Elem().Underlying()
	}
	return typ
}

func isLocalType(pass *analysis.Pass, typ types.Type) bool {
	switch x := typ.(type) {
	case *types.Struct:
		// struct literals are local types
		return true
	case *types.Pointer:
		return isLocalType(pass, x.Elem())
	case *types.Named:
		// names in package foo are local to foo_test too
		return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test")
	case *typeparams.TypeParam:
		return strings.TrimSuffix(x.Obj().Pkg().Path(), "_test") == strings.TrimSuffix(pass.Pkg.Path(), "_test")
	}
	return false
}
