1
+ // Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2
+ // for details. All rights reserved. Use of this source code is governed by a
3
+ // BSD-style license that can be found in the LICENSE file.
4
+
5
+ // SharedOptions=--enable-experiment=extension-methods
6
+
7
+ // Tests resolution of identifiers inside of extension methods
8
+
9
+ // Test an extension MyExt with no members against:
10
+ // - a class A with only its own members
11
+ // - and another extension ExtraExt with only its own members
12
+
13
+ import "package:expect/expect.dart" ;
14
+
15
+ // Bring global members into scope
16
+ import "helpers/global_scope.dart" ;
17
+
18
+ // Bring a class A with instance members into scope
19
+ import "helpers/class_no_shadow.dart" ;
20
+
21
+ // Bring an extension ExtraExt with no overlapping symbols into scope
22
+ import "helpers/extension_only.dart" ;
23
+
24
+ const bool extensionValue = true ;
25
+
26
+ // An extension which defines no members of its own
27
+ extension MyExt on A {
28
+ void testNakedIdentifiers () {
29
+ // Globals should resolve to the global name space, and not to the members
30
+ // of the other extension (when present)
31
+ {
32
+ int t0 = fieldInGlobalScope;
33
+ checkGlobalValue (t0);
34
+ int t1 = getterInGlobalScope;
35
+ checkGlobalValue (t1);
36
+ setterInGlobalScope = globalValue;
37
+ int t2 = methodInGlobalScope ();
38
+ checkGlobalValue (t2);
39
+ }
40
+
41
+ // Instance members resolve to the instance methods and not the members
42
+ // of the other extension (when present)
43
+ {
44
+ String t0 = fieldInInstanceScope;
45
+ checkInstanceValue (t0);
46
+ String t1 = getterInInstanceScope;
47
+ checkInstanceValue (t0);
48
+ setterInInstanceScope = instanceValue;
49
+ String t2 = methodInInstanceScope ();
50
+ checkInstanceValue (t0);
51
+ }
52
+
53
+ // Extension members resolve to the extension methods in the other
54
+ // extension (unresolved identifier "id" gets turned into "this.id",
55
+ // which is then subject to extension method lookup).
56
+ {
57
+ double t0 = fieldInOtherExtensionScope;
58
+ checkOtherExtensionValue (t0);
59
+ double t1 = getterInOtherExtensionScope;
60
+ checkOtherExtensionValue (t1);
61
+ setterInOtherExtensionScope = otherExtensionValue;
62
+ double t2 = methodInOtherExtensionScope ();
63
+ checkOtherExtensionValue (t2);
64
+ }
65
+
66
+ }
67
+
68
+ void testIdentifiersOnThis () {
69
+ // Instance members resolve to the instance methods and not the members
70
+ // of the other extension (when present)
71
+ {
72
+ String t0 = this .fieldInInstanceScope;
73
+ checkInstanceValue (t0);
74
+ String t1 = this .getterInInstanceScope;
75
+ checkInstanceValue (t0);
76
+ this .setterInInstanceScope = instanceValue;
77
+ String t2 = this .methodInInstanceScope ();
78
+ checkInstanceValue (t0);
79
+ }
80
+
81
+ // Extension members resolve to the extension methods in the other
82
+ // extension.
83
+ {
84
+ double t0 = this .fieldInOtherExtensionScope;
85
+ checkOtherExtensionValue (t0);
86
+ double t1 = this .getterInOtherExtensionScope;
87
+ checkOtherExtensionValue (t1);
88
+ this .setterInOtherExtensionScope = otherExtensionValue;
89
+ double t2 = this .methodInOtherExtensionScope ();
90
+ checkOtherExtensionValue (t2);
91
+ }
92
+ }
93
+
94
+ void testIdentifiersOnInstance () {
95
+ A self = this ;
96
+
97
+ // Instance members resolve to the instance methods and not the members
98
+ // of the other extension (when present)
99
+ {
100
+ String t0 = self.fieldInInstanceScope;
101
+ checkInstanceValue (t0);
102
+ String t1 = self.getterInInstanceScope;
103
+ checkInstanceValue (t1);
104
+ self.setterInInstanceScope = instanceValue;
105
+ String t2 = self.methodInInstanceScope ();
106
+ checkInstanceValue (t2);
107
+ }
108
+
109
+ // Extension members resolve to the extension methods in the other
110
+ // extension.
111
+ {
112
+ double t0 = self.fieldInOtherExtensionScope;
113
+ checkOtherExtensionValue (t0);
114
+ double t1 = self.getterInOtherExtensionScope;
115
+ checkOtherExtensionValue (t1);
116
+ self.setterInOtherExtensionScope = otherExtensionValue;
117
+ double t2 = self.methodInOtherExtensionScope ();
118
+ checkOtherExtensionValue (t2);
119
+
120
+ }
121
+ }
122
+
123
+ void instanceTest () {
124
+ MyExt (this ).testNakedIdentifiers ();
125
+ MyExt (this ).testIdentifiersOnThis ();
126
+ MyExt (this ).testIdentifiersOnInstance ();
127
+ }
128
+ }
129
+
130
+ class B extends A {
131
+ void testNakedIdentifiers () {
132
+ // Globals should resolve to the global name space, and not to the members
133
+ // of the other extension (when present)
134
+ {
135
+ int t0 = fieldInGlobalScope;
136
+ checkGlobalValue (t0);
137
+ int t1 = getterInGlobalScope;
138
+ checkGlobalValue (t1);
139
+ setterInGlobalScope = globalValue;
140
+ int t2 = methodInGlobalScope ();
141
+ checkGlobalValue (t2);
142
+ }
143
+
144
+ // Instance members resolve to the instance methods and not the members
145
+ // of the other extension (when present)
146
+ {
147
+ String t0 = fieldInInstanceScope;
148
+ checkInstanceValue (t0);
149
+ String t1 = getterInInstanceScope;
150
+ checkInstanceValue (t0);
151
+ setterInInstanceScope = instanceValue;
152
+ String t2 = methodInInstanceScope ();
153
+ checkInstanceValue (t0);
154
+ }
155
+
156
+ // Extension members resolve to the extension methods in the other
157
+ // extension (unresolved identifier "id" gets turned into "this.id",
158
+ // which is then subject to extension method lookup).
159
+ {
160
+ double t0 = fieldInOtherExtensionScope;
161
+ checkOtherExtensionValue (t0);
162
+ double t1 = getterInOtherExtensionScope;
163
+ checkOtherExtensionValue (t1);
164
+ setterInOtherExtensionScope = otherExtensionValue;
165
+ double t2 = methodInOtherExtensionScope ();
166
+ checkOtherExtensionValue (t2);
167
+ }
168
+ }
169
+ }
170
+
171
+ void main () {
172
+ var a = new A ();
173
+ a.instanceTest ();
174
+ new B ().testNakedIdentifiers ();
175
+
176
+ // Check external resolution as well while we're here
177
+
178
+ // Instance members resolve to the instance methods and not the members
179
+ // of the other extension (when present)
180
+ {
181
+ String t0 = a.fieldInInstanceScope;
182
+ checkInstanceValue (t0);
183
+ String t1 = a.getterInInstanceScope;
184
+ checkInstanceValue (t1);
185
+ a.setterInInstanceScope = instanceValue;
186
+ String t2 = a.methodInInstanceScope ();
187
+ checkInstanceValue (t2);
188
+ }
189
+
190
+ // Extension members resolve to the extension methods in the other
191
+ // extension.
192
+ {
193
+ double t0 = a.fieldInOtherExtensionScope;
194
+ checkOtherExtensionValue (t0);
195
+ double t1 = a.getterInOtherExtensionScope;
196
+ checkOtherExtensionValue (t1);
197
+ a.setterInOtherExtensionScope = otherExtensionValue;
198
+ double t2 = a.methodInOtherExtensionScope ();
199
+ checkOtherExtensionValue (t2);
200
+ }
201
+
202
+ }
0 commit comments