[cfe] Fixes to part with parts

Before this CL we could both crash and add wrong metadata to "part"
nodes when a part defined other parts.
This CL fixes it by
a) Not resetting a counter so *every* part in a part will be out of
   bounds when trying to reference it; and
b) Check if a part directive is in bounds and ignore it if it isn't
   (an error should already have been issued).

Change-Id: I3d31f2577b2120df6461c9cc1002131dbee9dbbc
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106641
Commit-Queue: Jens Johansen <jensj@google.com>
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index cf3c27f..c556487 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -496,8 +496,14 @@
 
     Token metadata = pop();
     Library libraryNode = library.target;
-    LibraryPart part = libraryNode.parts[partDirectiveIndex++];
-    parseMetadata(library, metadata, part);
+    if (libraryNode.parts.length > partDirectiveIndex) {
+      // If partDirectiveIndex >= libraryNode.parts.length we are in a case of
+      // on part having other parts. An error has already been issued.
+      // Don't try to parse metadata into other parts that have nothing to do
+      // with the one this keyword is talking about.
+      LibraryPart part = libraryNode.parts[partDirectiveIndex++];
+      parseMetadata(library, metadata, part);
+    }
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index c420708..3040e27 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -289,7 +289,6 @@
         Token tokens = await tokenize(part);
         if (tokens != null) {
           listener.uri = part.fileUri;
-          listener.partDirectiveIndex = 0;
           parser.parseUnit(tokens);
         }
       }
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 65cb2ec..7e5143d 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -2,9 +2,6 @@
 # for details. All rights reserved. Use of this source code is governed by a
 # BSD-style license that can be found in the LICENSE.md file.
 
-# Not sorted --- these crashes should be fixed ASAP!
-PartTwice/part_wrapped_script: Crash
-
 AbstractClassInstantiation/example: Fail
 AbstractClassMember/part_wrapped_script5: Fail
 AbstractClassMember/part_wrapped_script6: Fail
@@ -413,6 +410,7 @@
 PartOfUseUri/example: Fail
 PartOrphan/analyzerCode: Fail # Analyzer can't handle this situation
 PartOrphan/part_wrapped_script: Fail # Already using 'part of' in the (now) part.
+PartTwice/part_wrapped_script: Fail # Using 'part' in the (now) part.
 PatchClassTypeVariablesMismatch/analyzerCode: Fail
 PatchClassTypeVariablesMismatch/example: Fail
 PatchDeclarationMismatch/analyzerCode: Fail
diff --git a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.expect b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.expect
index 176c13c..929cc78 100644
--- a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.expect
+++ b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.expect
@@ -12,7 +12,6 @@
 import "dart:core" as core;
 
 @self::Foo
-@self::Bar
 part having_part_with_part_and_annotation_lib1.dart;
 static const field core::int Foo = 42;
 static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_part_and_annotation_lib1.dart */;
diff --git a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.transformed.expect b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.transformed.expect
index 176c13c..929cc78 100644
--- a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.legacy.transformed.expect
@@ -12,7 +12,6 @@
 import "dart:core" as core;
 
 @self::Foo
-@self::Bar
 part having_part_with_part_and_annotation_lib1.dart;
 static const field core::int Foo = 42;
 static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_part_and_annotation_lib1.dart */;
diff --git a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.expect b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.expect
index 176c13c..929cc78 100644
--- a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.expect
+++ b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.expect
@@ -12,7 +12,6 @@
 import "dart:core" as core;
 
 @self::Foo
-@self::Bar
 part having_part_with_part_and_annotation_lib1.dart;
 static const field core::int Foo = 42;
 static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_part_and_annotation_lib1.dart */;
diff --git a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.transformed.expect b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.transformed.expect
index 176c13c..929cc78 100644
--- a/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/having_part_with_part_and_annotation.dart.strong.transformed.expect
@@ -12,7 +12,6 @@
 import "dart:core" as core;
 
 @self::Foo
-@self::Bar
 part having_part_with_part_and_annotation_lib1.dart;
 static const field core::int Foo = 42;
 static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_part_and_annotation_lib1.dart */;
