Parts. Support for configurations in part directives.

Change-Id: I518205704b2670db7a9ecb0b5e99358b1a5c2ae7
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/379720
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 48e50c6..c5aea5d 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -96,7 +96,7 @@
 // TODO(scheglov): Clean up the list of implicitly analyzed files.
 class AnalysisDriver {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 379;
+  static const int DATA_VERSION = 380;
 
   /// The number of exception contexts allowed to write. Once this field is
   /// zero, we stop writing any new exception contexts in this process.
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 00cdd43..e37ee50 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -213,6 +213,18 @@
   Source? get source => null;
 }
 
+class DirectiveUris {
+  final DirectiveUri primary;
+  final List<DirectiveUri> configurations;
+  final DirectiveUri selected;
+
+  DirectiveUris({
+    required this.primary,
+    required this.configurations,
+    required this.selected,
+  });
+}
+
 /// [DirectiveUriWithUri] with URI that resolves to a [FileState].
 final class DirectiveUriWithFile extends DirectiveUriWithSource {
   final FileState file;
@@ -399,7 +411,7 @@
   List<LibraryExportState> get libraryExports {
     return _libraryExports ??=
         file.unlinked2.exports.map<LibraryExportState>((unlinked) {
-      var uris = file._buildNamespaceDirectiveUris(unlinked);
+      var uris = file._buildConfigurableDirectiveUris(unlinked);
       var selectedUri = uris.selected;
       switch (selectedUri) {
         case DirectiveUriWithFile():
@@ -475,31 +487,32 @@
   List<PartIncludeState> get partIncludes {
     return _partIncludes ??=
         file.unlinked2.parts.map<PartIncludeState>((unlinked) {
-      var uri = file._buildDirectiveUri(unlinked.uri);
-      switch (uri) {
+      var uris = file._buildConfigurableDirectiveUris(unlinked);
+      var selectedUri = uris.selected;
+      switch (selectedUri) {
         case DirectiveUriWithFile():
           return PartIncludeWithFile(
             container: this,
             unlinked: unlinked,
-            uri: uri,
+            uri: selectedUri,
           );
         case DirectiveUriWithUri():
           return PartIncludeWithUri(
             container: this,
             unlinked: unlinked,
-            uri: uri,
+            uri: selectedUri,
           );
         case DirectiveUriWithString():
           return PartIncludeWithUriStr(
             container: this,
             unlinked: unlinked,
-            uri: uri,
+            uri: selectedUri,
           );
         case DirectiveUriWithoutString():
           return PartIncludeState(
             container: this,
             unlinked: unlinked,
-            uri: uri,
+            uri: selectedUri,
           );
       }
     }).toFixedList();
@@ -607,7 +620,7 @@
   LibraryImportState _buildLibraryImportState(
     UnlinkedLibraryImportDirective directive,
   ) {
-    var uris = file._buildNamespaceDirectiveUris(directive);
+    var uris = file._buildConfigurableDirectiveUris(directive);
     var selectedUri = uris.selected;
     switch (selectedUri) {
       case DirectiveUriWithFile():
@@ -957,6 +970,32 @@
     return '$uri = $path';
   }
 
+  // TODO(scheglov): move to _fsState?
+  DirectiveUris _buildConfigurableDirectiveUris(
+    UnlinkedConfigurableUriDirective directive,
+  ) {
+    var primaryUri = _buildDirectiveUri(directive.uri);
+
+    DirectiveUri? selectedConfigurationUri;
+    var configurationUris = directive.configurations.map((configuration) {
+      var configurationUri = _buildDirectiveUri(configuration.uri);
+      // Maybe select this URI.
+      var name = configuration.name;
+      var value = configuration.valueOrTrue;
+      if (_fsState._declaredVariables.get(name) == value) {
+        selectedConfigurationUri ??= configurationUri;
+      }
+      // Include it anyway.
+      return configurationUri;
+    }).toFixedList();
+
+    return DirectiveUris(
+      primary: primaryUri,
+      configurations: configurationUris,
+      selected: selectedConfigurationUri ?? primaryUri,
+    );
+  }
+
   DirectiveUri _buildDirectiveUri(String? relativeUriStr) {
     if (relativeUriStr == null) {
       return const DirectiveUriWithoutString();
@@ -992,32 +1031,6 @@
     }
   }
 
-  // TODO(scheglov): move to _fsState?
-  NamespaceDirectiveUris _buildNamespaceDirectiveUris(
-    UnlinkedNamespaceDirective directive,
-  ) {
-    var primaryUri = _buildDirectiveUri(directive.uri);
-
-    DirectiveUri? selectedConfigurationUri;
-    var configurationUris = directive.configurations.map((configuration) {
-      var configurationUri = _buildDirectiveUri(configuration.uri);
-      // Maybe select this URI.
-      var name = configuration.name;
-      var value = configuration.valueOrTrue;
-      if (_fsState._declaredVariables.get(name) == value) {
-        selectedConfigurationUri ??= configurationUri;
-      }
-      // Include it anyway.
-      return configurationUri;
-    }).toFixedList();
-
-    return NamespaceDirectiveUris(
-      primary: primaryUri,
-      configurations: configurationUris,
-      selected: selectedConfigurationUri ?? primaryUri,
-    );
-  }
-
   /// Return the [FileState] for the given [relativeUriStr], or `null` if the
   /// URI cannot be parsed, cannot correspond any file, etc.
   UriResolution? _fileForRelativeUri(String? relativeUriStr) {
@@ -1277,11 +1290,8 @@
           name: directive.name2?.name,
         );
       } else if (directive is PartDirective) {
-        parts.add(
-          UnlinkedPartDirective(
-            uri: directive.uri.stringValue,
-          ),
-        );
+        var unlinked = _serializePart(directive);
+        parts.add(unlinked);
       } else if (directive is PartOfDirective) {
         var libraryName = directive.libraryName;
         var uri = directive.uri;
@@ -1465,6 +1475,13 @@
       prefix: unlinkedPrefix,
     );
   }
+
+  static UnlinkedPartDirective _serializePart(PartDirective node) {
+    return UnlinkedPartDirective(
+      configurations: _serializeConfigurations(node.configurations),
+      uri: node.uri.stringValue,
+    );
+  }
 }
 
 enum FileStateRefreshResult {
@@ -1989,7 +2006,7 @@
 final class LibraryExportState<U extends DirectiveUri> extends DirectiveState {
   final UnlinkedLibraryExportDirective unlinked;
   final U selectedUri;
-  final NamespaceDirectiveUris uris;
+  final DirectiveUris uris;
 
   LibraryExportState({
     required super.container,
@@ -2338,7 +2355,7 @@
 final class LibraryImportState<U extends DirectiveUri> extends DirectiveState {
   final UnlinkedLibraryImportDirective unlinked;
   final U selectedUri;
-  final NamespaceDirectiveUris uris;
+  final DirectiveUris uris;
 
   LibraryImportState({
     required super.container,
@@ -2453,18 +2470,6 @@
   });
 }
 
-class NamespaceDirectiveUris {
-  final DirectiveUri primary;
-  final List<DirectiveUri> configurations;
-  final DirectiveUri selected;
-
-  NamespaceDirectiveUris({
-    required this.primary,
-    required this.configurations,
-    required this.selected,
-  });
-}
-
 class ParsedFileState {
   final String code;
   final CompilationUnitImpl unit;
diff --git a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
index 115d64e..a3c58a8 100644
--- a/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/unlinked_data.dart
@@ -148,6 +148,16 @@
   }
 }
 
+abstract class UnlinkedConfigurableUriDirective {
+  final List<UnlinkedNamespaceDirectiveConfiguration> configurations;
+  final String? uri;
+
+  UnlinkedConfigurableUriDirective({
+    required this.configurations,
+    required this.uri,
+  });
+}
+
 class UnlinkedLibraryAugmentationDirective {
   final int augmentKeywordOffset;
   final int libraryKeywordOffset;
@@ -337,15 +347,14 @@
   }
 }
 
-abstract class UnlinkedNamespaceDirective {
+abstract class UnlinkedNamespaceDirective
+    extends UnlinkedConfigurableUriDirective {
   final List<UnlinkedCombinator> combinators;
-  final List<UnlinkedNamespaceDirectiveConfiguration> configurations;
-  final String? uri;
 
   UnlinkedNamespaceDirective({
     required this.combinators,
-    required this.configurations,
-    required this.uri,
+    required super.configurations,
+    required super.uri,
   });
 }
 
@@ -392,22 +401,28 @@
   }
 }
 
-class UnlinkedPartDirective {
-  final String? uri;
-
+class UnlinkedPartDirective extends UnlinkedConfigurableUriDirective {
   UnlinkedPartDirective({
-    required this.uri,
+    required super.configurations,
+    required super.uri,
   });
 
-  factory UnlinkedPartDirective.read(
-    SummaryDataReader reader,
-  ) {
+  factory UnlinkedPartDirective.read(SummaryDataReader reader) {
     return UnlinkedPartDirective(
+      configurations: reader.readTypedList(
+        () => UnlinkedNamespaceDirectiveConfiguration.read(reader),
+      ),
       uri: reader.readOptionalStringUtf8(),
     );
   }
 
   void write(BufferedSink sink) {
+    sink.writeList<UnlinkedNamespaceDirectiveConfiguration>(
+      configurations,
+      (x) {
+        x.write(sink);
+      },
+    );
     sink.writeOptionalStringUtf8(uri);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 7008c9f..93a8633 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -2911,6 +2911,227 @@
 ''');
   }
 
+  test_newFile_library_parts_configurations_useDefault() {
+    declaredVariables = {
+      'dart.library.io': 'false',
+    };
+
+    newFile('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile(testFile.path, r'''
+part 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+''');
+
+    fileStateFor(testFile);
+
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/foo.dart
+    uri: package:test/foo.dart
+    current
+      id: file_0
+      kind: partOfUriKnown_0
+        uriFile: file_3
+        library: library_3
+      referencingFiles: file_3
+      unlinkedKey: k00
+  /home/test/lib/foo_html.dart
+    uri: package:test/foo_html.dart
+    current
+      id: file_1
+      kind: partOfUriKnown_1
+        uriFile: file_3
+      unlinkedKey: k00
+  /home/test/lib/foo_io.dart
+    uri: package:test/foo_io.dart
+    current
+      id: file_2
+      kind: partOfUriKnown_2
+        uriFile: file_3
+      unlinkedKey: k00
+  /home/test/lib/test.dart
+    uri: package:test/test.dart
+    current
+      id: file_3
+      kind: library_3
+        libraryImports
+          library_4 dart:core synthetic
+        partIncludes
+          partOfUriKnown_0
+        fileKinds: library_3 partOfUriKnown_0
+        cycle_0
+          dependencies: dart:core
+          libraries: library_3
+          apiSignature_0
+      unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+  }
+
+  test_newFile_library_parts_configurations_useFirst() {
+    declaredVariables = {
+      'dart.library.io': 'true',
+      'dart.library.html': 'false',
+    };
+
+    newFile('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile(testFile.path, r'''
+part 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+''');
+
+    fileStateFor(testFile);
+
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/foo.dart
+    uri: package:test/foo.dart
+    current
+      id: file_0
+      kind: partOfUriKnown_0
+        uriFile: file_3
+      unlinkedKey: k00
+  /home/test/lib/foo_html.dart
+    uri: package:test/foo_html.dart
+    current
+      id: file_1
+      kind: partOfUriKnown_1
+        uriFile: file_3
+      unlinkedKey: k00
+  /home/test/lib/foo_io.dart
+    uri: package:test/foo_io.dart
+    current
+      id: file_2
+      kind: partOfUriKnown_2
+        uriFile: file_3
+        library: library_3
+      referencingFiles: file_3
+      unlinkedKey: k00
+  /home/test/lib/test.dart
+    uri: package:test/test.dart
+    current
+      id: file_3
+      kind: library_3
+        libraryImports
+          library_4 dart:core synthetic
+        partIncludes
+          partOfUriKnown_2
+        fileKinds: library_3 partOfUriKnown_2
+        cycle_0
+          dependencies: dart:core
+          libraries: library_3
+          apiSignature_0
+      unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+  }
+
+  test_newFile_library_parts_configurations_useSecond() {
+    declaredVariables = {
+      'dart.library.io': 'false',
+      'dart.library.html': 'true',
+    };
+
+    newFile('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    newFile(testFile.path, r'''
+part 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+''');
+
+    fileStateFor(testFile);
+
+    assertDriverStateString(testFile, r'''
+files
+  /home/test/lib/foo.dart
+    uri: package:test/foo.dart
+    current
+      id: file_0
+      kind: partOfUriKnown_0
+        uriFile: file_3
+      unlinkedKey: k00
+  /home/test/lib/foo_html.dart
+    uri: package:test/foo_html.dart
+    current
+      id: file_1
+      kind: partOfUriKnown_1
+        uriFile: file_3
+        library: library_3
+      referencingFiles: file_3
+      unlinkedKey: k00
+  /home/test/lib/foo_io.dart
+    uri: package:test/foo_io.dart
+    current
+      id: file_2
+      kind: partOfUriKnown_2
+        uriFile: file_3
+      unlinkedKey: k00
+  /home/test/lib/test.dart
+    uri: package:test/test.dart
+    current
+      id: file_3
+      kind: library_3
+        libraryImports
+          library_4 dart:core synthetic
+        partIncludes
+          partOfUriKnown_1
+        fileKinds: library_3 partOfUriKnown_1
+        cycle_0
+          dependencies: dart:core
+          libraries: library_3
+          apiSignature_0
+      unlinkedKey: k01
+libraryCycles
+elementFactory
+''');
+  }
+
   test_newFile_library_parts_emptyUri() {
     var a = newFile('$testPackageLibPath/a.dart', r'''
 part '';
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index c75d4f6..d12e455 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -31,7 +31,7 @@
   );
   var elementPrinter = ElementPrinter(
     sink: sink,
-    configuration: ElementPrinterConfiguration(),
+    configuration: configuration.elementPrinterConfiguration,
   );
   var writer = _ElementWriter(
     sink: sink,
@@ -51,6 +51,8 @@
 }
 
 class ElementTextConfiguration {
+  ElementPrinterConfiguration elementPrinterConfiguration =
+      ElementPrinterConfiguration();
   bool Function(Object) filter;
   List<Pattern>? macroDiagnosticMessagePatterns;
   bool withAllSupertypes = false;
diff --git a/pkg/analyzer/test/src/summary/elements/part_include_test.dart b/pkg/analyzer/test/src/summary/elements/part_include_test.dart
index 7d8164e..fb2a593 100644
--- a/pkg/analyzer/test/src/summary/elements/part_include_test.dart
+++ b/pkg/analyzer/test/src/summary/elements/part_include_test.dart
@@ -16,6 +16,350 @@
 }
 
 abstract class PartIncludeElementTest extends ElementsBaseTest {
+  test_configurations_useDefault() async {
+    declaredVariables = {
+      'dart.library.io': 'false',
+    };
+
+    addSource('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    var library = await buildLibrary(r'''
+part 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+
+class B extends A {}
+''');
+
+    configuration
+      ..elementPrinterConfiguration.withInterfaceTypeElements = true
+      ..withConstructors = false;
+    checkElementText(library, r'''
+library
+  reference: <testLibrary>
+  definingUnit: <testLibraryFragment>
+  parts
+    part_0
+  units
+    <testLibraryFragment>
+      enclosingElement: <testLibrary>
+      parts
+        part_0
+          uri: package:test/foo.dart
+          enclosingElement: <testLibrary>
+          enclosingElement3: <testLibraryFragment>
+          unit: <testLibrary>::@fragment::package:test/foo.dart
+      classes
+        class B @102
+          reference: <testLibraryFragment>::@class::B
+          enclosingElement: <testLibraryFragment>
+          supertype: A
+            element: <testLibrary>::@fragment::package:test/foo.dart::@class::A
+    <testLibrary>::@fragment::package:test/foo.dart
+      enclosingElement: <testLibrary>
+      enclosingElement3: <testLibraryFragment>
+      classes
+        class A @27
+          reference: <testLibrary>::@fragment::package:test/foo.dart::@class::A
+          enclosingElement: <testLibrary>::@fragment::package:test/foo.dart
+----------------------------------------
+library
+  reference: <testLibrary>
+  fragments
+    <testLibraryFragment>
+    <testLibrary>::@fragment::package:test/foo.dart
+''');
+  }
+
+  test_configurations_useFirst() async {
+    declaredVariables = {
+      'dart.library.io': 'true',
+      'dart.library.html': 'true',
+    };
+
+    addSource('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    var library = await buildLibrary(r'''
+part 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+
+class B extends A {}
+''');
+
+    configuration
+      ..elementPrinterConfiguration.withInterfaceTypeElements = true
+      ..withConstructors = false;
+    checkElementText(library, r'''
+library
+  reference: <testLibrary>
+  definingUnit: <testLibraryFragment>
+  parts
+    part_0
+  units
+    <testLibraryFragment>
+      enclosingElement: <testLibrary>
+      parts
+        part_0
+          uri: package:test/foo_io.dart
+          enclosingElement: <testLibrary>
+          enclosingElement3: <testLibraryFragment>
+          unit: <testLibrary>::@fragment::package:test/foo_io.dart
+      classes
+        class B @102
+          reference: <testLibraryFragment>::@class::B
+          enclosingElement: <testLibraryFragment>
+          supertype: A
+            element: <testLibrary>::@fragment::package:test/foo_io.dart::@class::A
+    <testLibrary>::@fragment::package:test/foo_io.dart
+      enclosingElement: <testLibrary>
+      enclosingElement3: <testLibraryFragment>
+      classes
+        class A @27
+          reference: <testLibrary>::@fragment::package:test/foo_io.dart::@class::A
+          enclosingElement: <testLibrary>::@fragment::package:test/foo_io.dart
+----------------------------------------
+library
+  reference: <testLibrary>
+  fragments
+    <testLibraryFragment>
+    <testLibrary>::@fragment::package:test/foo_io.dart
+''');
+  }
+
+  test_configurations_useFirst_eqTrue() async {
+    declaredVariables = {
+      'dart.library.io': 'true',
+      'dart.library.html': 'true',
+    };
+
+    addSource('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    var library = await buildLibrary(r'''
+part 'foo.dart'
+  if (dart.library.io == 'true') 'foo_io.dart'
+  if (dart.library.html == 'true') 'foo_html.dart';
+
+class B extends A {}
+''');
+
+    configuration
+      ..elementPrinterConfiguration.withInterfaceTypeElements = true
+      ..withConstructors = false;
+    checkElementText(library, r'''
+library
+  reference: <testLibrary>
+  definingUnit: <testLibraryFragment>
+  parts
+    part_0
+  units
+    <testLibraryFragment>
+      enclosingElement: <testLibrary>
+      parts
+        part_0
+          uri: package:test/foo_io.dart
+          enclosingElement: <testLibrary>
+          enclosingElement3: <testLibraryFragment>
+          unit: <testLibrary>::@fragment::package:test/foo_io.dart
+      classes
+        class B @122
+          reference: <testLibraryFragment>::@class::B
+          enclosingElement: <testLibraryFragment>
+          supertype: A
+            element: <testLibrary>::@fragment::package:test/foo_io.dart::@class::A
+    <testLibrary>::@fragment::package:test/foo_io.dart
+      enclosingElement: <testLibrary>
+      enclosingElement3: <testLibraryFragment>
+      classes
+        class A @27
+          reference: <testLibrary>::@fragment::package:test/foo_io.dart::@class::A
+          enclosingElement: <testLibrary>::@fragment::package:test/foo_io.dart
+----------------------------------------
+library
+  reference: <testLibrary>
+  fragments
+    <testLibraryFragment>
+    <testLibrary>::@fragment::package:test/foo_io.dart
+''');
+  }
+
+  test_configurations_useSecond() async {
+    declaredVariables = {
+      'dart.library.io': 'false',
+      'dart.library.html': 'true',
+    };
+
+    addSource('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    var library = await buildLibrary(r'''
+part 'foo.dart'
+  if (dart.library.io) 'foo_io.dart'
+  if (dart.library.html) 'foo_html.dart';
+
+class B extends A {}
+''');
+
+    configuration
+      ..elementPrinterConfiguration.withInterfaceTypeElements = true
+      ..withConstructors = false;
+    checkElementText(library, r'''
+library
+  reference: <testLibrary>
+  definingUnit: <testLibraryFragment>
+  parts
+    part_0
+  units
+    <testLibraryFragment>
+      enclosingElement: <testLibrary>
+      parts
+        part_0
+          uri: package:test/foo_html.dart
+          enclosingElement: <testLibrary>
+          enclosingElement3: <testLibraryFragment>
+          unit: <testLibrary>::@fragment::package:test/foo_html.dart
+      classes
+        class B @102
+          reference: <testLibraryFragment>::@class::B
+          enclosingElement: <testLibraryFragment>
+          supertype: A
+            element: <testLibrary>::@fragment::package:test/foo_html.dart::@class::A
+    <testLibrary>::@fragment::package:test/foo_html.dart
+      enclosingElement: <testLibrary>
+      enclosingElement3: <testLibraryFragment>
+      classes
+        class A @27
+          reference: <testLibrary>::@fragment::package:test/foo_html.dart::@class::A
+          enclosingElement: <testLibrary>::@fragment::package:test/foo_html.dart
+----------------------------------------
+library
+  reference: <testLibrary>
+  fragments
+    <testLibraryFragment>
+    <testLibrary>::@fragment::package:test/foo_html.dart
+''');
+  }
+
+  test_configurations_useSecond_eqTrue() async {
+    declaredVariables = {
+      'dart.library.io': 'false',
+      'dart.library.html': 'true',
+    };
+
+    addSource('$testPackageLibPath/foo.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_io.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    addSource('$testPackageLibPath/foo_html.dart', r'''
+part of 'test.dart';
+class A {}
+''');
+
+    var library = await buildLibrary(r'''
+part 'foo.dart'
+  if (dart.library.io == 'true') 'foo_io.dart'
+  if (dart.library.html == 'true') 'foo_html.dart';
+
+class B extends A {}
+''');
+
+    configuration
+      ..elementPrinterConfiguration.withInterfaceTypeElements = true
+      ..withConstructors = false;
+    checkElementText(library, r'''
+library
+  reference: <testLibrary>
+  definingUnit: <testLibraryFragment>
+  parts
+    part_0
+  units
+    <testLibraryFragment>
+      enclosingElement: <testLibrary>
+      parts
+        part_0
+          uri: package:test/foo_html.dart
+          enclosingElement: <testLibrary>
+          enclosingElement3: <testLibraryFragment>
+          unit: <testLibrary>::@fragment::package:test/foo_html.dart
+      classes
+        class B @122
+          reference: <testLibraryFragment>::@class::B
+          enclosingElement: <testLibraryFragment>
+          supertype: A
+            element: <testLibrary>::@fragment::package:test/foo_html.dart::@class::A
+    <testLibrary>::@fragment::package:test/foo_html.dart
+      enclosingElement: <testLibrary>
+      enclosingElement3: <testLibraryFragment>
+      classes
+        class A @27
+          reference: <testLibrary>::@fragment::package:test/foo_html.dart::@class::A
+          enclosingElement: <testLibrary>::@fragment::package:test/foo_html.dart
+----------------------------------------
+library
+  reference: <testLibrary>
+  fragments
+    <testLibraryFragment>
+    <testLibrary>::@fragment::package:test/foo_html.dart
+''');
+  }
+
   test_library_parts() async {
     addSource('$testPackageLibPath/a.dart', 'part of my.lib;');
     addSource('$testPackageLibPath/b.dart', 'part of my.lib;');