// Copyright 2022 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.

//go:build go1.18

package main

import (
	"fmt"
	"go/ast"
	"go/importer"
	"go/parser"
	"go/token"
	"go/types"
	"log"
)

const methods = `
//!+input
package methods

type List[E any] []E

func (l List[_]) Len() int {
	return len(l)
}

func (l *List[E]) Append(v E) {
	*l = append(*l, v)
}

type Pair[L, R comparable] struct {
	left  L
	right R
}

func (p Pair[L, _]) Left() L {
	return p.left
}

func (p Pair[_, R]) Right() R {
	return p.right
}

func (p Pair[L, R]) Equal(other Pair[L, R]) bool {
	return p.Left() == other.Left() && p.Right() == other.Right()
}
//!-input
`

// !+describe
func Describe(fset *token.FileSet, file *ast.File) error {
	conf := types.Config{Importer: importer.Default()}
	info := &types.Info{
		Defs: make(map[*ast.Ident]types.Object),
	}
	pkg, err := conf.Check("pair", fset, []*ast.File{file}, info)
	if err != nil {
		return err
	}
	for _, name := range pkg.Scope().Names() {
		obj := pkg.Scope().Lookup(name)
		typ := obj.Type().(*types.Named)

		fmt.Printf("type %s has %d methods\n", name, typ.NumMethods())
		for i := 0; i < typ.NumMethods(); i++ {
			m := typ.Method(i)
			sig := m.Type().(*types.Signature)
			recv := sig.Recv().Type()
			fmt.Printf("  %s has %d receiver type parameters\n", m.Name(), sig.RecvTypeParams().Len())
			fmt.Printf("  ...and receiver type %+v\n", recv)
		}
	}
	// }

	// func foo() {}
	for _, decl := range file.Decls {
		fdecl, ok := decl.(*ast.FuncDecl)
		if !ok {
			continue
		}
		fmt.Printf("Declaration of %q has receiver node type %T\n", fdecl.Name, fdecl.Recv.List[0].Type)
		declObj := info.Defs[fdecl.Name]
		recvIdent := receiverTypeName(fdecl.Recv.List[0].Type)
		typ := pkg.Scope().Lookup(recvIdent.Name).Type().(*types.Named)
		// ptr := types.NewPointer(typ)
		name := fdecl.Name.Name
		methodObj, _, _ := types.LookupFieldOrMethod(typ, false, pkg, name)
		if declObj == methodObj {
			fmt.Printf("  info.Uses[%s] == types.LookupFieldOrMethod(%s, ..., %q)\n", fdecl.Name, typ, name)
		}
	}
	return nil
}

func receiverTypeName(e ast.Expr) *ast.Ident {
	if s, ok := e.(*ast.StarExpr); ok {
		e = s.X
	}
	switch e := e.(type) {
	case *ast.IndexExpr:
		return e.X.(*ast.Ident)
	case *ast.IndexListExpr:
		return e.X.(*ast.Ident)
	}
	panic("unexpected receiver node type")
}

//!-describe

/*
//!+output
> go run golang.org/x/tools/internal/typeparams/example/methoddecls
Pair has 2 methods
  Left has 2 receiver type parameters
  ...and receiver type pair.Pair[L, _]
  Right has 2 receiver type parameters
  ...and receiver type pair.Pair[_, R]
Declaration of "Left" has receiver node type *ast.IndexListExpr
  info.Uses[Left] == types.LookupFieldOrMethod(pair.Pair[L, R any], ..., "Left")
Declaration of "Right" has receiver node type *ast.IndexListExpr
  info.Uses[Right] == types.LookupFieldOrMethod(pair.Pair[L, R any], ..., "Right")
//!-output
*/

func main() {
	// Parse one file.
	fset := token.NewFileSet()
	f, err := parser.ParseFile(fset, "methods.go", methods, 0)
	if err != nil {
		log.Fatal(err)
	}
	if err := Describe(fset, f); err != nil {
		log.Fatal(err)
	}
}
