// 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 stringintconv defines an Analyzer that flags type conversions
// from integers to strings.
package stringintconv

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 string(int) conversions

This checker flags conversions of the form string(x) where x is an integer
(but not byte or rune) type. Such conversions are discouraged because they
return the UTF-8 representation of the Unicode code point x, and not a decimal
string representation of x as one might expect. Furthermore, if x denotes an
invalid code point, the conversion cannot be statically rejected.

For conversions that intend on using the code point, consider replacing them
with string(rune(x)). Otherwise, strconv.Itoa and its equivalents return the
string representation of the value in the desired base.
`

var Analyzer = &analysis.Analyzer{
	Name:     "stringintconv",
	Doc:      Doc,
	URL:      "https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stringintconv",
	Requires: []*analysis.Analyzer{inspect.Analyzer},
	Run:      run,
}

// describe returns a string describing the type typ contained within the type
// set of inType. If non-empty, inName is used as the name of inType (this is
// necessary so that we can use alias type names that may not be reachable from
// inType itself).
func describe(typ, inType types.Type, inName string) string {
	name := inName
	if typ != inType {
		name = typeName(typ)
	}
	if name == "" {
		return ""
	}

	var parentheticals []string
	if underName := typeName(typ.Underlying()); underName != "" && underName != name {
		parentheticals = append(parentheticals, underName)
	}

	if typ != inType && inName != "" && inName != name {
		parentheticals = append(parentheticals, "in "+inName)
	}

	if len(parentheticals) > 0 {
		name += " (" + strings.Join(parentheticals, ", ") + ")"
	}

	return name
}

func typeName(typ types.Type) string {
	if v, _ := typ.(interface{ Name() string }); v != nil {
		return v.Name()
	}
	if v, _ := typ.(interface{ Obj() *types.TypeName }); v != nil {
		return v.Obj().Name()
	}
	return ""
}

func run(pass *analysis.Pass) (interface{}, error) {
	inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector)
	nodeFilter := []ast.Node{
		(*ast.CallExpr)(nil),
	}
	inspect.Preorder(nodeFilter, func(n ast.Node) {
		call := n.(*ast.CallExpr)

		if len(call.Args) != 1 {
			return
		}
		arg := call.Args[0]

		// Retrieve target type name.
		var tname *types.TypeName
		switch fun := call.Fun.(type) {
		case *ast.Ident:
			tname, _ = pass.TypesInfo.Uses[fun].(*types.TypeName)
		case *ast.SelectorExpr:
			tname, _ = pass.TypesInfo.Uses[fun.Sel].(*types.TypeName)
		}
		if tname == nil {
			return
		}

		// In the conversion T(v) of a value v of type V to a target type T, we
		// look for types T0 in the type set of T and V0 in the type set of V, such
		// that V0->T0 is a problematic conversion. If T and V are not type
		// parameters, this amounts to just checking if V->T is a problematic
		// conversion.

		// First, find a type T0 in T that has an underlying type of string.
		T := tname.Type()
		ttypes, err := structuralTypes(T)
		if err != nil {
			return // invalid type
		}

		var T0 types.Type // string type in the type set of T

		for _, tt := range ttypes {
			u, _ := tt.Underlying().(*types.Basic)
			if u != nil && u.Kind() == types.String {
				T0 = tt
				break
			}
		}

		if T0 == nil {
			// No target types have an underlying type of string.
			return
		}

		// Next, find a type V0 in V that has an underlying integral type that is
		// not byte or rune.
		V := pass.TypesInfo.TypeOf(arg)
		vtypes, err := structuralTypes(V)
		if err != nil {
			return // invalid type
		}

		var V0 types.Type // integral type in the type set of V

		for _, vt := range vtypes {
			u, _ := vt.Underlying().(*types.Basic)
			if u != nil && u.Info()&types.IsInteger != 0 {
				switch u.Kind() {
				case types.Byte, types.Rune, types.UntypedRune:
					continue
				}
				V0 = vt
				break
			}
		}

		if V0 == nil {
			// No source types are non-byte or rune integer types.
			return
		}

		convertibleToRune := true // if true, we can suggest a fix
		for _, t := range vtypes {
			if !types.ConvertibleTo(t, types.Typ[types.Rune]) {
				convertibleToRune = false
				break
			}
		}

		target := describe(T0, T, tname.Name())
		source := describe(V0, V, typeName(V))

		if target == "" || source == "" {
			return // something went wrong
		}

		diag := analysis.Diagnostic{
			Pos:     n.Pos(),
			Message: fmt.Sprintf("conversion from %s to %s yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)", source, target),
		}

		if convertibleToRune {
			diag.SuggestedFixes = []analysis.SuggestedFix{
				{
					Message: "Did you mean to convert a rune to a string?",
					TextEdits: []analysis.TextEdit{
						{
							Pos:     arg.Pos(),
							End:     arg.Pos(),
							NewText: []byte("rune("),
						},
						{
							Pos:     arg.End(),
							End:     arg.End(),
							NewText: []byte(")"),
						},
					},
				},
			}
		}
		pass.Report(diag)
	})
	return nil, nil
}

func structuralTypes(t types.Type) ([]types.Type, error) {
	var structuralTypes []types.Type
	switch t := t.(type) {
	case *typeparams.TypeParam:
		terms, err := typeparams.StructuralTerms(t)
		if err != nil {
			return nil, err
		}
		for _, term := range terms {
			structuralTypes = append(structuralTypes, term.Type())
		}
	default:
		structuralTypes = append(structuralTypes, t)
	}
	return structuralTypes, nil
}