diff --git a/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.legacy.expect b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.legacy.expect
new file mode 100644
index 0000000..a33aba1
--- /dev/null
+++ b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.legacy.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:4:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:6:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+import self as self;
+import "dart:core" as core;
+
+@self::Foo
+part having_part_with_parts_and_annotation_lib1.dart;
+static const field core::int Foo = 42;
+static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static const field core::int Baz = 44 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static method fromMain() → void {}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */ fromLib1() → void {}
diff --git a/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.legacy.transformed.expect b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.legacy.transformed.expect
new file mode 100644
index 0000000..a33aba1
--- /dev/null
+++ b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.legacy.transformed.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:4:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:6:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+import self as self;
+import "dart:core" as core;
+
+@self::Foo
+part having_part_with_parts_and_annotation_lib1.dart;
+static const field core::int Foo = 42;
+static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static const field core::int Baz = 44 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static method fromMain() → void {}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */ fromLib1() → void {}
diff --git a/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.strong.expect b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.strong.expect
new file mode 100644
index 0000000..a33aba1
--- /dev/null
+++ b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.strong.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:4:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:6:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+import self as self;
+import "dart:core" as core;
+
+@self::Foo
+part having_part_with_parts_and_annotation_lib1.dart;
+static const field core::int Foo = 42;
+static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static const field core::int Baz = 44 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static method fromMain() → void {}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */ fromLib1() → void {}
diff --git a/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.strong.transformed.expect b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.strong.transformed.expect
new file mode 100644
index 0000000..a33aba1
--- /dev/null
+++ b/pkg/front_end/testcases/having_part_with_parts_and_annotation.dart.strong.transformed.expect
@@ -0,0 +1,27 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:4:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+// pkg/front_end/testcases/having_part_with_parts_and_annotation_lib1.dart:6:6: Error: A file that's a part of a library can't have parts itself.
+// Try moving the 'part' declaration to the containing library.
+// part 'having_part_with_parts_and_annotation_lib2.dart';
+//      ^
+// pkg/front_end/testcases/having_part_with_parts_and_annotation.dart: Context: This is the containing library.
+//
+import self as self;
+import "dart:core" as core;
+
+@self::Foo
+part having_part_with_parts_and_annotation_lib1.dart;
+static const field core::int Foo = 42;
+static const field core::int Bar = 43 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static const field core::int Baz = 44 /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */;
+static method fromMain() → void {}
+static method main() → dynamic {}
+static method /* from org-dartlang-testcase:///having_part_with_parts_and_annotation_lib1.dart */ fromLib1() → void {}
diff --git a/pkg/front_end/testcases/legacy.status b/pkg/front_end/testcases/legacy.status
index 2a0d665..b1b1917 100644
--- a/pkg/front_end/testcases/legacy.status
+++ b/pkg/front_end/testcases/legacy.status
@@ -16,7 +16,6 @@
 external_import: RuntimeError # Expected -- test uses import which doesn't exist.
 fallthrough: Fail # Missing FallThroughError.
 function_type_recovery: Fail
-having_part_with_parts_and_annotation: Crash
 incomplete_field_formal_parameter: Fail # Fasta doesn't recover well
 inference/bug31436: RuntimeError # Test exercises Dart 2.0 semantics
 inference/constructors_too_many_positional_arguments: Fail
diff --git a/pkg/front_end/testcases/strong.status b/pkg/front_end/testcases/strong.status
index 44b9c0b..79ac736 100644
--- a/pkg/front_end/testcases/strong.status
+++ b/pkg/front_end/testcases/strong.status
@@ -24,7 +24,6 @@
 expressions: RuntimeError
 external_import: RuntimeError # The native extension to import doesn't exist. This is ok.
 fallthrough: ExpectationFileMismatch
-having_part_with_parts_and_annotation: Crash
 incomplete_field_formal_parameter: RuntimeError
 inference/abstract_class_instantiation: InstrumentationMismatch # Issue #30040
 inference/conflicting_fields: TypeCheckError
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index b43ed5f..8508fee 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -105,7 +105,7 @@
 future_or_test: TextSerializationFailure # Was: Pass
 hello: TextSerializationFailure # Was: Pass
 having_part_with_part_and_annotation: TextSerializationFailure
-having_part_with_parts_and_annotation: Crash
+having_part_with_parts_and_annotation: TextSerializationFailure
 illegal_named_function_expression: TextSerializationFailure # Was: Pass
 illegal_named_function_expression_scope: TextSerializationFailure # Was: Pass
 implicit_const_with_static_fields: TextSerializationFailure # Was: Pass