Skip to content

Commit d204876

Browse files
committed
Add tests of internal extension method resolution.
This adds tests verifying expected error and non-error cases for resolution of symbols referenced from inside of the definition of an extension method or a class, which have overlapping definitions in various different scoping levels. Change-Id: I753cc80c0dfdefb3e44429e8bb085c8af3ceb685 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/111882 Reviewed-by: Erik Ernst <eernst@google.com>
1 parent 01a679b commit d204876

16 files changed

+2536
-0
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
import "package:expect/expect.dart";
8+
9+
const String instanceValue = "1";
10+
11+
void checkInstanceValue(String other) {
12+
Expect.equals(other, instanceValue);
13+
}
14+
15+
// A class which has only its own instance methods
16+
class A {
17+
String fieldInInstanceScope = instanceValue;
18+
String get getterInInstanceScope => instanceValue;
19+
set setterInInstanceScope(String x) {
20+
checkInstanceValue(x);
21+
}
22+
String methodInInstanceScope() => instanceValue;
23+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
import "package:expect/expect.dart";
8+
9+
import "class_no_shadow.dart";
10+
11+
// A class which has its own instance methods, which also
12+
// shadows the global scope
13+
class AGlobal extends A {
14+
15+
String fieldInGlobalScope = instanceValue;
16+
String get getterInGlobalScope => instanceValue;
17+
set setterInGlobalScope(String x) {
18+
checkInstanceValue(x);
19+
}
20+
String methodInGlobalScope() => instanceValue;
21+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
import "package:expect/expect.dart";
8+
import "class_no_shadow.dart";
9+
10+
const double otherExtensionValue = 1.234;
11+
12+
void checkOtherExtensionValue(double other) {
13+
Expect.equals(other, otherExtensionValue);
14+
}
15+
16+
// An extension which defines all symbols
17+
extension ExtraExt on A {
18+
double get fieldInGlobalScope => otherExtensionValue;
19+
double get getterInGlobalScope => otherExtensionValue;
20+
set setterInGlobalScope(double x) {
21+
checkOtherExtensionValue(x);
22+
}
23+
double methodInGlobalScope() => otherExtensionValue;
24+
25+
double get fieldInInstanceScope => otherExtensionValue;
26+
double get getterInInstanceScope => otherExtensionValue;
27+
set setterInInstanceScope(double x) {
28+
checkOtherExtensionValue(x);
29+
}
30+
double methodInInstanceScope() => otherExtensionValue;
31+
32+
double get fieldInExtensionScope => otherExtensionValue;
33+
double get getterInExtensionScope => otherExtensionValue;
34+
set setterInExtensionScope(double x) {
35+
checkOtherExtensionValue(x);
36+
}
37+
double methodInExtensionScope() => otherExtensionValue;
38+
39+
double get fieldInOtherExtensionScope => otherExtensionValue;
40+
double get getterInOtherExtensionScope => otherExtensionValue;
41+
set setterInOtherExtensionScope(double x) {
42+
checkOtherExtensionValue(x);
43+
}
44+
double methodInOtherExtensionScope() => otherExtensionValue;
45+
46+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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+
import "package:expect/expect.dart";
8+
import "class_no_shadow.dart";
9+
10+
const double otherExtensionValue = 1.234;
11+
12+
void checkOtherExtensionValue(double other) {
13+
Expect.equals(other, otherExtensionValue);
14+
}
15+
16+
// An extension which defines only global, instance and its own symbols
17+
extension ExtraExt on A {
18+
double get fieldInGlobalScope => otherExtensionValue;
19+
double get getterInGlobalScope => otherExtensionValue;
20+
set setterInGlobalScope(double x) {
21+
checkOtherExtensionValue(x);
22+
}
23+
double methodInGlobalScope() => otherExtensionValue;
24+
25+
double get fieldInInstanceScope => otherExtensionValue;
26+
double get getterInInstanceScope => otherExtensionValue;
27+
set setterInInstanceScope(double x) {
28+
checkOtherExtensionValue(x);
29+
}
30+
double methodInInstanceScope() => otherExtensionValue;
31+
32+
double get fieldInOtherExtensionScope => otherExtensionValue;
33+
double get getterInOtherExtensionScope => otherExtensionValue;
34+
set setterInOtherExtensionScope(double x) {
35+
checkOtherExtensionValue(x);
36+
}
37+
double methodInOtherExtensionScope() => otherExtensionValue;
38+
39+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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+
import "package:expect/expect.dart";
8+
import "class_no_shadow.dart";
9+
10+
const double otherExtensionValue = 1.234;
11+
12+
void checkOtherExtensionValue(double other) {
13+
Expect.equals(other, otherExtensionValue);
14+
}
15+
16+
// An extension which defines only its own symbols
17+
extension ExtraExt on A {
18+
double get fieldInOtherExtensionScope => otherExtensionValue;
19+
double get getterInOtherExtensionScope => otherExtensionValue;
20+
set setterInOtherExtensionScope(double x) {
21+
checkOtherExtensionValue(x);
22+
}
23+
double methodInOtherExtensionScope() => otherExtensionValue;
24+
25+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
import "package:expect/expect.dart";
8+
9+
const int globalValue = 0;
10+
11+
void checkGlobalValue(int x) {
12+
Expect.equals(x, globalValue);
13+
}
14+
15+
// Add symbols to the global scope
16+
int fieldInGlobalScope = globalValue;
17+
int get getterInGlobalScope => globalValue;
18+
set setterInGlobalScope(int x) {
19+
checkGlobalValue(x);
20+
}
21+
int methodInGlobalScope() => globalValue;
Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
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

Comments
 (0)