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;');