Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for enhanced parts #3892

Merged
merged 2 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 23 additions & 7 deletions lib/src/model/package_builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -548,24 +551,37 @@ class DartDocResolvedLibrary {
extension on Set<String> {
/// 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 <LibraryImportElement>[],
};
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 <LibraryExportElement>[],
};
for (var export in libraryExports) {
addFilesReferencedBy(export.exportedLibrary);
}
if (element is LibraryElement) {
for (var part in element.parts
.map((e) => e.uri)
.whereType<DirectiveUriWithUnit>()) {
add(part.source.fullName);
for (var unit in element.units) {
addFilesReferencedBy(unit);
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion test/dartdoc_test_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ abstract class DartdocTestBase {

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

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

bool get skipUnreachableSdkLibraries => true;

Expand Down
97 changes: 97 additions & 0 deletions test/packages_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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<Class>().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<Class>().having((c) => c.name, 'name', 'C'));
}
}