-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathassignability_test.go
183 lines (172 loc) · 4.5 KB
/
assignability_test.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package gospec
import (
"go/types"
"testing"
)
// func (s *Spec) Assignment(v, t string) bool
// 1. x's type is identical to T.
// x 的类型 与 T 相同
func TestAssignment01(t *testing.T) {
s := NewSpec(`
type T = int
var x = 1
`)
if s.Identical("x", "T") {
if !s.Assignment("x", "T") {
t.Error(`test rule:
1. x's type is identical to T.
failed`)
}
}
}
// 2. x's type V and T have identical underlying types
// and at least one of V or T is not a defined type.
// x 的类型 V 和 T 有相同的 underlying type 并且 V 或 T 至少有一个是未(显示)定义类型
func TestAssignment02(t *testing.T) {
s := NewSpec(`
type V = func()
type T func()
var x V
`)
V := s.GetType("x")
T := s.GetType("T")
if Identical(V.Underlying(), T.Underlying()) && !IsDefinedType(V) && IsDefinedType(T) {
if !s.Assignment("x", "T") {
t.Error(`test rule:
2. x's type V and T have identical underlying types and at least one of V or T is not a defined type.
failed`)
}
}
}
// 3. T is an interface type and x implements T.
// T 是一个接口,x 实现了 T
func TestAssignment03(t *testing.T) {
s := NewSpec(`
type T interface {
m()
}
type V struct{}
func (v V) m() {}
var x V
`)
if _, ok := ToInterface(s.GetType("T")); ok {
if s.Implements("x", "T") {
if !s.Assignment("x", "T") {
t.Error(`test rule:
3. T is an interface type and x implements T.
failed`)
}
}
}
}
// 4. x is a bidirectional channel value, T is a channel type,
// x's type V and T have identical element types,
// and at least one of V or T is not a defined type.
// x 是一个双向管道的值,T 是一个管道类型
// x 的类型 V 和 T 有相同的元素类型,并且 V 或 T 至少有一个是未(显示)定义类型
func TestAssignment04(t *testing.T) {
s := NewSpec(`
type T chan int
var x = make(chan int)
`)
V := s.GetType("x")
T := s.GetType("T")
var xIsABidirectionalChanValue, TisAChanType bool
vc, ok := ToChan(V)
if ok && vc.Dir() == types.SendRecv {
xIsABidirectionalChanValue = true
}
tc, ok := ToChan(T)
if ok {
TisAChanType = true
}
if xIsABidirectionalChanValue && TisAChanType {
if Identical(vc.Elem(), tc.Elem()) {
if !IsDefinedType(V) && IsDefinedType(T) {
if !s.Assignment("x", "T") {
t.Error(`test rule:
4. x is a bidirectional channel value, T is a channel type, x's type V and T have identical element types, and at least one of V or T is not a defined type.
failed`)
}
}
}
}
}
// 5. x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
// x 是 nil,T 是一个 指针、函数、切片、字典、管道 或 接口
func TestAssignment05(t *testing.T) {
type typeInfo struct {
code string
f func(types.Type) bool
}
typeNames := []string{"pointer", "function", "slice", "map", "channel", "interface"}
typeMap := map[string]typeInfo{
"pointer": {"type T *int", func(t types.Type) bool {
_, ok := ToPointer(t)
return ok
}},
"function": {"type T func()", func(t types.Type) bool {
_, ok := ToFunction(t)
return ok
}},
"slice": {"type T []string", func(t types.Type) bool {
_, ok := ToSlice(t)
return ok
}},
"map": {"type T map[string]int", func(t types.Type) bool {
_, ok := ToMap(t)
return ok
}},
"channel": {"type T chan int", func(t types.Type) bool {
_, ok := ToChan(t)
return ok
}},
"interface": {"type T interface{}", func(t types.Type) bool {
_, ok := ToInterface(t)
return ok
}},
}
for _, v := range typeNames {
ti, ok := typeMap[v]
if !ok {
continue
}
s := NewSpec(ti.code)
if s.IsInUniverse("nil") && ti.f(s.GetType("T")) {
if !s.Assignment("nil", "T") {
t.Error(`test rule:
5. x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type.
failed`)
}
}
}
}
// 6. x is an untyped constant representable by a value of type T.
// x 是一个未显示定义的常量,且是个可以被 T 代表的值
// 具体见 Representability 可被代表性
func TestAssignment06(t *testing.T) {
s := NewSpec(`
type T int
const x = 1
`)
x := s.GetType("x")
if IsUntyped(x) && IsConstType(x) {
if s.Representable("x", "T") {
if !s.Assignment("x", "T") {
t.Error(`test rule:
6. x is an untyped constant representable by a value of type T.failed`)
}
}
}
}
// func Assignment(code, v, t string) bool
func TestAssignment07(t *testing.T) {
code := `type T = int; var x = 1`
if Identical(code, "x", "T") {
if !Assignment(code, "x", "T") {
t.Error(`test rule:
1. x's type is identical to T.
failed`)
}
}
}