github.com/goplus/xtypes@v0.2.1/types_test.go (about)

     1  package xtypes_test
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"go/importer"
     7  	"go/parser"
     8  	"go/token"
     9  	"go/types"
    10  	"image/color"
    11  	"reflect"
    12  	"strings"
    13  	"testing"
    14  
    15  	"github.com/goplus/xtypes"
    16  )
    17  
    18  const filename = "<src>"
    19  
    20  func makePkg(src string) (*types.Package, error) {
    21  	fset := token.NewFileSet()
    22  	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
    23  	if err != nil {
    24  		return nil, err
    25  	}
    26  	// use the package name as package path
    27  	conf := types.Config{Importer: importer.Default()}
    28  	return conf.Check(file.Name.Name, fset, []*ast.File{file}, nil)
    29  }
    30  
    31  type testEntry struct {
    32  	src, str string
    33  }
    34  
    35  // dup returns a testEntry where both src and str are the same.
    36  func dup(s string) testEntry {
    37  	return testEntry{s, s}
    38  }
    39  
    40  func two(src, str string) testEntry {
    41  	return testEntry{src, str}
    42  }
    43  
    44  var basicTypes = []testEntry{
    45  	// basic
    46  	dup(`bool`),
    47  	dup(`int`),
    48  	dup(`int8`),
    49  	dup(`int16`),
    50  	dup(`int32`),
    51  	dup(`int64`),
    52  	dup(`uint`),
    53  	dup(`uint8`),
    54  	dup(`uint16`),
    55  	dup(`uint32`),
    56  	dup(`uint64`),
    57  	dup(`uintptr`),
    58  	dup(`float32`),
    59  	dup(`float64`),
    60  	dup(`complex64`),
    61  	dup(`complex128`),
    62  	dup(`string`),
    63  	dup(`unsafe.Pointer`),
    64  }
    65  
    66  var typesTest = []testEntry{
    67  	dup(`*int`),
    68  	dup(`*string`),
    69  	dup(`[]int`),
    70  	dup(`[]string`),
    71  	dup(`[2]int`),
    72  	dup(`[2]string`),
    73  	dup(`map[int]string`),
    74  	dup(`chan int`),
    75  	dup(`chan string`),
    76  	dup(`struct { x int; y string }`),
    77  	two(`interface{}`, `interface {}`),
    78  	two(`func(x int, y string)`, `func(int, string)`),
    79  	two(`func(fmt string, a ...interface{})`, `func(string, ...interface {})`),
    80  	two(`interface {
    81  		Add(a, b int) int
    82  		Info() string
    83  	}`, `interface { Add(int, int) int; Info() string }`),
    84  	two(`interface {
    85  		Stringer
    86  		Add(a, b int) int
    87  	}`, `interface { Add(int, int) int; String() string }`),
    88  	two(`error`, `interface { Error() string }`),
    89  	two(`func(path *byte, argv **byte, envp **byte) error`, `func(*uint8, **uint8, **uint8) error`),
    90  	two(`[4]struct{ item int; _ [40]byte }`, `[4]struct { item int; _ [40]uint8 }`),
    91  }
    92  
    93  func TestTypes(t *testing.T) {
    94  	var tests []testEntry
    95  	tests = append(tests, basicTypes...)
    96  	tests = append(tests, typesTest...)
    97  
    98  	for _, test := range tests {
    99  		src := `package p; import "unsafe"; import "fmt"; type _ unsafe.Pointer; type Stringer fmt.Stringer; type T ` + test.src
   100  		pkg, err := makePkg(src)
   101  		if err != nil {
   102  			t.Errorf("%s: %s", src, err)
   103  			continue
   104  		}
   105  		typ := pkg.Scope().Lookup("T").Type().Underlying()
   106  		rt, err := xtypes.ToType(typ, xtypes.NewContext(nil, nil, nil))
   107  		if err != nil {
   108  			t.Errorf("%s: ToType error %v", test.src, err)
   109  		}
   110  		if got := rt.String(); got != test.str {
   111  			t.Errorf("%s: got %s, want %s", test.src, got, test.str)
   112  		}
   113  	}
   114  }
   115  
   116  var namedTest = []testEntry{
   117  	two(`package main
   118  	type T int`, `0`),
   119  	two(`package main
   120  	type T byte`, `0x0`),
   121  	two(`package main
   122  	type T func(a **byte, b *int, c string)`, `(main.T)(nil)`),
   123  	two(`package main
   124  	type T struct {
   125  		X int
   126  		Y int
   127  	}
   128  	`, `main.T{X:0, Y:0}`),
   129  	two(`package main
   130  	type T struct {
   131  		_ int
   132  		_ int
   133  		x int
   134  		y int
   135  	}
   136  	`, `main.T{_:0, _:0, x:0, y:0}`),
   137  	two(`package main
   138  	type Point struct {
   139  		X int
   140  		Y int
   141  	}
   142  	type T struct {
   143  		pt Point
   144  	}
   145  	`, `main.T{pt:main.Point{X:0, Y:0}}`),
   146  	two(`package main
   147  	type T struct {
   148  		P map[string]T
   149  	}
   150  	`, `main.T{P:map[string]main.T(nil)}`),
   151  	two(`package main
   152  	type N struct {
   153  		*T
   154  	}
   155  	type T struct {
   156  		*N
   157  	}
   158  	`, `main.T{N:(*main.N)(nil)}`),
   159  	two(`package main
   160  	type T struct {
   161  		*T
   162  	}`, `main.T{T:(*main.T)(nil)}`),
   163  	two(`package main
   164  	type T *T`, `(main.T)(nil)`),
   165  	two(`package main
   166  	type T [2]*T`, `main.T{(*main.T)(nil), (*main.T)(nil)}`),
   167  	two(`package main
   168  	import "errors"
   169  	var T = errors.New("err")
   170  	`, `<nil>`),
   171  	two(`package main
   172  	import "io"
   173  	var T io.Writer
   174  	`, `<nil>`),
   175  }
   176  
   177  func TestNamed(t *testing.T) {
   178  	var tests []testEntry
   179  	tests = append(tests, namedTest...)
   180  
   181  	for _, test := range tests {
   182  		pkg, err := makePkg(test.src)
   183  		if err != nil {
   184  			t.Errorf("%s: %s", test.src, err)
   185  			continue
   186  		}
   187  		ctx := xtypes.NewContext(nil, nil, nil)
   188  		typ := pkg.Scope().Lookup("T").Type()
   189  		rt, err := xtypes.ToType(typ, ctx)
   190  		if err != nil {
   191  			t.Errorf("%s: ToType error %v", test.src, err)
   192  		}
   193  		if got := fmt.Sprintf("%+#v", reflect.New(rt).Elem().Interface()); got != test.str {
   194  			t.Errorf("%s: got %s, want %s", test.src, got, test.str)
   195  		}
   196  	}
   197  }
   198  
   199  var methodTest = []testEntry{
   200  	two(`//001
   201  	package main
   202  	import "fmt"
   203  	type T struct {
   204  		X int
   205  		Y int
   206  	}
   207  	func (t T) String() string {
   208  		return fmt.Sprintf("(%v,%v)",t.X,t.Y)
   209  	}
   210  	func (t *T) Set(x int, y int) {
   211  		t.X, t.Y = x, y
   212  	}
   213  	`, `String func(main.T) string
   214  Set func(*main.T, int, int)`),
   215  	two(`//002
   216  	package main
   217  	import "fmt"
   218  	type N struct {
   219  		size int
   220  	}
   221  	func (b N) Size() int {
   222  		return b.size
   223  	}
   224  	func (b *N) SetSize(n int) {
   225  		b.size = n
   226  	}
   227  	type T struct {
   228  		N
   229  		X int
   230  		Y int
   231  	}
   232  	func (t T) String() string {
   233  		return fmt.Sprintf("(%v,%v)",t.X,t.Y)
   234  	}
   235  	func (t *T) Set(x int, y int) {
   236  		t.X, t.Y = x, y
   237  	}
   238  	`, `Size func(main.T) int
   239  String func(main.T) string
   240  Set func(*main.T, int, int)
   241  SetSize func(*main.T, int)`),
   242  	two(`//003
   243  	package main
   244  	import "fmt"
   245  	type N interface {
   246  		Size() int
   247  		SetSize(int)
   248  	}
   249  	type T struct {
   250  		N
   251  		X int
   252  		Y int
   253  	}
   254  	func (t T) String() string {
   255  		return fmt.Sprintf("(%v,%v)",t.X,t.Y)
   256  	}
   257  	func (t *T) Set(x int, y int) {
   258  		t.X, t.Y = x, y
   259  	}
   260  	`, `SetSize func(main.T, int)
   261  Size func(main.T) int
   262  String func(main.T) string
   263  Set func(*main.T, int, int)`),
   264  	two(`//004
   265  	package main
   266  	import "fmt"
   267  	type N struct {
   268  		size int
   269  	}
   270  	func (b N) Size() int {
   271  		return b.size
   272  	}
   273  	func (b *N) SetSize(n int) {
   274  		b.size = n
   275  	}
   276  	type T struct {
   277  		*N
   278  		X int
   279  		Y int
   280  	}
   281  	func (t T) String() string {
   282  		return fmt.Sprintf("(%v,%v)",t.X,t.Y)
   283  	}
   284  	func (t *T) Set(x int, y int) {
   285  		t.X, t.Y = x, y
   286  	}
   287  	func (t T) This() T {
   288  		return t
   289  	}
   290  	`, `SetSize func(main.T, int)
   291  Size func(main.T) int
   292  String func(main.T) string
   293  This func(main.T) main.T
   294  Set func(*main.T, int, int)`),
   295  }
   296  
   297  func TestMethod(t *testing.T) {
   298  	var tests []testEntry
   299  	tests = append(tests, methodTest...)
   300  
   301  	for _, test := range tests {
   302  		pkg, err := makePkg(test.src)
   303  		if err != nil {
   304  			t.Errorf("%s: %s", test.src, err)
   305  			continue
   306  		}
   307  		ctx := xtypes.NewContext(nil, nil, nil)
   308  		typ := pkg.Scope().Lookup("T").Type()
   309  		rt, err := xtypes.ToType(typ, ctx)
   310  		if err != nil {
   311  			t.Errorf("%s: ToType error %v", test.src, err)
   312  		}
   313  		var infos []string
   314  		skip := make(map[string]bool)
   315  		for i := 0; i < rt.NumMethod(); i++ {
   316  			fn := rt.Method(i)
   317  			infos = append(infos, fmt.Sprintf("%v %v", fn.Name, fn.Type.String()))
   318  			skip[fn.Name] = true
   319  		}
   320  		prt := reflect.PtrTo(rt)
   321  		for i := 0; i < prt.NumMethod(); i++ {
   322  			fn := prt.Method(i)
   323  			if skip[fn.Name] {
   324  				continue
   325  			}
   326  			infos = append(infos, fmt.Sprintf("%v %v", fn.Name, fn.Type.String()))
   327  		}
   328  		if got := strings.Join(infos, "\n"); got != test.str {
   329  			t.Errorf("%s: methods\ngot\n%v\nwant\n%v", test.src, got, test.str)
   330  		}
   331  		if m, ok := rt.MethodByName("This"); ok {
   332  			if m.Type.Out(0) != rt {
   333  				t.Errorf("%s: methods type failed", test.src)
   334  			}
   335  		}
   336  	}
   337  }
   338  
   339  var invokeTest = `
   340  package main
   341  
   342  import "fmt"
   343  
   344  type T struct {
   345  	X int
   346  	Y int
   347  }
   348  
   349  func (t *T) Set(x int, y int) {
   350  	t.X, t.Y = x, y
   351  }
   352  
   353  func (t T) Add(o T) T {
   354  	return T{t.X+o.X, t.Y+o.Y}
   355  }
   356  
   357  func (t T) String() string {
   358  	return fmt.Sprintf("(%v,%v)", t.X,t.Y)
   359  }
   360  `
   361  
   362  func TestInvoke(t *testing.T) {
   363  	pkg, err := makePkg(invokeTest)
   364  	if err != nil {
   365  		t.Errorf("invoke: makePkg error %s", err)
   366  	}
   367  	typ := pkg.Scope().Lookup("T").Type()
   368  	ctx := xtypes.NewContext(func(mtyp reflect.Type, method *types.Func) func(args []reflect.Value) []reflect.Value {
   369  		switch method.Name() {
   370  		case "Set":
   371  			return func(args []reflect.Value) []reflect.Value {
   372  				v := args[0].Elem()
   373  				v.Field(0).Set(args[1])
   374  				v.Field(1).Set(args[2])
   375  				return nil
   376  			}
   377  		case "String":
   378  			return func(args []reflect.Value) []reflect.Value {
   379  				v := args[0]
   380  				r := fmt.Sprintf("(%v,%v)", v.Field(0).Int(), v.Field(1).Int())
   381  				return []reflect.Value{reflect.ValueOf(r)}
   382  			}
   383  		case "Add":
   384  			return func(args []reflect.Value) []reflect.Value {
   385  				v := args[0]
   386  				o := args[1]
   387  				r := reflect.New(v.Type()).Elem()
   388  				r.Field(0).SetInt(v.Field(0).Int() + o.Field(0).Int())
   389  				r.Field(1).SetInt(v.Field(1).Int() + o.Field(1).Int())
   390  				return []reflect.Value{r}
   391  			}
   392  		}
   393  		return nil
   394  	}, nil, nil)
   395  	rt, err := xtypes.ToType(typ, ctx)
   396  	if err != nil {
   397  		t.Errorf("invoke: ToType error %v", err)
   398  	}
   399  	v := reflect.New(rt)
   400  	v.MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(100), reflect.ValueOf(200)})
   401  	if r := v.MethodByName("String").Call(nil); len(r) != 1 || fmt.Sprint(r[0].Interface()) != "(100,200)" {
   402  		t.Errorf("error call String: %v", r)
   403  	}
   404  	o := reflect.New(rt)
   405  	o.MethodByName("Set").Call([]reflect.Value{reflect.ValueOf(10), reflect.ValueOf(20)})
   406  	if r := v.MethodByName("Add").Call([]reflect.Value{o.Elem()}); len(r) != 1 || fmt.Sprint(r[0].Interface()) != "(110,220)" {
   407  		t.Errorf("error call Add: %v", r)
   408  	}
   409  }
   410  
   411  func TestPtrElem(t *testing.T) {
   412  	pkg, err := makePkg("package main; type T *T")
   413  	if err != nil {
   414  		t.Errorf("elem: makePkg error %s", err)
   415  	}
   416  	typ := pkg.Scope().Lookup("T").Type()
   417  	rt, err := xtypes.ToType(typ, xtypes.NewContext(nil, nil, nil))
   418  	if err != nil {
   419  		t.Errorf("elem: ToType error %v", err)
   420  	}
   421  	ptr := reflect.PtrTo(rt)
   422  	if !ptr.AssignableTo(rt) || !rt.AssignableTo(ptr) {
   423  		t.Errorf("elem: AssignableTo error %v", rt)
   424  	}
   425  }
   426  
   427  func TestArrayElem(t *testing.T) {
   428  	pkg, err := makePkg("package main; type T []T")
   429  	if err != nil {
   430  		t.Errorf("elem: makePkg error %s", err)
   431  	}
   432  	typ := pkg.Scope().Lookup("T").Type()
   433  	rt, err := xtypes.ToType(typ, xtypes.NewContext(nil, nil, nil))
   434  	if err != nil {
   435  		t.Errorf("elem: ToType error %v", err)
   436  	}
   437  	ptr := rt.Elem()
   438  	if !ptr.AssignableTo(rt) || !rt.AssignableTo(ptr) {
   439  		t.Errorf("elem: AssignableTo error %v", rt)
   440  	}
   441  }
   442  
   443  func TestFunc(t *testing.T) {
   444  	pkg, err := makePkg("package main; type T func(string) T")
   445  	if err != nil {
   446  		t.Errorf("func: makePkg error %s", err)
   447  	}
   448  	typ := pkg.Scope().Lookup("T").Type()
   449  	rt, err := xtypes.ToType(typ, xtypes.NewContext(nil, nil, nil))
   450  	if err != nil {
   451  		t.Errorf("func: ToType error %v", err)
   452  	}
   453  	out := rt.Out(0)
   454  	if out != rt {
   455  		t.Errorf("func: out error %v", out.Kind())
   456  	}
   457  }
   458  
   459  func TestInterface(t *testing.T) {
   460  	pkg, err := makePkg(`package main
   461  	type T interface {
   462  		a(s string) T
   463  		b(s string) string
   464  	}`)
   465  	if err != nil {
   466  		t.Errorf("func: makePkg error %s", err)
   467  	}
   468  	typ := pkg.Scope().Lookup("T").Type()
   469  	rt, err := xtypes.ToType(typ, xtypes.NewContext(nil, nil, nil))
   470  	if err != nil {
   471  		t.Errorf("func: ToType error %v", err)
   472  	}
   473  	out := rt.Method(0).Type.Out(0)
   474  	if out != rt {
   475  		t.Errorf("func: out error %v", out.Kind())
   476  	}
   477  }
   478  
   479  var structTest = `
   480  package main
   481  
   482  import "fmt"
   483  
   484  type T struct {
   485  	X int
   486  	Y int
   487  }
   488  
   489  func (t *T) Set(x int, y int) {
   490  	t.X, t.Y = x, y
   491  }
   492  
   493  func (t T) Add(o T) T {
   494  	return T{t.X+o.X, t.Y+o.Y}
   495  }
   496  
   497  func (t T) String() string {
   498  	return fmt.Sprintf("(%v,%v)", t.X,t.Y)
   499  }
   500  
   501  type Stringer interface {
   502  	String() string
   503  }
   504  
   505  var t1 struct{ T }
   506  var t2 struct{ *T }
   507  var t3 struct{ Stringer }
   508  `
   509  
   510  func TestEmbbed(t *testing.T) {
   511  	pkg, err := makePkg(structTest)
   512  	if err != nil {
   513  		t.Errorf("embbed: makePkg error %s", err)
   514  	}
   515  	typ := pkg.Scope().Lookup("t1").Type()
   516  	ctx := xtypes.NewContext(nil, nil, nil)
   517  	rt, err := xtypes.ToType(typ, ctx)
   518  	if err != nil {
   519  		t.Errorf("embbed: ToType error %v", err)
   520  	}
   521  	if n := rt.NumMethod(); n != 2 {
   522  		t.Errorf("embbed: num method %v", n)
   523  	}
   524  	typ = pkg.Scope().Lookup("t2").Type()
   525  	rt, err = xtypes.ToType(typ, ctx)
   526  	if err != nil {
   527  		t.Errorf("embbed: ToType error %v", err)
   528  	}
   529  	if n := rt.NumMethod(); n != 3 {
   530  		t.Errorf("embbed: num method %v", n)
   531  	}
   532  	typ = pkg.Scope().Lookup("t3").Type()
   533  	rt, err = xtypes.ToType(typ, ctx)
   534  	if err != nil {
   535  		t.Errorf("embbed: ToType error %v", err)
   536  	}
   537  	if n := rt.NumMethod(); n != 1 {
   538  		t.Errorf("embbed: num method %v", n)
   539  	}
   540  }
   541  
   542  var dddTest = `
   543  package main
   544  
   545  type T []T
   546  
   547  func ln(args ...T) int { return len(args) }
   548  
   549  func (*T) Sum(args ...int) int { return 1 }
   550  
   551  type U struct {
   552  	*T
   553  }
   554  
   555  func (u *U) Test() {
   556  }
   557  `
   558  
   559  func TestDDD(t *testing.T) {
   560  	pkg, err := makePkg(dddTest)
   561  	if err != nil {
   562  		t.Errorf("ddd: makePkg error %s", err)
   563  	}
   564  	typ := pkg.Scope().Lookup("U").Type()
   565  	ctx := xtypes.NewContext(nil, nil, nil)
   566  	rt, err := xtypes.ToType(typ, ctx)
   567  	if err != nil {
   568  		t.Errorf("ddd: ToType error %v", err)
   569  	}
   570  	if n := rt.NumMethod(); n != 1 {
   571  		t.Errorf("ddd: num method %v", n)
   572  	}
   573  	if n := reflect.PtrTo(rt).NumMethod(); n != 2 {
   574  		t.Errorf("ddd: num method %v", n)
   575  	}
   576  }
   577  
   578  var multipleTest = `
   579  package main
   580  
   581  type T struct {
   582  	X int
   583  	Y int
   584  }
   585  
   586  func init() {
   587  	type T struct {
   588  		s string
   589  	}
   590  	b := &T{"hello"}
   591  	println(b)
   592  }
   593  
   594  func init() {
   595  	type T *T
   596  	var c T
   597  	println(c)
   598  }
   599  
   600  func main() {
   601  	a := &T{100,200}
   602  	println(a)
   603  }
   604  
   605  `
   606  
   607  func lookupObject(scope *types.Scope, name string) (types.Object, bool) {
   608  	if obj := scope.Lookup(name); obj != nil {
   609  		return obj, true
   610  	}
   611  	for i := 0; i < scope.NumChildren(); i++ {
   612  		if obj, ok := lookupObject(scope.Child(i), name); ok {
   613  			return obj, true
   614  		}
   615  	}
   616  	return nil, false
   617  }
   618  
   619  func TestMultiple(t *testing.T) {
   620  	pkg, err := makePkg(multipleTest)
   621  	if err != nil {
   622  		t.Errorf("makePkg error %s", err)
   623  	}
   624  	a, ok := lookupObject(pkg.Scope(), "a")
   625  	if !ok {
   626  		t.Error("not found object a")
   627  	}
   628  	b, ok := lookupObject(pkg.Scope(), "b")
   629  	if !ok {
   630  		t.Error("not found object b")
   631  	}
   632  	c, ok := lookupObject(pkg.Scope(), "c")
   633  	if !ok {
   634  		t.Error("not found object b")
   635  	}
   636  	ctx := xtypes.NewContext(nil, nil, nil)
   637  	ta, err := xtypes.ToType(a.Type(), ctx)
   638  	if err != nil {
   639  		t.Errorf("ToType error %v", err)
   640  	}
   641  	tb, err := xtypes.ToType(b.Type(), ctx)
   642  	if err != nil {
   643  		t.Errorf("ToType error %v", err)
   644  	}
   645  	tc, err := xtypes.ToType(c.Type(), ctx)
   646  	if ta.Elem() == tb.Elem() || ta.Elem() == tc.Elem() || tb.Elem() == tc.Elem() {
   647  		t.Error("must diffrent type")
   648  	}
   649  	if s := fmt.Sprintf("%#v", reflect.New(ta.Elem()).Interface()); s != "&main.T{X:0, Y:0}" {
   650  		t.Error("bad type", s)
   651  	}
   652  	if s := fmt.Sprintf("%#v", reflect.New(tb.Elem()).Interface()); s != `&main.T{s:""}` {
   653  		t.Error("bad type", s)
   654  	}
   655  	if s := fmt.Sprintf("%#v", reflect.New(tc.Elem()).Elem().Interface()); s != `(main.T)(nil)` {
   656  		t.Error("bad type", s)
   657  	}
   658  }
   659  
   660  var basicInterfaceTest = `
   661  package main
   662  
   663  var i interface{}
   664  var e error
   665  var b []byte
   666  `
   667  
   668  func TestBasicInterface(t *testing.T) {
   669  	pkg, err := makePkg(basicInterfaceTest)
   670  	if err != nil {
   671  		t.Errorf("makePkg error %s", err)
   672  	}
   673  	i := pkg.Scope().Lookup("i")
   674  	e := pkg.Scope().Lookup("e")
   675  	b := pkg.Scope().Lookup("b")
   676  	ctx := xtypes.NewContext(nil, nil, nil)
   677  	typ, err := xtypes.ToType(i.Type(), ctx)
   678  	if err != nil {
   679  		t.Errorf("ToType error %v", err)
   680  	}
   681  	if typ != reflect.TypeOf((*interface{})(nil)).Elem() {
   682  		t.Errorf("to interface{} error %v", err)
   683  	}
   684  	typ, err = xtypes.ToType(e.Type(), ctx)
   685  	if err != nil {
   686  		t.Errorf("ToType error %v", err)
   687  	}
   688  	if typ != reflect.TypeOf((*error)(nil)).Elem() {
   689  		t.Errorf("to error interface error %v", err)
   690  	}
   691  	typ, err = xtypes.ToType(b.Type(), ctx)
   692  	if err != nil {
   693  		t.Errorf("ToType error %v", err)
   694  	}
   695  	if typ != reflect.TypeOf((*[]byte)(nil)).Elem() {
   696  		t.Errorf("to []byte error %v", err)
   697  	}
   698  }
   699  
   700  var extTest = `
   701  package main
   702  
   703  import "image/color"
   704  
   705  var r = &color.RGBA{255,0,0,255}
   706  `
   707  
   708  func TestExtType(t *testing.T) {
   709  	pkg, err := makePkg(extTest)
   710  	if err != nil {
   711  		t.Errorf("makePkg error %s", err)
   712  	}
   713  	r := pkg.Scope().Lookup("r")
   714  	ctx := xtypes.NewContext(nil, func(name *types.TypeName) (reflect.Type, bool) {
   715  		if name.Type().String() == "image/color.RGBA" {
   716  			return reflect.TypeOf((*color.RGBA)(nil)).Elem(), true
   717  		}
   718  		return nil, false
   719  	}, nil)
   720  	typ, err := xtypes.ToType(r.Type(), ctx)
   721  	if err != nil {
   722  		t.Errorf("ToType error %v", err)
   723  	}
   724  	if typ != reflect.TypeOf((*color.RGBA)(nil)) {
   725  		t.Error("to ext type color.RGBA failed")
   726  	}
   727  }
   728  
   729  var jsonTest = `
   730  package main
   731  
   732  import "encoding/json"
   733  
   734  var err json.MarshalerError
   735  `
   736  
   737  func TestJson(t *testing.T) {
   738  	pkg, err := makePkg(jsonTest)
   739  	if err != nil {
   740  		t.Errorf("makePkg error %s", err)
   741  	}
   742  	r := pkg.Scope().Lookup("err")
   743  	ctx := xtypes.NewContext(nil, nil, nil)
   744  	typ, err := xtypes.ToType(r.Type(), ctx)
   745  	if err != nil {
   746  		t.Errorf("ToType error %v", err)
   747  	}
   748  	if n := typ.NumField(); n != 3 {
   749  		t.Errorf("num field error %v", n)
   750  	}
   751  }
   752  
   753  var sliceElemTest = `
   754  package main
   755  
   756  type Scope struct {
   757  	s     string
   758  	child []*Scope
   759  }
   760  var s *Scope
   761  `
   762  
   763  func TestSliceElem(t *testing.T) {
   764  	pkg, err := makePkg(sliceElemTest)
   765  	if err != nil {
   766  		t.Errorf("makePkg error %s", err)
   767  	}
   768  	r := pkg.Scope().Lookup("s")
   769  	ctx := xtypes.NewContext(nil, nil, nil)
   770  	typ, err := xtypes.ToType(r.Type(), ctx)
   771  	if err != nil {
   772  		t.Errorf("ToType error %v", err)
   773  	}
   774  	if elem := typ.Elem().Field(1).Type.Elem(); elem != typ {
   775  		t.Errorf("child ptr error %#v != %#v", elem, typ)
   776  	}
   777  }
   778  
   779  var implementsTest = `
   780  package main
   781  
   782  type Object interface {
   783  	Name() string
   784  	id() int
   785  }
   786  
   787  type Named struct {
   788  	name string
   789  }
   790  
   791  func (m Named) Name() string {
   792  	return m.name
   793  }
   794  
   795  func (m Named) id() int {
   796  	return 0
   797  }
   798  
   799  var v Object
   800  var n Named
   801  
   802  
   803  `
   804  
   805  func TestImplement(t *testing.T) {
   806  	pkg, err := makePkg(implementsTest)
   807  	if err != nil {
   808  		t.Errorf("makePkg error %s", err)
   809  	}
   810  	v := pkg.Scope().Lookup("v")
   811  	ctx := xtypes.NewContext(nil, nil, nil)
   812  	ityp, err := xtypes.ToType(v.Type(), ctx)
   813  	if err != nil {
   814  		t.Errorf("ToType error %v", err)
   815  	}
   816  	if n := ityp.NumMethod(); n != 2 {
   817  		t.Errorf("num method %v", n)
   818  	}
   819  	r := pkg.Scope().Lookup("n")
   820  	typ, err := xtypes.ToType(r.Type(), ctx)
   821  	if err != nil {
   822  		t.Errorf("ToType error %v", err)
   823  	}
   824  	if n := typ.NumMethod(); n != 1 {
   825  		t.Errorf("num method %v", n)
   826  	}
   827  	if n := reflect.PtrTo(typ).NumMethod(); n != 1 {
   828  		t.Errorf("num method %v", n)
   829  	}
   830  	if !typ.Implements(ityp) {
   831  		t.Error("bad typ Implements")
   832  	}
   833  	if !reflect.PtrTo(typ).Implements(ityp) {
   834  		t.Error("bad ptr typ Implements")
   835  	}
   836  	// if !reflectx.Implements(ityp, typ) {
   837  	// 	t.Error("bad typ Implements")
   838  	// }
   839  	// if !reflectx.Implements(ityp, reflect.PtrTo(typ)) {
   840  	// 	t.Error("bad ptr typ Implements")
   841  	// }
   842  }
   843  
   844  var typesObjectTest = `
   845  package main
   846  
   847  import "go/types"
   848  
   849  var v types.Object
   850  var n *types.TypeName
   851  `
   852  
   853  func TestTypesObject(t *testing.T) {
   854  	pkg, err := makePkg(typesObjectTest)
   855  	if err != nil {
   856  		t.Errorf("makePkg error %s", err)
   857  	}
   858  	v := pkg.Scope().Lookup("v")
   859  	ctx := xtypes.NewContext(nil, nil, nil)
   860  	ityp, err := xtypes.ToType(v.Type(), ctx)
   861  	if err != nil {
   862  		t.Errorf("ToType error %v", err)
   863  	}
   864  	if n := ityp.NumMethod(); n != reflect.TypeOf((*types.Object)(nil)).Elem().NumMethod() {
   865  		t.Errorf("num method %v", n)
   866  	}
   867  	r := pkg.Scope().Lookup("n")
   868  	typ, err := xtypes.ToType(r.Type(), ctx)
   869  	if err != nil {
   870  		t.Errorf("ToType error %v", err)
   871  	}
   872  	if !typ.Implements(ityp) {
   873  		t.Error("bad typ Implements")
   874  	}
   875  }