From e06738bba4fd5d76d93c274d6fc23fd1d1ce9c46 Mon Sep 17 00:00:00 2001 From: Greg Spencer Date: Mon, 12 Aug 2024 18:55:07 -0700 Subject: [PATCH] Add fake dependency on flutter_gpu for the docs (#153325) ## Description This adds a fake dependency to the docs generation for the `flutter_gpu` package so that it will be included in the docs even though Flutter itself doesn't depend on it directly. ## Related Issues - Fixes https://github.com/flutter/flutter/issues/153320 ## Tests - Adding a test to the canary files that the docs generation script looks for. (Not yet added: still draft) --- dev/tools/create_api_docs.dart | 38 ++++-- dev/tools/test/create_api_docs_test.dart | 151 +++++++++++++++++++++++ 2 files changed, 180 insertions(+), 9 deletions(-) diff --git a/dev/tools/create_api_docs.dart b/dev/tools/create_api_docs.dart index 74667b936ce..543e9df35fa 100644 --- a/dev/tools/create_api_docs.dart +++ b/dev/tools/create_api_docs.dart @@ -23,6 +23,12 @@ import 'dartdoc_checker.dart'; const String kDummyPackageName = 'Flutter'; const String kPlatformIntegrationPackageName = 'platform_integration'; +/// Additional package dependencies that we want to have in the docs, +/// but not actually depend on them. +const Map kFakeDependencies = { + 'flutter_gpu': ('flutter_gpu/gpu.dart', '\n sdk: flutter'), + }; + class PlatformDocsSection { const PlatformDocsSection({ required this.zipName, @@ -235,6 +241,12 @@ class Configurator { } } + // Add a fake references for libraries that we don't actually depend on so + // that they will be included in the docs. + for (final String package in kFakeDependencies.keys) { + yield kFakeDependencies[package]!.$1; + } + // Add a fake package for platform integration APIs. yield '$kPlatformIntegrationPackageName/android.dart'; yield '$kPlatformIntegrationPackageName/ios.dart'; @@ -252,8 +264,11 @@ class Configurator { 'environment:', " sdk: '>=3.2.0-0 <4.0.0'", 'dependencies:', - for (final String package in findPackageNames(filesystem)) ' $package:\n sdk: flutter', + for (final String package in findPackageNames(filesystem)) + ' $package:\n sdk: flutter', ' $kPlatformIntegrationPackageName: 0.0.1', + for (final String package in kFakeDependencies.keys) + ' $package: ${kFakeDependencies[package]!.$2}', 'dependency_overrides:', ' $kPlatformIntegrationPackageName:', ' path: ${docsRoot.childDirectory(kPlatformIntegrationPackageName).path}', @@ -326,14 +341,16 @@ class Configurator { if (assetsDir.existsSync()) { assetsDir.deleteSync(recursive: true); } - copyDirectorySync( - docsRoot.childDirectory('assets'), - assetsDir, - onFileCopied: (File src, File dest) { - print('Copied ${path.canonicalize(src.absolute.path)} to ${path.canonicalize(dest.absolute.path)}'); - }, - filesystem: filesystem, - ); + if (assetSource.existsSync()) { + copyDirectorySync( + assetSource, + assetsDir, + onFileCopied: (File src, File dest) { + print('Copied ${path.canonicalize(src.absolute.path)} to ${path.canonicalize(dest.absolute.path)}'); + }, + filesystem: filesystem, + ); + } } /// Generates an OpenSearch XML description that can be used to add a custom @@ -712,6 +729,9 @@ class DartdocGenerator { .childDirectory('flutter_driver') .childDirectory('FlutterDriver') .childFile('FlutterDriver.connectedTo.html'), + flutterDirectory + .childDirectory('flutter_gpu') + .childFile('flutter_gpu-library.html'), flutterDirectory.childDirectory('flutter_test').childDirectory('WidgetTester').childFile('pumpWidget.html'), flutterDirectory.childDirectory('material').childFile('Material-class.html'), flutterDirectory.childDirectory('material').childFile('Tooltip-class.html'), diff --git a/dev/tools/test/create_api_docs_test.dart b/dev/tools/test/create_api_docs_test.dart index 77c3ae4944a..520f5829ae5 100644 --- a/dev/tools/test/create_api_docs_test.dart +++ b/dev/tools/test/create_api_docs_test.dart @@ -225,6 +225,157 @@ void main() { }); }); + group('Configurator', () { + late MemoryFileSystem fs; + late FakeProcessManager fakeProcessManager; + late Directory publishRoot; + late Directory packageRoot; + late Directory docsRoot; + late File searchTemplate; + late apidocs.Configurator configurator; + late FakePlatform fakePlatform; + late apidocs.FlutterInformation flutterInformation; + + void setUpWithEnvironment(Map environment) { + fakePlatform = FakePlatform(environment: environment); + flutterInformation = apidocs.FlutterInformation( + filesystem: fs, + processManager: fakeProcessManager, + platform: fakePlatform, + ); + apidocs.FlutterInformation.instance = flutterInformation; + } + + setUp(() { + fs = MemoryFileSystem.test(); + publishRoot = fs.directory('/path/to/publish'); + packageRoot = fs.directory('/path/to/package'); + docsRoot = fs.directory('/path/to/docs'); + searchTemplate = docsRoot.childDirectory('lib').childFile('opensearch.xml'); + fs.directory('/home/user/flutter/packages').createSync(recursive: true); + fakeProcessManager = FakeProcessManager.empty(); + setUpWithEnvironment({}); + publishRoot.createSync(recursive: true); + packageRoot.createSync(recursive: true); + docsRoot.createSync(recursive: true); + final List files = [ + 'README.md', + 'analysis_options.yaml', + 'dartdoc_options.yaml', + searchTemplate.path, + publishRoot.childFile('opensearch.xml').path, + ]; + for (final String file in files) { + docsRoot.childFile(file).createSync(recursive: true); + } + searchTemplate.writeAsStringSync('{SITE_URL}'); + configurator = apidocs.Configurator( + docsRoot: docsRoot, + packageRoot: packageRoot, + publishRoot: publishRoot, + filesystem: fs, + processManager: fakeProcessManager, + platform: fakePlatform, + ); + fakeProcessManager.addCommands([ + const FakeCommand( + command: ['flutter', '--version', '--machine'], + stdout: testVersionInfo, + ), + const FakeCommand( + command: ['git', 'status', '-b', '--porcelain'], + stdout: '## $branchName', + ), + const FakeCommand( + command: ['git', 'rev-parse', 'HEAD'], + ), + const FakeCommand( + command: ['/flutter/bin/flutter', 'pub', 'global', 'list'], + ), + FakeCommand( + command: [ + '/flutter/bin/flutter', + 'pub', + 'global', + 'run', + '--enable-asserts', + 'dartdoc', + '--output', + '/path/to/publish/flutter', + '--allow-tools', + '--json', + '--validate-links', + '--link-to-source-excludes', + '/flutter/bin/cache', + '--link-to-source-root', + '/flutter', + '--link-to-source-uri-template', + 'https://github.com/flutter/flutter/blob/main/%f%#L%l%', + '--inject-html', + '--use-base-href', + '--header', + '/path/to/docs/styles.html', + '--header', + '/path/to/docs/analytics-header.html', + '--header', + '/path/to/docs/survey.html', + '--header', + '/path/to/docs/snippets.html', + '--header', + '/path/to/docs/opensearch.html', + '--footer', + '/path/to/docs/analytics-footer.html', + '--footer-text', + '/path/to/package/footer.html', + '--allow-warnings-in-packages', + // match package names + RegExp(r'^(\w+,)+(\w+)$'), + '--exclude-packages', + RegExp(r'^(\w+,)+(\w+)$'), + '--exclude', + // match dart package URIs + RegExp(r'^([\w\/:.]+,)+([\w\/:.]+)$'), + '--favicon', + '/path/to/docs/favicon.ico', + '--package-order', + 'flutter,Dart,${apidocs.kPlatformIntegrationPackageName},flutter_test,flutter_driver', + '--auto-include-dependencies', + ], + ), + ]); + }); + + test('.generateConfiguration generates pubspec.yaml', () async { + configurator.generateConfiguration(); + expect(packageRoot.childFile('pubspec.yaml').existsSync(), isTrue); + expect(packageRoot.childFile('pubspec.yaml').readAsStringSync(), contains('flutter_gpu:')); + expect(packageRoot.childFile('pubspec.yaml').readAsStringSync(), contains('dependency_overrides:')); + expect(packageRoot.childFile('pubspec.yaml').readAsStringSync(), contains('platform_integration:')); + }); + + test('.generateConfiguration generates fake lib', () async { + configurator.generateConfiguration(); + expect(packageRoot.childDirectory('lib').existsSync(), isTrue); + expect(packageRoot.childDirectory('lib').childFile('temp_doc.dart').existsSync(), isTrue); + expect(packageRoot.childDirectory('lib').childFile('temp_doc.dart').readAsStringSync(), contains('library temp_doc;')); + expect(packageRoot.childDirectory('lib').childFile('temp_doc.dart').readAsStringSync(), contains("import 'package:flutter_gpu/gpu.dart';")); + }); + + test('.generateConfiguration generates page footer', () async { + configurator.generateConfiguration(); + expect(packageRoot.childFile('footer.html').existsSync(), isTrue); + expect(packageRoot.childFile('footer.html').readAsStringSync(), contains('