Skip to content

Commit 53cdbfb

Browse files
chloestefantsovaCommit Bot
authored and
Commit Bot
committed
[cfe] Preserve correct enum elements to avoid cascading errors
Part of #47453 Change-Id: Ic79a7667e5eb1b4cf27c1d1628312e4d8c052304 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/233382 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Chloe Stefantsova <[email protected]>
1 parent bbe065b commit 53cdbfb

11 files changed

+291
-1
lines changed

pkg/_fe_analyzer_shared/lib/src/parser/stack_listener.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ enum NullValue {
4242
ContinueTarget,
4343
Deferred,
4444
DocumentationComment,
45+
EnumConstantInfo,
4546
Expression,
4647
ExtendsClause,
4748
FieldInitializer,

pkg/front_end/lib/src/fasta/source/outline_builder.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2358,7 +2358,7 @@ class OutlineBuilder extends StackListenerImpl {
23582358
..argumentsBeginToken = argumentsBeginToken);
23592359
} else {
23602360
assert(enumConstantInfo is ParserRecovery);
2361-
push(enumConstantInfo);
2361+
push(NullValue.EnumConstantInfo);
23622362
}
23632363
}
23642364

@@ -2400,6 +2400,26 @@ class OutlineBuilder extends StackListenerImpl {
24002400
int elementsCount = pop() as int;
24012401
List<EnumConstantInfo?>? enumConstantInfos =
24022402
const FixedNullableList<EnumConstantInfo>().pop(stack, elementsCount);
2403+
2404+
if (enumConstantInfos != null) {
2405+
List<EnumConstantInfo?>? parsedEnumConstantInfos;
2406+
for (int index = 0; index < enumConstantInfos.length; index++) {
2407+
EnumConstantInfo? info = enumConstantInfos[index];
2408+
if (info == null) {
2409+
parsedEnumConstantInfos = enumConstantInfos.take(index).toList();
2410+
} else if (parsedEnumConstantInfos != null) {
2411+
parsedEnumConstantInfos.add(info);
2412+
}
2413+
}
2414+
if (parsedEnumConstantInfos != null) {
2415+
if (parsedEnumConstantInfos.isEmpty) {
2416+
enumConstantInfos = null;
2417+
} else {
2418+
enumConstantInfos = parsedEnumConstantInfos;
2419+
}
2420+
}
2421+
}
2422+
24032423
int endCharOffset = popCharOffset();
24042424
int startCharOffset = popCharOffset();
24052425
List<TypeBuilder>? interfaces = pop() as List<TypeBuilder>?;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
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+
enum E {
6+
element, // The declaration of the element is correct.
7+
8+
final String foo = "foo"; // Error: attempt to parse the field as an element.
9+
}
10+
11+
test() {
12+
return E.element; // No error: the element is added to the enum.
13+
}
14+
15+
main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected an identifier, but got 'final'.
6+
// Try inserting an identifier before 'final'.
7+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
8+
// ^^^^^
9+
//
10+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected '}' before this.
11+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
12+
// ^^^^^
13+
//
14+
import self as self;
15+
import "dart:core" as core;
16+
17+
class E extends core::_Enum /*isEnum*/ {
18+
static const field core::List<self::E> values = #C4;
19+
static const field self::E element = #C3;
20+
const constructor •(core::int index, core::String name) → self::E
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
}
26+
static method test() → dynamic {
27+
return #C3;
28+
}
29+
static method main() → dynamic {}
30+
31+
constants {
32+
#C1 = 0
33+
#C2 = "element"
34+
#C3 = self::E {index:#C1, _name:#C2}
35+
#C4 = <self::E>[#C3]
36+
}
37+
38+
39+
Constructor coverage from constants:
40+
org-dartlang-testcase:///recovery_in_elements.dart:
41+
- E. (from org-dartlang-testcase:///recovery_in_elements.dart:5:6)
42+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
43+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected an identifier, but got 'final'.
6+
// Try inserting an identifier before 'final'.
7+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
8+
// ^^^^^
9+
//
10+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected '}' before this.
11+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
12+
// ^^^^^
13+
//
14+
import self as self;
15+
import "dart:core" as core;
16+
17+
class E extends core::_Enum /*isEnum*/ {
18+
static const field core::List<self::E> values = #C4;
19+
static const field self::E element = #C3;
20+
const constructor •(core::int index, core::String name) → self::E
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
}
26+
static method test() → dynamic {
27+
return #C3;
28+
}
29+
static method main() → dynamic {}
30+
31+
constants {
32+
#C1 = 0
33+
#C2 = "element"
34+
#C3 = self::E {index:#C1, _name:#C2}
35+
#C4 = <self::E>[#C3]
36+
}
37+
38+
39+
Constructor coverage from constants:
40+
org-dartlang-testcase:///recovery_in_elements.dart:
41+
- E. (from org-dartlang-testcase:///recovery_in_elements.dart:5:6)
42+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
43+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
enum E { element, final String foo = "foo"; }
2+
test() {}
3+
main() {}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected an identifier, but got 'final'.
6+
// Try inserting an identifier before 'final'.
7+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
8+
// ^^^^^
9+
//
10+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected '}' before this.
11+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
12+
// ^^^^^
13+
//
14+
import self as self;
15+
import "dart:core" as core;
16+
17+
class E extends core::_Enum /*isEnum*/ {
18+
static const field core::List<self::E> values = #C4;
19+
static const field self::E element = #C3;
20+
const constructor •(core::int index, core::String name) → self::E
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
}
26+
static method test() → dynamic {
27+
return #C3;
28+
}
29+
static method main() → dynamic {}
30+
31+
constants {
32+
#C1 = 0
33+
#C2 = "element"
34+
#C3 = self::E {index:#C1, _name:#C2}
35+
#C4 = <self::E*>[#C3]
36+
}
37+
38+
39+
Constructor coverage from constants:
40+
org-dartlang-testcase:///recovery_in_elements.dart:
41+
- E. (from org-dartlang-testcase:///recovery_in_elements.dart:5:6)
42+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
43+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected an identifier, but got 'final'.
6+
// Try inserting an identifier before 'final'.
7+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
8+
// ^^^^^
9+
//
10+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected '}' before this.
11+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
12+
// ^^^^^
13+
//
14+
import self as self;
15+
import "dart:core" as core;
16+
17+
class E extends core::_Enum /*isEnum*/ {
18+
static const field core::List<self::E> values = #C4;
19+
static const field self::E element = #C3;
20+
const constructor •(core::int index, core::String name) → self::E
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
}
26+
static method test() → dynamic {
27+
return #C3;
28+
}
29+
static method main() → dynamic {}
30+
31+
constants {
32+
#C1 = 0
33+
#C2 = "element"
34+
#C3 = self::E {index:#C1, _name:#C2}
35+
#C4 = <self::E*>[#C3]
36+
}
37+
38+
39+
Constructor coverage from constants:
40+
org-dartlang-testcase:///recovery_in_elements.dart:
41+
- E. (from org-dartlang-testcase:///recovery_in_elements.dart:5:6)
42+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
43+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected an identifier, but got 'final'.
6+
// Try inserting an identifier before 'final'.
7+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
8+
// ^^^^^
9+
//
10+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected '}' before this.
11+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
12+
// ^^^^^
13+
//
14+
import self as self;
15+
import "dart:core" as core;
16+
17+
class E extends core::_Enum /*isEnum*/ {
18+
static const field core::List<self::E> values = const <self::E>[self::E::element];
19+
static const field self::E element = const self::E::•(0, "element");
20+
const constructor •(core::int index, core::String name) → self::E
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
}
26+
static method test() → dynamic
27+
;
28+
static method main() → dynamic
29+
;
30+
31+
32+
Extra constant evaluation status:
33+
Evaluated: ListLiteral @ org-dartlang-testcase:///recovery_in_elements.dart:5:6 -> ListConstant(const <E*>[const E{_Enum.index: 0, _Enum._name: "element"}])
34+
Evaluated: ConstructorInvocation @ org-dartlang-testcase:///recovery_in_elements.dart:6:3 -> InstanceConstant(const E{_Enum.index: 0, _Enum._name: "element"})
35+
Extra constant evaluation: evaluated: 7, effectively constant: 2
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
library /*isNonNullableByDefault*/;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected an identifier, but got 'final'.
6+
// Try inserting an identifier before 'final'.
7+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
8+
// ^^^^^
9+
//
10+
// pkg/front_end/testcases/enhanced_enums/recovery_in_elements.dart:8:3: Error: Expected '}' before this.
11+
// final String foo = "foo"; // Error: attempt to parse the field as an element.
12+
// ^^^^^
13+
//
14+
import self as self;
15+
import "dart:core" as core;
16+
17+
class E extends core::_Enum /*isEnum*/ {
18+
static const field core::List<self::E> values = #C4;
19+
static const field self::E element = #C3;
20+
const constructor •(core::int index, core::String name) → self::E
21+
: super core::_Enum::•(index, name)
22+
;
23+
method toString() → core::String
24+
return "E.${this.{core::_Enum::_name}{core::String}}";
25+
}
26+
static method test() → dynamic {
27+
return #C3;
28+
}
29+
static method main() → dynamic {}
30+
31+
constants {
32+
#C1 = 0
33+
#C2 = "element"
34+
#C3 = self::E {index:#C1, _name:#C2}
35+
#C4 = <self::E*>[#C3]
36+
}
37+
38+
39+
Constructor coverage from constants:
40+
org-dartlang-testcase:///recovery_in_elements.dart:
41+
- E. (from org-dartlang-testcase:///recovery_in_elements.dart:5:6)
42+
- _Enum. (from org-dartlang-sdk:///sdk/lib/core/enum.dart:103:9)
43+
- Object. (from org-dartlang-sdk:///sdk/lib/core/object.dart:25:9)

pkg/front_end/testcases/textual_outline.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enhanced_enums/members: FormatterCrash
4444
enhanced_enums/named_arguments: FormatterCrash
4545
enhanced_enums/named_arguments_anywhere/redirecting_constructor: FormatterCrash
4646
enhanced_enums/qualified_names_with_no_type_arguments: FormatterCrash
47+
enhanced_enums/recovery_in_elements: FormatterCrash
4748
enhanced_enums/redirecting_initializers: FormatterCrash
4849
enhanced_enums/simple_fields: FormatterCrash
4950
enhanced_enums/simple_interfaces: FormatterCrash

0 commit comments

Comments
 (0)