Clean up the DevTools extensions `example/README.md` and `README.md` files (#7237)
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index cca4832..98787fb 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -68,7 +68,8 @@ * Fixed an issue with not detecting extensions for test files in subdirectories. - [#7174](https://github.com/flutter/devtools/pull/7174) -* Add an example of creating an extension for a pure Dart package. - [#7196](https://github.com/flutter/devtools/pull/7196) +* Added an example of creating an extension for a pure Dart package. - [#7196](https://github.com/flutter/devtools/pull/7196) +* Updated the `example/README.md` with more complete documentation. - [#7237](https://github.com/flutter/devtools/pull/7237) ## Full commit history
diff --git a/packages/devtools_extensions/CHANGELOG.md b/packages/devtools_extensions/CHANGELOG.md index c200fc9..b5be606 100644 --- a/packages/devtools_extensions/CHANGELOG.md +++ b/packages/devtools_extensions/CHANGELOG.md
@@ -3,6 +3,7 @@ * Bump `package:vm_service` dependency to ^14.0.0. * Refactor `example` directory to support more package examples. * Add an example of providing an extension from a pure Dart package. +* Update the `example/README.md`. ## 0.0.13 * Bump `package:web` to `^0.4.1`.
diff --git a/packages/devtools_extensions/README.md b/packages/devtools_extensions/README.md index e587103..578f2c4 100644 --- a/packages/devtools_extensions/README.md +++ b/packages/devtools_extensions/README.md
@@ -234,7 +234,8 @@ dart run devtools_extensions build_and_copy --source=. --dest=../foo/extension/devtools ``` -Then publish your package. +Then publish your package. When running `pub publish`, you will see a warning if you +do not have the `config.yaml` file and a non-empty `build` directory as required. ### What if I don't want the `extension/devtools/build/` contents checked into source control?
diff --git a/packages/devtools_extensions/example/README.md b/packages/devtools_extensions/example/README.md index 398a49f..8f0e1a1 100644 --- a/packages/devtools_extensions/example/README.md +++ b/packages/devtools_extensions/example/README.md
@@ -1,18 +1,78 @@ -# Example DevTools Extension +# DevTools extension examples +This directory contains end-to-end examples of DevTools extensions. Each +end-to-end example is made up of three components: +1. **Parent package**: Dart package that provides the extension +2. **DevTools extension**: the tool itself +3. **End-user application**: the app that the extension is used on -This is an end-to-end example of a DevTools extension, including -- the parent `package:foo` that provides the DevTools extension to end-user -applications (`foo/packages/foo`) -- the end-user application (`app_that_uses_foo`) that depends on `package:foo`, -which will trigger a load of the `package:foo` DevTools extension when debugging -this app with DevTools -- the `package:foo` DevTools extension (`foo/packages/foo_devtools_extension`), -which is a Flutter web app that will be embedded in DevTools when debugging an -app the uses `package:foo` +## Parent package +This is the Dart package that provides a DevTools extension for end-user +applications to use in DevTools. There are multiple extension-providing pacakges +in the `example` directory. -This example will show you how to: -1. Structure your package for optimal extension development and publishing +- `package:foo` from `packages_with_extensions/foo/packages/foo`: a package for Flutter apps + +- `package:dart_foo` from `packages_with_extensions/dart_foo/packages/dart_foo`: a +pure Dart package for Dart or Flutter apps + +<!-- TODO(kenz): build this example. --> +<!-- - `package:standalone_tool` from `packages_with_extensions/dart_foo/packages/stanalone_tool`, which is a package that is strictly meant to provide a tool +as a DevTools extension. This is different from the other packages in that it +is not an extension shipped with an existing Dart package. It is a package +published solely to provide a DevTools extension. --> + +<!-- TODO(kenz): build this example, or pull in Khan's extension. --> +<!-- - `package:gemini_ai_tool` from `packages_with_extensions/dart_foo/packages/gemini_ai_tool`, which is a standalone tool (like `package:standalone_tool`) +that provides an example of using the Gemini SDK to build an AI powered tool +as a DevTools extension. --> + +## DevTools extension + +These are Flutter web apps that will be embedded in DevTools when connected to an app +that depends on the [parent package](#parent-package). + +- `packages_with_extensions/foo/packages/foo_devtools_extension`: this +is the Flutter web app whose built assets are included in `package:foo`'s +`extension/devtools/build` directory. + +- `packages_with_extensions/dart_foo/packages/dart_foo_devtools_extension`: this +is the Flutter web app whose built assets are included in `package:dart_foo`'s +`extension/devtools/build` directory. + +## End-user application + +These are the applications that depend on the [parent package](#parent-package) and +can connect to the [DevTools extension](#devtools-extension) provided by the parent package. + +### `app_that_uses_foo` + +This Flutter app depends on `package:foo` and `package:dart_foo`. When debugging +`app_that_uses_foo`, or one if its `bin/` or `test/` libraries, the provided +DevTools extensions will load in their own tab in DevTools. + +- `flutter run` the `app_that_uses_foo` app and open DevTools to see both the +`package:foo` and `package:dart_foo` extensions in DevTools connected to a +Flutter app. + +- Run `dart run --observe bin/script.dart` and open DevTools to see the +`package_dart_foo` extension in DevTools connected to a Dart CLI app. + +<!-- TODO(kenz): uncomment once https://github.com/flutter/devtools/issues/7183 is resolved. --> +<!-- - Run `dart test test/nested/simple_test.dart --pause-after-load` and open +DevTools to see the `package:dart_foo` extension connected to a Dart test. + +- Run `flutter test test/app_that_uses_foo_test.dart --start-paused` and open +DevTools to see both the `package:foo` and `package:dart_foo` extensions +connected to a Flutter test. --> + +## Learn how to structure your Dart package + +The examples will show you how to structure your package for optimal extension +development and publishing. + +1. If you are adding a DevTools extension to an existing Dart package, this is +the recommended structure: ``` foo/ # formerly the repository root of your pub package packages/ @@ -20,27 +80,60 @@ extension/ devtools/ build/ - ... # pre-compiled output of foo_devtools_extension + ... # pre-compiled build output of foo_devtools_extension config.yaml foo_devtools_extension/ # source code for your extension ``` -2. Configure your extension using the `foo/extension/devtools/config.yaml` file - ```yaml - name: foo - issueTracker: <link_to_your_issue_tracker.com> - version: 0.0.1 - materialIconCodePoint: '0xe0b1' + `package:foo` and `package:dart_foo` provide an example of this structure. + +2. If you are creating a DevTools extension as a standalone package, this is +the recommended structure: ``` -3. Use `package:devtools_extensions` and `package:devtools_app_shared` to -develop your DevTools extension (see source code under `foo_devtools_extension`). -4. Ship your extension with your pub package by including the pre-built assets -in the `foo/extension/devtools/build` directory. - - For this example, the pre-built assets for `foo_devtools_extension` were added - to `foo/extension/devtools/build` by running the following command from the - `foo_devtools_extension/` directory: - ```sh - flutter pub get && - dart run devtools_extensions build_and_copy \ - --source=. \ - --dest=../foo/extension/devtools - ``` + standalone_tool/ # your new pub package + extension/ + devtools/ + build/ + ... # pre-compiled build output of standalone_tool + config.yaml + lib/ # source code for your extension + ``` + <!-- TODO(kenz): uncomment once these examples are provided. --> + <!-- `package:standalone_tool` and `package:gemini_ai_tool` provide an example of this structure. --> + +The pre-compiled build output included in the example packages' +`extension/devtools/build` directories were included using the `build_and_copy` +command provided by `package:devtools_extensions`. + - For example, `package:foo`'s `extension/devtools/build` directory was populated + by running the following command from the `foo_devtools_extension/` directory: + + ```sh + flutter pub get && + dart run devtools_extensions build_and_copy \ + --source=. \ + --dest=../foo/extension/devtools + ``` +## Learn how to configure your extension's `config.yaml` file + +In these examples, you will also learn how to properly configure your extension's +`config.yaml` file. DevTools reads this file in order to embed your extension in its +own tab. This file must be configured as shown. + +```yaml +name: foo +issueTracker: <link_to_your_issue_tracker.com> +version: 0.0.1 +materialIconCodePoint: '0xe0b1' +``` + +For the most up-to-date documentation on the `config.yaml` spec, see +[extension_config_spec.md](https://github.com/flutter/devtools/blob/master/packages/devtools_extensions/extension_config_spec.md) + +## Learn how to use shared packages from DevTools + +To learn how to use the shared packages from Devtools (`package:devtools_extensions` +and `package:devtools_app_shared`), see the source for the `package:foo` extension. + +`packages_with_extensions/foo/packages/foo_devtools_extension` provides in-depth +examples of how to do things like interact with the connected app's VM service, +read / write to the user's project files over the Dart Tooling Daemon, interact +with the DevTools extension framework APIs, etc.
diff --git a/packages/devtools_extensions/example/app_that_uses_foo/lib/main.dart b/packages/devtools_extensions/example/app_that_uses_foo/lib/main.dart index a5bc3cb..5b10845 100644 --- a/packages/devtools_extensions/example/app_that_uses_foo/lib/main.dart +++ b/packages/devtools_extensions/example/app_that_uses_foo/lib/main.dart
@@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +import 'package:dart_foo/dart_foo.dart'; import 'package:flutter/material.dart'; import 'package:foo/foo.dart'; @@ -36,11 +37,13 @@ class _HomePageState extends State<HomePage> { late final FooController fooController; + late final dartFoo = DartFoo(); @override void initState() { super.initState(); fooController = FooController.instance; + dartFoo.foo(); } @override
diff --git a/packages/devtools_extensions/example/app_that_uses_foo/test/dart_test/example_dart_test.dart b/packages/devtools_extensions/example/app_that_uses_foo/test/nested/simple_test.dart similarity index 100% rename from packages/devtools_extensions/example/app_that_uses_foo/test/dart_test/example_dart_test.dart rename to packages/devtools_extensions/example/app_that_uses_foo/test/nested/simple_test.dart
diff --git a/packages/devtools_shared/test/server/server_api_test.dart b/packages/devtools_shared/test/server/server_api_test.dart index 16c1faf..348cf4b 100644 --- a/packages/devtools_shared/test/server/server_api_test.dart +++ b/packages/devtools_shared/test/server/server_api_test.dart
@@ -35,7 +35,7 @@ request, extensionsManager: ExtensionsManager(buildDir: '/'), deeplinkManager: fakeManager, - analytics: NoOpAnalytics(), + analytics: const NoOpAnalytics(), ); expect(response.statusCode, HttpStatus.ok); expect(await response.readAsString(), '["debug", "release]'); @@ -57,7 +57,7 @@ request, extensionsManager: ExtensionsManager(buildDir: '/'), deeplinkManager: FakeDeeplinkManager(), - analytics: NoOpAnalytics(), + analytics: const NoOpAnalytics(), ); expect(response.statusCode, HttpStatus.badRequest); }, @@ -87,7 +87,7 @@ request, extensionsManager: ExtensionsManager(buildDir: '/'), deeplinkManager: fakeManager, - analytics: NoOpAnalytics(), + analytics: const NoOpAnalytics(), ); expect(response.statusCode, HttpStatus.ok); expect(await response.readAsString(), someMessage); @@ -117,7 +117,7 @@ request, extensionsManager: ExtensionsManager(buildDir: '/'), deeplinkManager: fakeManager, - analytics: NoOpAnalytics(), + analytics: const NoOpAnalytics(), ); expect(response.statusCode, HttpStatus.ok); expect(await response.readAsString(), someMessage); @@ -150,7 +150,7 @@ request, extensionsManager: ExtensionsManager(buildDir: '/'), deeplinkManager: fakeManager, - analytics: NoOpAnalytics(), + analytics: const NoOpAnalytics(), ); expect(response.statusCode, HttpStatus.ok); expect(await response.readAsString(), someMessage); @@ -174,7 +174,7 @@ extensionsManager: ExtensionsManager(buildDir: '/'), deeplinkManager: fakeManager, dtdUri: dtdUri, - analytics: NoOpAnalytics(), + analytics: const NoOpAnalytics(), ); expect(response.statusCode, HttpStatus.ok); expect(