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

package ssa

import (
	"go/types"
	"sync"

	"golang.org/x/tools/internal/aliases"
	"golang.org/x/tools/internal/typeparams"
)

// tpWalker walks over types looking for parameterized types.
//
// NOTE: Adapted from go/types/infer.go. If that is exported in a future release remove this copy.
type tpWalker struct {
	mu   sync.Mutex
	seen map[types.Type]bool
}

// isParameterized reports whether t recursively contains a type parameter.
// Thread-safe.
func (w *tpWalker) isParameterized(t types.Type) bool {
	// TODO(adonovan): profile. If this operation is expensive,
	// handle the most common but shallow cases such as T, pkg.T,
	// *T without consulting the cache under the lock.

	w.mu.Lock()
	defer w.mu.Unlock()
	return w.isParameterizedLocked(t)
}

// Requires w.mu.
func (w *tpWalker) isParameterizedLocked(typ types.Type) (res bool) {
	// NOTE: Adapted from go/types/infer.go. Try to keep in sync.

	// detect cycles
	if x, ok := w.seen[typ]; ok {
		return x
	}
	w.seen[typ] = false
	defer func() {
		w.seen[typ] = res
	}()

	switch t := typ.(type) {
	case nil, *types.Basic: // TODO(gri) should nil be handled here?
		break

	case *aliases.Alias:
		return w.isParameterizedLocked(aliases.Unalias(t))

	case *types.Array:
		return w.isParameterizedLocked(t.Elem())

	case *types.Slice:
		return w.isParameterizedLocked(t.Elem())

	case *types.Struct:
		for i, n := 0, t.NumFields(); i < n; i++ {
			if w.isParameterizedLocked(t.Field(i).Type()) {
				return true
			}
		}

	case *types.Pointer:
		return w.isParameterizedLocked(t.Elem())

	case *types.Tuple:
		n := t.Len()
		for i := 0; i < n; i++ {
			if w.isParameterizedLocked(t.At(i).Type()) {
				return true
			}
		}

	case *types.Signature:
		// t.tparams may not be nil if we are looking at a signature
		// of a generic function type (or an interface method) that is
		// part of the type we're testing. We don't care about these type
		// parameters.
		// Similarly, the receiver of a method may declare (rather than
		// use) type parameters, we don't care about those either.
		// Thus, we only need to look at the input and result parameters.
		return w.isParameterizedLocked(t.Params()) || w.isParameterizedLocked(t.Results())

	case *types.Interface:
		for i, n := 0, t.NumMethods(); i < n; i++ {
			if w.isParameterizedLocked(t.Method(i).Type()) {
				return true
			}
		}
		terms, err := typeparams.InterfaceTermSet(t)
		if err != nil {
			panic(err)
		}
		for _, term := range terms {
			if w.isParameterizedLocked(term.Type()) {
				return true
			}
		}

	case *types.Map:
		return w.isParameterizedLocked(t.Key()) || w.isParameterizedLocked(t.Elem())

	case *types.Chan:
		return w.isParameterizedLocked(t.Elem())

	case *types.Named:
		args := t.TypeArgs()
		// TODO(taking): this does not match go/types/infer.go. Check with rfindley.
		if params := t.TypeParams(); params.Len() > args.Len() {
			return true
		}
		for i, n := 0, args.Len(); i < n; i++ {
			if w.isParameterizedLocked(args.At(i)) {
				return true
			}
		}
		return w.isParameterizedLocked(t.Underlying()) // recurse for types local to parameterized functions

	case *types.TypeParam:
		return true

	default:
		panic(t) // unreachable
	}

	return false
}

// anyParameterized reports whether any element of ts is parameterized.
// Thread-safe.
func (w *tpWalker) anyParameterized(ts []types.Type) bool {
	w.mu.Lock()
	defer w.mu.Unlock()
	for _, t := range ts {
		if w.isParameterizedLocked(t) {
			return true
		}
	}
	return false
}
