Error when a file is a part of more than one library

Fixes https://github.com/dart-lang/sdk/issues/32999

Corresponding spec issue: https://github.com/dart-lang/sdk/issues/33225
Issue for co19 fix: https://github.com/dart-lang/co19/issues/149

The code contains a temporary hack that works around the co19 use.
This hack can be removed when the co19 fix rolls in.

Change-Id: I61b50c9142f4b215fc4d9258f1259e24ab4c052f
Reviewed-on: https://dart-review.googlesource.com/56521
Reviewed-by: Peter von der Ahé <ahe@google.com>
Commit-Queue: Aske Simon Christensen <askesc@google.com>
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index da2122c..46e8ad8 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -4859,6 +4859,27 @@
     tip: r"""Try removing all but one of the part-of directives.""");
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOfTwoLibraries = messagePartOfTwoLibraries;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOfTwoLibraries = const MessageCode(
+    "PartOfTwoLibraries",
+    severity: Severity.error,
+    message: r"""A file can't be part of more than one library.""",
+    tip:
+        r"""Try moving the shared declarations into the libraries, or into a new library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Null> codePartOfTwoLibrariesContext =
+    messagePartOfTwoLibrariesContext;
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const MessageCode messagePartOfTwoLibrariesContext = const MessageCode(
+    "PartOfTwoLibrariesContext",
+    severity: Severity.context,
+    message: r"""Used as a part in this library.""");
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
     Message Function(
         Uri uri_,
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 93390f9..9b5db36 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -43,6 +43,8 @@
         messageExpectedUri,
         messageMemberWithSameNameAsClass,
         messagePartOfSelf,
+        messagePartOfTwoLibraries,
+        messagePartOfTwoLibrariesContext,
         noLength,
         templateConflictsWithMember,
         templateConflictsWithSetter,
@@ -589,11 +591,23 @@
 
   void includeParts() {
     Set<Uri> seenParts = new Set<Uri>();
-    for (SourceLibraryBuilder<T, R> part in parts.toList()) {
+    for (SourceLibraryBuilder<T, R> part in parts) {
       if (part == this) {
         addCompileTimeError(messagePartOfSelf, -1, noLength, fileUri);
       } else if (seenParts.add(part.fileUri)) {
-        includePart(part);
+        if (part.partOfLibrary != null &&
+            // TODO(askesc): Remove this hack when co19 fix is rolled in.
+            !part.fileUri.path.endsWith("/co19/src/Utils/expect_common.dart")) {
+          addProblem(messagePartOfTwoLibraries, -1, noLength, part.fileUri,
+              context: [
+                messagePartOfTwoLibrariesContext.withLocation(
+                    part.partOfLibrary.fileUri, -1, noLength),
+                messagePartOfTwoLibrariesContext.withLocation(
+                    this.fileUri, -1, noLength)
+              ]);
+        } else {
+          includePart(part);
+        }
       } else {
         addCompileTimeError(templatePartTwice.withArguments(part.fileUri), -1,
             noLength, fileUri);
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 31e6bfa..f3952c9 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -206,6 +206,10 @@
       DietParser parser = new DietParser(listener);
       parser.parseUnit(tokens);
       for (SourceLibraryBuilder part in library.parts) {
+        if (part.partOfLibrary != library) {
+          // Part was included in multiple libraries. Skip it here.
+          continue;
+        }
         Token tokens = await tokenize(part);
         if (tokens != null) {
           listener.uri = part.fileUri;
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 1116346..c754cc6 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -313,6 +313,8 @@
 PartOfLibraryNameMismatch/example: Fail
 PartOfSelf/analyzerCode: Fail
 PartOfSelf/example: Fail
+PartOfTwoLibraries/analyzerCode: Fail # Issue 33227
+PartOfTwoLibraries/example: Fail # Needs multiple files
 PartOfUriMismatch/analyzerCode: Fail
 PartOfUriMismatch/example: Fail
 PartOfUseUri/analyzerCode: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 7c31f2a..8a1f1f2 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1704,6 +1704,15 @@
 PartTwice:
   template: "Can't use '#uri' as a part more than once."
 
+PartOfTwoLibraries:
+  template: "A file can't be part of more than one library."
+  tip: "Try moving the shared declarations into the libraries, or into a new library."
+  severity: ERROR
+
+PartOfTwoLibrariesContext:
+  template: "Used as a part in this library."
+  severity: CONTEXT
+
 FactoryTopLevelDeclaration:
   template: "Top-level declarations can't be declared to be 'factory'."
   tip: "Try removing the keyword 'factory'."
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 3c2b597..b22bdfb 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -102,6 +102,7 @@
 parameter_initializer3_negative_test: CompileTimeError
 parameter_initializer4_negative_test: CompileTimeError
 parameter_initializer6_negative_test: CompileTimeError
+part_of_multiple_libs_test/01: MissingCompileTimeError # Issue 33227
 part_refers_to_core_library_test/01: MissingCompileTimeError # Issue 29709
 prefix_shadow_test/01: MissingCompileTimeError # Issue 33005
 private_member1_negative_test: Fail # Issue 14021
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index b6bc7b9..79b883b 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -142,6 +142,7 @@
 override_inheritance_generic_test/02: CompileTimeError
 override_inheritance_method_test/28: CompileTimeError
 override_inheritance_method_test/29: CompileTimeError
+part_of_multiple_libs_test/01: MissingCompileTimeError
 part_refers_to_core_library_test/01: Crash
 prefix_shadow_test/01: MissingCompileTimeError # Issue 33005
 regress_23089_test: MissingCompileTimeError
diff --git a/tests/language_2/part_of_multiple_libs_lib.dart b/tests/language_2/part_of_multiple_libs_lib.dart
new file mode 100644
index 0000000..7c71bcb
--- /dev/null
+++ b/tests/language_2/part_of_multiple_libs_lib.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library ambiguous_lib;
+
+part "part_of_multiple_libs_part.dart";
+
+test() {
+  foo();
+}
diff --git a/tests/language_2/part_of_multiple_libs_part.dart b/tests/language_2/part_of_multiple_libs_part.dart
new file mode 100644
index 0000000..4ac530b
--- /dev/null
+++ b/tests/language_2/part_of_multiple_libs_part.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of ambiguous_lib;
+
+bar() {}
+
+foo() {
+  bar();
+}
diff --git a/tests/language_2/part_of_multiple_libs_test.dart b/tests/language_2/part_of_multiple_libs_test.dart
new file mode 100644
index 0000000..73fd235
--- /dev/null
+++ b/tests/language_2/part_of_multiple_libs_test.dart
@@ -0,0 +1,13 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library ambiguous_lib;
+
+import 'part_of_multiple_libs_lib.dart'; //# 01: compile-time error
+
+part "part_of_multiple_libs_part.dart";
+
+main() {
+  foo();
+}