diff --git a/lib/src/model/package_builder.dart b/lib/src/model/package_builder.dart index 1631382a62..e6fe631550 100644 --- a/lib/src/model/package_builder.dart +++ b/lib/src/model/package_builder.dart @@ -283,6 +283,9 @@ class PubPackageBuilder implements PackageBuilder { continue; } newFiles.addFilesReferencedBy(resolvedLibrary.element); + for (var unit in resolvedLibrary.units) { + newFiles.addFilesReferencedBy(unit.declaredElement); + } if (processedLibraries.contains(resolvedLibrary.element)) { continue; } @@ -548,24 +551,37 @@ class DartDocResolvedLibrary { extension on Set { /// Adds [element]'s path and all of its part files' paths to `this`, and /// recursively adds the paths of all imported and exported libraries. - void addFilesReferencedBy(LibraryOrAugmentationElement? element) { + /// + /// [element] must be a [LibraryElement] or [CompilationUnitElement]. + void addFilesReferencedBy(Element? element) { if (element == null) return; var path = element.source?.fullName; if (path == null) return; if (add(path)) { - for (var import in element.libraryImports) { + var libraryImports = switch (element) { + LibraryElement(:var libraryImports) || + CompilationUnitElement(:var libraryImports) => + libraryImports, + _ => const [], + }; + for (var import in libraryImports) { addFilesReferencedBy(import.importedLibrary); } - for (var export in element.libraryExports) { + + var libraryExports = switch (element) { + LibraryElement(:var libraryExports) || + CompilationUnitElement(:var libraryExports) => + libraryExports, + _ => const [], + }; + for (var export in libraryExports) { addFilesReferencedBy(export.exportedLibrary); } if (element is LibraryElement) { - for (var part in element.parts - .map((e) => e.uri) - .whereType()) { - add(part.source.fullName); + for (var unit in element.units) { + addFilesReferencedBy(unit); } } } diff --git a/test/dartdoc_test_base.dart b/test/dartdoc_test_base.dart index 15b2af7786..606a1fb78b 100644 --- a/test/dartdoc_test_base.dart +++ b/test/dartdoc_test_base.dart @@ -43,7 +43,7 @@ abstract class DartdocTestBase { String get sdkConstraint => '>=3.6.0 <4.0.0'; - List get experiments => ['wildcard-variables']; + List get experiments => ['enhanced-parts', 'wildcard-variables']; bool get skipUnreachableSdkLibraries => true; diff --git a/test/packages_test.dart b/test/packages_test.dart index 4961ae0545..60db22a1b7 100644 --- a/test/packages_test.dart +++ b/test/packages_test.dart @@ -5,16 +5,26 @@ import 'package:analyzer/file_system/file_system.dart'; import 'package:analyzer/file_system/memory_file_system.dart'; import 'package:dartdoc/src/dartdoc_options.dart'; +import 'package:dartdoc/src/model/class.dart'; import 'package:dartdoc/src/model/documentable.dart'; import 'package:dartdoc/src/model/kind.dart'; import 'package:dartdoc/src/package_config_provider.dart'; import 'package:dartdoc/src/package_meta.dart'; import 'package:dartdoc/src/special_elements.dart'; import 'package:test/test.dart'; +import 'package:test_reflective_loader/test_reflective_loader.dart'; +import 'dartdoc_test_base.dart'; +import 'src/test_descriptor_utils.dart' as d; import 'src/utils.dart' as utils; void main() { + defineReflectiveSuite(() { + defineReflectiveTests(PackagesTest); + }); + + // TODO(srawlins): Migrate to test_reflective_loader tests. + late MemoryResourceProvider resourceProvider; late PackageMetaProvider packageMetaProvider; late FakePackageConfigProvider packageConfigProvider; @@ -103,6 +113,8 @@ int x; projectPath, packageMetaProvider, packageConfigProvider); expect(packageGraph.localPublicLibraries, hasLength(1)); + var library = packageGraph.libraries.named('a'); + expect(library.isDocumented, true); }); test('has private libraries', () async { @@ -489,3 +501,88 @@ int x; }); }); } + +@reflectiveTest +class PackagesTest extends DartdocTestBase { + @override + String get libraryName => 'lib'; + + void test_exportedElements() async { + var graph = await bootPackageFromFiles( + [ + d.dir('lib', [ + d.file('lib.dart', "export 'src/impl.dart';"), + d.dir('src', [ + d.file('impl.dart', 'class C {}'), + ]), + ]), + ], + ); + var library = graph.libraries.named('lib'); + expect(library.classes.single.name, 'C'); + } + + void test_exportedElements_indirectlyExported() async { + var graph = await bootPackageFromFiles( + [ + d.dir('lib', [ + d.file('lib.dart', "export 'src/impl.dart';"), + d.dir('src', [ + d.file('impl.dart', "export 'impl2.dart';"), + d.file('impl2.dart', 'class C {}'), + ]), + ]), + ], + ); + var library = graph.libraries.named('lib'); + expect(library.classes.single.name, 'C'); + } + + void test_exportedElements_fromPart() async { + var graph = await bootPackageFromFiles( + [ + d.dir('lib', [ + d.file('lib.dart', "part 'part.dart';"), + d.file('part.dart', ''' +part of 'lib.dart'; +export 'src/impl.dart'; +'''), + d.dir('src', [ + d.file('impl.dart', 'class C {}'), + ]), + ]), + ], + ); + var library = graph.libraries.named('lib'); + expect(library.qualifiedName, 'lib'); + expect(library.classes, isNotEmpty); + expect(library.classes.single, + isA().having((c) => c.name, 'name', 'C')); + } + + void test_exportedElements_fromPartOfPart() async { + var graph = await bootPackageFromFiles( + [ + d.dir('lib', [ + d.file('lib.dart', "part 'part1.dart';"), + d.file('part1.dart', ''' +part of 'lib.dart'; +part 'part2.dart'; +'''), + d.file('part2.dart', ''' +part of 'part1.dart'; +export 'src/impl.dart'; +'''), + d.dir('src', [ + d.file('impl.dart', 'class C {}'), + ]), + ]), + ], + ); + var library = graph.libraries.named('lib'); + expect(library.qualifiedName, 'lib'); + expect(library.classes, isNotEmpty); + expect(library.classes.single, + isA().having((c) => c.name, 'name', 'C')); + } +}