Skip to content

Commit 76678f6

Browse files
authored
Support for enhanced parts (dart-lang#3892)
There isn't _much_ for dartdoc to be concerned with. Dartdoc basically must be aware of an exports foud in a part, and there might be reasons to be concerned with imports coming from a part. In particular, dartdoc used to skip resolving all part files when searching for libraries, just as an optimization. Can't do that any more. This might not be a full implementation of enhanced parts support, but it sets up the basics.
1 parent c613f42 commit 76678f6

File tree

3 files changed

+121
-8
lines changed

3 files changed

+121
-8
lines changed

lib/src/model/package_builder.dart

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,9 @@ class PubPackageBuilder implements PackageBuilder {
283283
continue;
284284
}
285285
newFiles.addFilesReferencedBy(resolvedLibrary.element);
286+
for (var unit in resolvedLibrary.units) {
287+
newFiles.addFilesReferencedBy(unit.declaredElement);
288+
}
286289
if (processedLibraries.contains(resolvedLibrary.element)) {
287290
continue;
288291
}
@@ -548,24 +551,37 @@ class DartDocResolvedLibrary {
548551
extension on Set<String> {
549552
/// Adds [element]'s path and all of its part files' paths to `this`, and
550553
/// recursively adds the paths of all imported and exported libraries.
551-
void addFilesReferencedBy(LibraryOrAugmentationElement? element) {
554+
///
555+
/// [element] must be a [LibraryElement] or [CompilationUnitElement].
556+
void addFilesReferencedBy(Element? element) {
552557
if (element == null) return;
553558

554559
var path = element.source?.fullName;
555560
if (path == null) return;
556561

557562
if (add(path)) {
558-
for (var import in element.libraryImports) {
563+
var libraryImports = switch (element) {
564+
LibraryElement(:var libraryImports) ||
565+
CompilationUnitElement(:var libraryImports) =>
566+
libraryImports,
567+
_ => const <LibraryImportElement>[],
568+
};
569+
for (var import in libraryImports) {
559570
addFilesReferencedBy(import.importedLibrary);
560571
}
561-
for (var export in element.libraryExports) {
572+
573+
var libraryExports = switch (element) {
574+
LibraryElement(:var libraryExports) ||
575+
CompilationUnitElement(:var libraryExports) =>
576+
libraryExports,
577+
_ => const <LibraryExportElement>[],
578+
};
579+
for (var export in libraryExports) {
562580
addFilesReferencedBy(export.exportedLibrary);
563581
}
564582
if (element is LibraryElement) {
565-
for (var part in element.parts
566-
.map((e) => e.uri)
567-
.whereType<DirectiveUriWithUnit>()) {
568-
add(part.source.fullName);
583+
for (var unit in element.units) {
584+
addFilesReferencedBy(unit);
569585
}
570586
}
571587
}

test/dartdoc_test_base.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ abstract class DartdocTestBase {
4343

4444
String get sdkConstraint => '>=3.6.0 <4.0.0';
4545

46-
List<String> get experiments => ['wildcard-variables'];
46+
List<String> get experiments => ['enhanced-parts', 'wildcard-variables'];
4747

4848
bool get skipUnreachableSdkLibraries => true;
4949

test/packages_test.dart

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,26 @@
55
import 'package:analyzer/file_system/file_system.dart';
66
import 'package:analyzer/file_system/memory_file_system.dart';
77
import 'package:dartdoc/src/dartdoc_options.dart';
8+
import 'package:dartdoc/src/model/class.dart';
89
import 'package:dartdoc/src/model/documentable.dart';
910
import 'package:dartdoc/src/model/kind.dart';
1011
import 'package:dartdoc/src/package_config_provider.dart';
1112
import 'package:dartdoc/src/package_meta.dart';
1213
import 'package:dartdoc/src/special_elements.dart';
1314
import 'package:test/test.dart';
15+
import 'package:test_reflective_loader/test_reflective_loader.dart';
1416

17+
import 'dartdoc_test_base.dart';
18+
import 'src/test_descriptor_utils.dart' as d;
1519
import 'src/utils.dart' as utils;
1620

1721
void main() {
22+
defineReflectiveSuite(() {
23+
defineReflectiveTests(PackagesTest);
24+
});
25+
26+
// TODO(srawlins): Migrate to test_reflective_loader tests.
27+
1828
late MemoryResourceProvider resourceProvider;
1929
late PackageMetaProvider packageMetaProvider;
2030
late FakePackageConfigProvider packageConfigProvider;
@@ -103,6 +113,8 @@ int x;
103113
projectPath, packageMetaProvider, packageConfigProvider);
104114

105115
expect(packageGraph.localPublicLibraries, hasLength(1));
116+
var library = packageGraph.libraries.named('a');
117+
expect(library.isDocumented, true);
106118
});
107119

108120
test('has private libraries', () async {
@@ -489,3 +501,88 @@ int x;
489501
});
490502
});
491503
}
504+
505+
@reflectiveTest
506+
class PackagesTest extends DartdocTestBase {
507+
@override
508+
String get libraryName => 'lib';
509+
510+
void test_exportedElements() async {
511+
var graph = await bootPackageFromFiles(
512+
[
513+
d.dir('lib', [
514+
d.file('lib.dart', "export 'src/impl.dart';"),
515+
d.dir('src', [
516+
d.file('impl.dart', 'class C {}'),
517+
]),
518+
]),
519+
],
520+
);
521+
var library = graph.libraries.named('lib');
522+
expect(library.classes.single.name, 'C');
523+
}
524+
525+
void test_exportedElements_indirectlyExported() async {
526+
var graph = await bootPackageFromFiles(
527+
[
528+
d.dir('lib', [
529+
d.file('lib.dart', "export 'src/impl.dart';"),
530+
d.dir('src', [
531+
d.file('impl.dart', "export 'impl2.dart';"),
532+
d.file('impl2.dart', 'class C {}'),
533+
]),
534+
]),
535+
],
536+
);
537+
var library = graph.libraries.named('lib');
538+
expect(library.classes.single.name, 'C');
539+
}
540+
541+
void test_exportedElements_fromPart() async {
542+
var graph = await bootPackageFromFiles(
543+
[
544+
d.dir('lib', [
545+
d.file('lib.dart', "part 'part.dart';"),
546+
d.file('part.dart', '''
547+
part of 'lib.dart';
548+
export 'src/impl.dart';
549+
'''),
550+
d.dir('src', [
551+
d.file('impl.dart', 'class C {}'),
552+
]),
553+
]),
554+
],
555+
);
556+
var library = graph.libraries.named('lib');
557+
expect(library.qualifiedName, 'lib');
558+
expect(library.classes, isNotEmpty);
559+
expect(library.classes.single,
560+
isA<Class>().having((c) => c.name, 'name', 'C'));
561+
}
562+
563+
void test_exportedElements_fromPartOfPart() async {
564+
var graph = await bootPackageFromFiles(
565+
[
566+
d.dir('lib', [
567+
d.file('lib.dart', "part 'part1.dart';"),
568+
d.file('part1.dart', '''
569+
part of 'lib.dart';
570+
part 'part2.dart';
571+
'''),
572+
d.file('part2.dart', '''
573+
part of 'part1.dart';
574+
export 'src/impl.dart';
575+
'''),
576+
d.dir('src', [
577+
d.file('impl.dart', 'class C {}'),
578+
]),
579+
]),
580+
],
581+
);
582+
var library = graph.libraries.named('lib');
583+
expect(library.qualifiedName, 'lib');
584+
expect(library.classes, isNotEmpty);
585+
expect(library.classes.single,
586+
isA<Class>().having((c) => c.name, 'name', 'C'));
587+
}
588+
}

0 commit comments

Comments
 (0)