1package typep
2
3import (
4	"go/ast"
5	"go/types"
6)
7
8// IsTypeExpr reports whether x represents a type expression.
9//
10// Type expression does not evaluate to any run time value,
11// but rather describes a type that is used inside Go expression.
12//
13// For example, (*T)(v) is a CallExpr that "calls" (*T).
14// (*T) is a type expression that tells Go compiler type v should be converted to.
15func IsTypeExpr(info *types.Info, x ast.Expr) bool {
16	switch x := x.(type) {
17	case *ast.StarExpr:
18		return IsTypeExpr(info, x.X)
19	case *ast.ParenExpr:
20		return IsTypeExpr(info, x.X)
21	case *ast.SelectorExpr:
22		return IsTypeExpr(info, x.Sel)
23
24	case *ast.Ident:
25		// Identifier may be a type expression if object
26		// it reffers to is a type name.
27		_, ok := info.ObjectOf(x).(*types.TypeName)
28		return ok
29
30	case *ast.FuncType, *ast.StructType, *ast.InterfaceType, *ast.ArrayType, *ast.MapType, *ast.ChanType:
31		return true
32
33	default:
34		return false
35	}
36}
37