Skip to content

Commit f5fa463

Browse files
authored
#1399. [Records] Tests for ambiguity with metadata annotations added (#1524)
Authored by @sgrekhov. Add tests for ambiguity with metadata annotations.
1 parent 31e395d commit f5fa463

13 files changed

+842
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) 2022, 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+
/// @assertion @metadata (a, b) function() {}
6+
/// This could be a metadata annotation @metadata(a, b) associated with a
7+
/// function declaration with no return type. Or it could be a metadata
8+
/// annotation @metadata associated with a function whose return type is the
9+
/// record type (a, b).
10+
///
11+
/// In practice, idiomatically written code is clear thanks to whitespace:
12+
///
13+
/// @metadata(a, b) function() {}
14+
///
15+
/// @metadata (a, b) function() {}
16+
///
17+
/// The former applies (a, b) to the metadata annotation and the latter is a
18+
/// return type. We disambiguate in the same way, by making whitespace after a
19+
/// metadata annotation name significant. Change the grammar to:
20+
///
21+
/// metadatum ::= identifier // Existing rule.
22+
/// | qualifiedName // Existing rule.
23+
/// | constructorDesignation NO_SPACE arguments // Changed.
24+
/// The NO_SPACE lexical rule matches when there are no whitespace characters or
25+
/// comments (according to the existing WHITESPACE and COMMENT lexical rules)
26+
/// between the constructorDesignation and arguments. In other words, for an
27+
/// argument list to be part of the metadata annotation, the ( must occur
28+
/// immediately after the last character in the constructorDesignation. The last
29+
/// character in constructorDesignation may be an identifier or the > in a type
30+
/// argument list.
31+
///
32+
/// @description Checks that if there is a space between @metadata and (a, b)
33+
/// then (a, b) denotes a record. Test functions with no comment between a
34+
/// metadata and a return type
35+
/// @author [email protected]
36+
37+
// SharedOptions=--enable-experiment=records
38+
39+
import "../../Utils/expect.dart";
40+
41+
const Meta = "meta";
42+
43+
@Meta (int, String) foo1() => (1, "2");
44+
45+
@Meta
46+
(int, String) foo2() => (3, "4");
47+
48+
@Meta () foo3() => ();
49+
50+
@Meta
51+
() foo4() => ();
52+
53+
@Meta (int, {String name}) foo5() => (5, name: "name");
54+
55+
main() {
56+
Expect.equals(1, foo1().$0);
57+
Expect.equals("2", foo1().$1);
58+
Expect.equals(3, foo2().$0);
59+
Expect.equals("4", foo2().$1);
60+
Expect.equals((), foo3());
61+
Expect.equals((), foo4());
62+
Expect.equals(5, foo5().$0);
63+
Expect.equals("name", foo5().name);
64+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2022, 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+
/// @assertion @metadata (a, b) function() {}
6+
/// This could be a metadata annotation @metadata(a, b) associated with a
7+
/// function declaration with no return type. Or it could be a metadata
8+
/// annotation @metadata associated with a function whose return type is the
9+
/// record type (a, b).
10+
///
11+
/// In practice, idiomatically written code is clear thanks to whitespace:
12+
///
13+
/// @metadata(a, b) function() {}
14+
///
15+
/// @metadata (a, b) function() {}
16+
///
17+
/// The former applies (a, b) to the metadata annotation and the latter is a
18+
/// return type. We disambiguate in the same way, by making whitespace after a
19+
/// metadata annotation name significant. Change the grammar to:
20+
///
21+
/// metadatum ::= identifier // Existing rule.
22+
/// | qualifiedName // Existing rule.
23+
/// | constructorDesignation NO_SPACE arguments // Changed.
24+
/// The NO_SPACE lexical rule matches when there are no whitespace characters or
25+
/// comments (according to the existing WHITESPACE and COMMENT lexical rules)
26+
/// between the constructorDesignation and arguments. In other words, for an
27+
/// argument list to be part of the metadata annotation, the ( must occur
28+
/// immediately after the last character in the constructorDesignation. The last
29+
/// character in constructorDesignation may be an identifier or the > in a type
30+
/// argument list.
31+
///
32+
/// @description Checks that if there is a space between @metadata and (a, b)
33+
/// then (a, b) denotes a record. Test functions with comment between a
34+
/// metadata and a return type
35+
/// @author [email protected]
36+
37+
// SharedOptions=--enable-experiment=records
38+
39+
import "../../Utils/expect.dart";
40+
41+
const Meta = "meta";
42+
43+
@Meta/* comment */(int, String) foo1() => (1, "2");
44+
45+
@Meta// comment
46+
(int, String) foo2() => (3, "4");
47+
48+
@Meta /* comment */() foo3() => ();
49+
50+
@Meta// comment
51+
() foo4() => ();
52+
53+
@Meta/* comment */ (int, {String name}) foo5() => (5, name: "name");
54+
55+
@Meta /* comment */ (int, {String name}) foo6() => (6, name: "name");
56+
57+
main() {
58+
Expect.equals(1, foo1().$0);
59+
Expect.equals("2", foo1().$1);
60+
Expect.equals(3, foo2().$0);
61+
Expect.equals("4", foo2().$1);
62+
Expect.equals((), foo3());
63+
Expect.equals((), foo4());
64+
Expect.equals(5, foo5().$0);
65+
Expect.equals("name", foo5().name);
66+
Expect.equals(6, foo6().$0);
67+
Expect.equals("name", foo6().name);
68+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
// Copyright (c) 2022, 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+
/// @assertion @metadata (a, b) function() {}
6+
/// This could be a metadata annotation @metadata(a, b) associated with a
7+
/// function declaration with no return type. Or it could be a metadata
8+
/// annotation @metadata associated with a function whose return type is the
9+
/// record type (a, b).
10+
///
11+
/// In practice, idiomatically written code is clear thanks to whitespace:
12+
///
13+
/// @metadata(a, b) function() {}
14+
///
15+
/// @metadata (a, b) function() {}
16+
///
17+
/// The former applies (a, b) to the metadata annotation and the latter is a
18+
/// return type. We disambiguate in the same way, by making whitespace after a
19+
/// metadata annotation name significant. Change the grammar to:
20+
///
21+
/// metadatum ::= identifier // Existing rule.
22+
/// | qualifiedName // Existing rule.
23+
/// | constructorDesignation NO_SPACE arguments // Changed.
24+
/// The NO_SPACE lexical rule matches when there are no whitespace characters or
25+
/// comments (according to the existing WHITESPACE and COMMENT lexical rules)
26+
/// between the constructorDesignation and arguments. In other words, for an
27+
/// argument list to be part of the metadata annotation, the ( must occur
28+
/// immediately after the last character in the constructorDesignation. The last
29+
/// character in constructorDesignation may be an identifier or the > in a type
30+
/// argument list.
31+
///
32+
/// @description Checks that if there is a space between @metadata and (a, b)
33+
/// then (a, b) denotes a record. Test variables declaration with no comment
34+
/// between a metadata and a return type
35+
/// @author [email protected]
36+
37+
// SharedOptions=--enable-experiment=records
38+
39+
import "../../Utils/expect.dart";
40+
41+
const Meta = "meta";
42+
43+
main() {
44+
@Meta (int, String) r1 = (1, "2");
45+
46+
@Meta
47+
(int, String) r2 = (3, "4");
48+
49+
@Meta () r3 = ();
50+
51+
@Meta
52+
() r4 = ();
53+
54+
@Meta (int, {String name}) r5 = (5, name: "name");
55+
56+
Expect.equals(1, r1.$0);
57+
Expect.equals("2", r1.$1);
58+
Expect.equals(3, r2.$0);
59+
Expect.equals("4", r2.$1);
60+
Expect.equals((), r3);
61+
Expect.equals((), r4);
62+
Expect.equals(5, r5.$0);
63+
Expect.equals("name", r5.name);
64+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// Copyright (c) 2022, 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+
/// @assertion @metadata (a, b) function() {}
6+
/// This could be a metadata annotation @metadata(a, b) associated with a
7+
/// function declaration with no return type. Or it could be a metadata
8+
/// annotation @metadata associated with a function whose return type is the
9+
/// record type (a, b).
10+
///
11+
/// In practice, idiomatically written code is clear thanks to whitespace:
12+
///
13+
/// @metadata(a, b) function() {}
14+
///
15+
/// @metadata (a, b) function() {}
16+
///
17+
/// The former applies (a, b) to the metadata annotation and the latter is a
18+
/// return type. We disambiguate in the same way, by making whitespace after a
19+
/// metadata annotation name significant. Change the grammar to:
20+
///
21+
/// metadatum ::= identifier // Existing rule.
22+
/// | qualifiedName // Existing rule.
23+
/// | constructorDesignation NO_SPACE arguments // Changed.
24+
/// The NO_SPACE lexical rule matches when there are no whitespace characters or
25+
/// comments (according to the existing WHITESPACE and COMMENT lexical rules)
26+
/// between the constructorDesignation and arguments. In other words, for an
27+
/// argument list to be part of the metadata annotation, the ( must occur
28+
/// immediately after the last character in the constructorDesignation. The last
29+
/// character in constructorDesignation may be an identifier or the > in a type
30+
/// argument list.
31+
///
32+
/// @description Checks that if there is a space between @metadata and (a, b)
33+
/// then (a, b) denotes a record. Test variables declaration with a comment
34+
/// between a metadata and a return type
35+
/// @author [email protected]
36+
37+
// SharedOptions=--enable-experiment=records
38+
39+
import "../../Utils/expect.dart";
40+
41+
const Meta = "meta";
42+
43+
main() {
44+
@Meta/* comment */(int, String) r1 = (1, "2");
45+
46+
@Meta// comment
47+
(int, String) r2 = (3, "4");
48+
49+
@Meta/* comment */ () r3 = ();
50+
51+
@Meta // comment
52+
() r4 = ();
53+
54+
@Meta /* comment */(int, {String name}) r5 = (5, name: "name");
55+
56+
@Meta /* comment */ (int, {String name}) r6 = (6, name: "name");
57+
58+
Expect.equals(1, r1.$0);
59+
Expect.equals("2", r1.$1);
60+
Expect.equals(3, r2.$0);
61+
Expect.equals("4", r2.$1);
62+
Expect.equals((), r3);
63+
Expect.equals((), r4);
64+
Expect.equals(5, r5.$0);
65+
Expect.equals("name", r5.name);
66+
Expect.equals(6, r5.$0);
67+
Expect.equals("name", r6.name);
68+
}
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright (c) 2022, 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+
/// @assertion @metadata (a, b) function() {}
6+
/// This could be a metadata annotation @metadata(a, b) associated with a
7+
/// function declaration with no return type. Or it could be a metadata
8+
/// annotation @metadata associated with a function whose return type is the
9+
/// record type (a, b).
10+
///
11+
/// In practice, idiomatically written code is clear thanks to whitespace:
12+
///
13+
/// @metadata(a, b) function() {}
14+
///
15+
/// @metadata (a, b) function() {}
16+
///
17+
/// The former applies (a, b) to the metadata annotation and the latter is a
18+
/// return type. We disambiguate in the same way, by making whitespace after a
19+
/// metadata annotation name significant. Change the grammar to:
20+
///
21+
/// metadatum ::= identifier // Existing rule.
22+
/// | qualifiedName // Existing rule.
23+
/// | constructorDesignation NO_SPACE arguments // Changed.
24+
/// The NO_SPACE lexical rule matches when there are no whitespace characters or
25+
/// comments (according to the existing WHITESPACE and COMMENT lexical rules)
26+
/// between the constructorDesignation and arguments. In other words, for an
27+
/// argument list to be part of the metadata annotation, the ( must occur
28+
/// immediately after the last character in the constructorDesignation. The last
29+
/// character in constructorDesignation may be an identifier or the > in a type
30+
/// argument list.
31+
///
32+
/// @description Checks that it is a compile-time error if there is a space
33+
/// between metadata and its arguments list.
34+
/// @author [email protected]
35+
36+
// SharedOptions=--enable-experiment=records
37+
38+
class Meta {
39+
const Meta(Type t1, Type t2);
40+
}
41+
42+
class M {
43+
const M();
44+
}
45+
46+
/**/@Meta (int, String) foo1() => (1, "2");
47+
// ^^^^^
48+
// [analyzer] unspecified
49+
// [cfe] unspecified
50+
51+
/**/@Meta
52+
// ^^^^^
53+
// [analyzer] unspecified
54+
// [cfe] unspecified
55+
(int, String) foo2() => (3, "4");
56+
57+
/**/@M () foo3() => ();
58+
// ^^
59+
// [analyzer] unspecified
60+
// [cfe] unspecified
61+
/**/@M
62+
// ^^
63+
// [analyzer] unspecified
64+
// [cfe] unspecified
65+
() foo4() => ();
66+
67+
/**/@Meta/* comment */(int, String) foo5() => (5, "6");
68+
// ^^^^^
69+
// [analyzer] unspecified
70+
// [cfe] unspecified
71+
72+
/**/@Meta // comment
73+
// ^^^^^
74+
// [analyzer] unspecified
75+
// [cfe] unspecified
76+
(int, String) foo6() => (7, "8");
77+
78+
/**/@M/* comment */ () foo7() => ();
79+
// ^^
80+
// [analyzer] unspecified
81+
// [cfe] unspecified
82+
83+
/**/@M // comment
84+
// ^^
85+
// [analyzer] unspecified
86+
// [cfe] unspecified
87+
() foo8() => ();
88+
89+
main() {
90+
foo1();
91+
foo2();
92+
foo3();
93+
foo4();
94+
foo5();
95+
foo6();
96+
foo7();
97+
foo8();
98+
}

0 commit comments

Comments
 (0)