From 44523e7118543f783e4bf174e53d741053cd7562 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 15:54:32 -0700 Subject: [PATCH 01/19] Add check-unused-code to DCM CI checks. --- .github/workflows/build.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index d1fd75d9c0a..a4abae7fa9c 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -79,9 +79,13 @@ jobs: echo "$(dcm --version)" - name: Setup Dart SDK uses: dart-lang/setup-dart@e51d8e571e22473a2ddebf0ef8a2123f0ab2c02c - - name: Run DCM on root + - name: Run dcm analyze on root run: | dcm analyze packages/devtools_app packages/devtools_app_shared packages/devtools_extensions packages/devtools_shared packages/devtools_test + - name: Run dcm checks on packages + # TODO(https://github.com/flutter/devtools/issues/9906): run on all packages. + run: | + dcm check-unused-code packages/devtools_app test-packages: name: ${{ matrix.os }} ${{ matrix.package }} test From 76e7220f7abf487b488c6e6df7e089b68488e3da Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 15:57:02 -0700 Subject: [PATCH 02/19] exclude public API --- .github/workflows/build.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index a4abae7fa9c..125a7ca0e6b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -83,9 +83,9 @@ jobs: run: | dcm analyze packages/devtools_app packages/devtools_app_shared packages/devtools_extensions packages/devtools_shared packages/devtools_test - name: Run dcm checks on packages - # TODO(https://github.com/flutter/devtools/issues/9906): run on all packages. + # TODO(https://github.com/flutter/devtools/issues/9906): run on all DevTools packages. run: | - dcm check-unused-code packages/devtools_app + dcm check-unused-code packages/devtools_app --exclude-public-api test-packages: name: ${{ matrix.os }} ${{ matrix.package }} test From 93ec692f4146672ac23a6e9c089a25bc22ae6387 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:05:02 -0700 Subject: [PATCH 03/19] Add excludes --- analysis_options.yaml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/analysis_options.yaml b/analysis_options.yaml index f59d8d0ede5..9c0b00deb23 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -156,6 +156,19 @@ dart_code_metrics: maximum-nesting-level: 5 metrics-exclude: - test/** + exclude: + unused-code: + # TODO(https://github.com/dart-lang/sdk/issues/63864): clean up these + # paths once this issue is fixed. These paths are currently relative to + # devtools_app/. + # TODO(https://github.com/flutter/devtools/issues/9906) remove these + # excludes as findings are resolved. + - lib/src/extensions/** + - lib/src/framework/** + - lib/src/screens/** + - lib/src/shared/** + - lib/src/standalone_ui/** + - test/ rules: # - arguments-ordering Too strict # - avoid-banned-imports # TODO(polina-c): add configuration From 6ebb76b19dfe4a540a810841187a1042fa364103 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:06:32 -0700 Subject: [PATCH 04/19] exclude test/ --- analysis_options.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 9c0b00deb23..ddb75b26666 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -168,7 +168,7 @@ dart_code_metrics: - lib/src/screens/** - lib/src/shared/** - lib/src/standalone_ui/** - - test/ + - test/** rules: # - arguments-ordering Too strict # - avoid-banned-imports # TODO(polina-c): add configuration From 00d014e641a1256a5a4ea6ff652af85ba6155212 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:08:03 -0700 Subject: [PATCH 05/19] exclude service/ --- analysis_options.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/analysis_options.yaml b/analysis_options.yaml index ddb75b26666..314eb64b341 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -166,6 +166,7 @@ dart_code_metrics: - lib/src/extensions/** - lib/src/framework/** - lib/src/screens/** + - lib/src/service/** - lib/src/shared/** - lib/src/standalone_ui/** - test/** From 0b896c5809279700fb79d9a1386dda139b465017 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:09:26 -0700 Subject: [PATCH 06/19] exclude integration_test/ --- analysis_options.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/analysis_options.yaml b/analysis_options.yaml index 314eb64b341..d6dd068cd84 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -163,6 +163,7 @@ dart_code_metrics: # devtools_app/. # TODO(https://github.com/flutter/devtools/issues/9906) remove these # excludes as findings are resolved. + - integration_test/** - lib/src/extensions/** - lib/src/framework/** - lib/src/screens/** From 6d414f7e62a93785633b7762852a94a15d4c7be8 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:11:10 -0700 Subject: [PATCH 07/19] Ignore false positives in app.dart. --- packages/devtools_app/lib/src/app.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart index e51ec18c84a..b19f4506f84 100644 --- a/packages/devtools_app/lib/src/app.dart +++ b/packages/devtools_app/lib/src/app.dart @@ -618,7 +618,9 @@ typedef UrlParametersBuilder = /// /// This avoids issues with widgets in the appbar being hidden by the banner /// in a web or desktop app. +// ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907): false positive. class _AlternateCheckedModeBanner extends StatelessWidget { + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907): false positive. const _AlternateCheckedModeBanner({required this.builder}); final WidgetBuilder builder; From 03c168c2326162a59839455e4d50547254348dc2 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:16:10 -0700 Subject: [PATCH 08/19] Remove unused code in extensions/ and framework/ --- analysis_options.yaml | 2 -- .../lib/src/extensions/embedded/_controller_web.dart | 1 + .../lib/src/extensions/embedded/_view_desktop.dart | 7 ++++--- .../devtools_app/lib/src/extensions/extension_service.dart | 1 + packages/devtools_app/lib/src/framework/home_screen.dart | 3 +-- packages/devtools_app/lib/src/framework/release_notes.dart | 1 + .../lib/src/framework/scaffold/status_line.dart | 2 -- 7 files changed, 8 insertions(+), 9 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index d6dd068cd84..e57f4c29d8e 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -164,8 +164,6 @@ dart_code_metrics: # TODO(https://github.com/flutter/devtools/issues/9906) remove these # excludes as findings are resolved. - integration_test/** - - lib/src/extensions/** - - lib/src/framework/** - lib/src/screens/** - lib/src/service/** - lib/src/shared/** diff --git a/packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart b/packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart index 388fe7ab9d8..bdcc3f16bf0 100644 --- a/packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart +++ b/packages/devtools_app/lib/src/extensions/embedded/_controller_web.dart @@ -78,6 +78,7 @@ class EmbeddedExtensionControllerImpl extends EmbeddedExtensionController final extensionPostEventStream = StreamController.broadcast(); + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907): false positive. bool _initialized = false; @override diff --git a/packages/devtools_app/lib/src/extensions/embedded/_view_desktop.dart b/packages/devtools_app/lib/src/extensions/embedded/_view_desktop.dart index 5d9403f6ce8..051461bbbe0 100644 --- a/packages/devtools_app/lib/src/extensions/embedded/_view_desktop.dart +++ b/packages/devtools_app/lib/src/extensions/embedded/_view_desktop.dart @@ -7,9 +7,10 @@ import 'package:flutter/material.dart'; import 'controller.dart'; class EmbeddedExtension extends StatelessWidget { - const EmbeddedExtension({super.key, required this.controller}); - - final EmbeddedExtensionController controller; + const EmbeddedExtension({ + super.key, + required EmbeddedExtensionController controller, + }); @override Widget build(BuildContext context) { diff --git a/packages/devtools_app/lib/src/extensions/extension_service.dart b/packages/devtools_app/lib/src/extensions/extension_service.dart index 2c7513b48ca..ae49a3b7022 100644 --- a/packages/devtools_app/lib/src/extensions/extension_service.dart +++ b/packages/devtools_app/lib/src/extensions/extension_service.dart @@ -70,6 +70,7 @@ class ExtensionService extends DisposableController /// /// This set of extensions will include one version of a DevTools extension /// per package. + @visibleForTesting List get availableExtensions => _currentExtensions.value.availableExtensions; diff --git a/packages/devtools_app/lib/src/framework/home_screen.dart b/packages/devtools_app/lib/src/framework/home_screen.dart index 7b02646f24e..e7b3781aadb 100644 --- a/packages/devtools_app/lib/src/framework/home_screen.dart +++ b/packages/devtools_app/lib/src/framework/home_screen.dart @@ -32,8 +32,6 @@ class HomeScreen extends Screen { titleGenerator: () => devToolsTitle.value, ); - static final id = ScreenMetaData.home.id; - final List sampleData; @override @@ -171,6 +169,7 @@ class _ConnectInputState extends State with BlockingActionMixin { }()); } + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907): false positive. void _debugInitVmServiceCache() async { // We only do this in debug mode as it speeds iteration for DevTools // developers who tend to repeatedly restart DevTools to debug the same diff --git a/packages/devtools_app/lib/src/framework/release_notes.dart b/packages/devtools_app/lib/src/framework/release_notes.dart index f6ea52ca9aa..f7632c6eaf0 100644 --- a/packages/devtools_app/lib/src/framework/release_notes.dart +++ b/packages/devtools_app/lib/src/framework/release_notes.dart @@ -28,6 +28,7 @@ bool debugTestReleaseNotes = false; // from the flutter/website PR, which has a GitHub action that automatically // stages commits to firebase. Example: // https://flutter-docs-prod--pr12652-devtools-release-notes-2-52-3bbb8c0u.web.app/tools/devtools/release-notes/release-notes-2.52.0.md. +// ignore: unused-code, debug-only feature. String? _debugReleaseNotesUrl; const releaseNotesKey = Key('release_notes'); diff --git a/packages/devtools_app/lib/src/framework/scaffold/status_line.dart b/packages/devtools_app/lib/src/framework/scaffold/status_line.dart index 16133d36a29..54e78dc2954 100644 --- a/packages/devtools_app/lib/src/framework/scaffold/status_line.dart +++ b/packages/devtools_app/lib/src/framework/scaffold/status_line.dart @@ -37,8 +37,6 @@ class StatusLine extends StatelessWidget { /// Whether to highlight the footer when DevTools is connected to an app. final bool highlightForConnection; - static const deviceInfoTooltip = 'Device Info'; - /// The padding around the footer in the DevTools UI. EdgeInsets get padding => const EdgeInsets.symmetric( horizontal: defaultSpacing, From 1e8add7c765fca92a52c4b22a6c13ba8c4322d45 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:18:10 -0700 Subject: [PATCH 09/19] use if (kDebugMode) --- packages/devtools_app/lib/src/framework/home_screen.dart | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/packages/devtools_app/lib/src/framework/home_screen.dart b/packages/devtools_app/lib/src/framework/home_screen.dart index e7b3781aadb..c3fceb32168 100644 --- a/packages/devtools_app/lib/src/framework/home_screen.dart +++ b/packages/devtools_app/lib/src/framework/home_screen.dart @@ -163,13 +163,9 @@ class _ConnectInputState extends State with BlockingActionMixin { void initState() { super.initState(); connectDialogController = TextEditingController(); - assert(() { - _debugInitVmServiceCache(); - return true; - }()); + if (kDebugMode) _debugInitVmServiceCache(); } - // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907): false positive. void _debugInitVmServiceCache() async { // We only do this in debug mode as it speeds iteration for DevTools // developers who tend to repeatedly restart DevTools to debug the same From 6c3805741433e8976ebaeaa6392c68c0aca0e61b Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:19:34 -0700 Subject: [PATCH 10/19] remove other assert --- packages/devtools_app/lib/src/app.dart | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/packages/devtools_app/lib/src/app.dart b/packages/devtools_app/lib/src/app.dart index b19f4506f84..b948d84edec 100644 --- a/packages/devtools_app/lib/src/app.dart +++ b/packages/devtools_app/lib/src/app.dart @@ -242,12 +242,11 @@ class DevToolsAppState extends State with AutoDisposeMixin { // Provide the appropriate page route. if (pages.containsKey(page)) { Widget widget = pages[page]!(context, page, params, state); - assert(() { + if (kDebugMode) { widget = _AlternateCheckedModeBanner( builder: (context) => pages[page]!(context, page, params, state), ); - return true; - }()); + } return MaterialPage(child: widget); } From 57ddcd21311c14adecd19bdc244a03ab38650b27 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:57:06 -0700 Subject: [PATCH 11/19] Remove unused code from `screens/` --- analysis_options.yaml | 3 +- .../accessibility/accessibility_screen.dart | 4 +- .../src/screens/app_size/app_size_screen.dart | 3 - .../screens/debugger/breakpoint_manager.dart | 1 - .../screens/debugger/codeview_controller.dart | 1 + .../lib/src/screens/debugger/span_parser.dart | 15 +--- .../screens/debugger/syntax_highlighter.dart | 1 + .../deep_link_list_view.dart | 7 +- .../deep_links_model.dart | 9 +-- .../deep_links_screen.dart | 5 +- .../deep_links_services.dart | 1 + .../lib/src/screens/dtd/dtd_tools_model.dart | 2 - .../lib/src/screens/dtd/dtd_tools_screen.dart | 2 - .../lib/src/screens/dtd/services.dart | 1 - .../screens/inspector/inspector_screen.dart | 2 - .../inspector/inspector_screen_body.dart | 1 - .../inspector/layout_explorer/box/box.dart | 55 +------------ .../inspector/layout_explorer/ui/theme.dart | 11 --- .../layout_explorer/ui/widgets_theme.dart | 1 - .../src/screens/inspector/widget_details.dart | 2 +- .../widget_properties/properties_view.dart | 8 -- .../lib/src/screens/logging/_logs_table.dart | 5 -- .../screens/logging/logging_controller.dart | 17 ---- .../src/screens/logging/logging_screen.dart | 2 - .../memory/panes/chart/data/charts.dart | 19 ----- .../memory/panes/diff/widgets/instances.dart | 3 +- .../memory/panes/profile/instances.dart | 3 +- .../tracing/tracing_pane_controller.dart | 1 + .../shared/primitives/memory_timeline.dart | 2 - .../lib/src/screens/network/constants.dart | 10 --- .../src/screens/network/har_network_data.dart | 2 + .../src/screens/network/network_model.dart | 2 - .../src/screens/network/network_screen.dart | 9 +-- .../screens/network/offline_network_data.dart | 2 + .../flutter_frames/flutter_frame_model.dart | 4 - .../flutter_frames_controller.dart | 7 -- .../frame_analysis/frame_analysis_model.dart | 3 + .../rebuild_stats/rebuild_stats_model.dart | 2 - .../perfetto/_perfetto_controller_web.dart | 1 + .../perfetto/_perfetto_desktop.dart | 4 +- .../perfetto/tracing/model.dart | 1 + .../timeline_events_controller.dart | 1 - .../performance/performance_model.dart | 10 --- .../screens/profiler/cpu_profile_model.dart | 10 +-- .../profiler/cpu_profiler_controller.dart | 1 + .../controls/profiler_screen_controls.dart | 3 - .../method_table/method_table_model.dart | 2 + .../src/screens/profiler/profiler_screen.dart | 1 - .../src/screens/provider/provider_screen.dart | 2 - .../inbound_references_tree.dart | 1 + .../vm_developer_tools_screen.dart | 2 - .../vm_service_private_extensions.dart | 77 +------------------ .../debugger_screen_breakpoints_test.dart | 3 - .../devtools_test/lib/src/helpers/utils.dart | 15 ---- .../lib/src/mocks/fake_service_manager.dart | 4 +- .../devtools_test/lib/src/mocks/mocks.dart | 9 ++- 56 files changed, 45 insertions(+), 330 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index e57f4c29d8e..070a4f5e864 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -164,7 +164,8 @@ dart_code_metrics: # TODO(https://github.com/flutter/devtools/issues/9906) remove these # excludes as findings are resolved. - integration_test/** - - lib/src/screens/** + # Investigate internal usages of inspector_controller before removing. + - lib/src/screens/inspector/**_controller.dart - lib/src/service/** - lib/src/shared/** - lib/src/standalone_ui/** diff --git a/packages/devtools_app/lib/src/screens/accessibility/accessibility_screen.dart b/packages/devtools_app/lib/src/screens/accessibility/accessibility_screen.dart index fc387547b58..9fe59bacf4a 100644 --- a/packages/devtools_app/lib/src/screens/accessibility/accessibility_screen.dart +++ b/packages/devtools_app/lib/src/screens/accessibility/accessibility_screen.dart @@ -19,8 +19,6 @@ export 'semantics_tree_pane.dart'; class AccessibilityScreen extends Screen { AccessibilityScreen() : super.fromMetaData(ScreenMetaData.accessibility); - static final id = ScreenMetaData.accessibility.id; - @override Widget buildScreenBody(BuildContext context) => const AccessibilityScreenBody(); @@ -36,11 +34,13 @@ class AccessibilityScreenBody extends StatefulWidget { class _AccessibilityScreenBodyState extends State with AutoDisposeMixin { + // ignore: unused-code, temporarily ignore since this screen is under active development. late AccessibilityController controller; @override void initState() { super.initState(); + // ignore: unused-code, temporarily ignore since this screen is under active development. controller = screenControllers.lookup(); } diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart index ff9deef67f9..d2cc641a2bb 100644 --- a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart +++ b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart @@ -212,7 +212,6 @@ class _AppSizeBodyState extends State if (currentTab.key == AppSizeScreen.diffTabKey) ...[ const SizedBox(width: defaultSpacing), DiffTreeTypeDropdown( - value: controller.activeDiffTreeType.value, onChanged: (newDiffTreeType) { controller.changeActiveDiffTreeType(newDiffTreeType!); }, @@ -279,11 +278,9 @@ class AppUnitDropdown extends StatelessWidget { class DiffTreeTypeDropdown extends StatelessWidget { const DiffTreeTypeDropdown({ super.key, - required this.value, required this.onChanged, }); - final DiffTreeType value; final ValueChanged? onChanged; @override diff --git a/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart b/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart index 646fffa5d4b..b8207bc08d4 100644 --- a/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart +++ b/packages/devtools_app/lib/src/screens/debugger/breakpoint_manager.dart @@ -23,7 +23,6 @@ class BreakpointManager with DisposerMixin { final _breakPositionsMap = >{}; - ValueListenable> get breakpoints => _breakpoints; final _breakpoints = ValueNotifier>([]); ValueListenable> diff --git a/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart b/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart index befe39d175b..8f7abe4e6de 100644 --- a/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart +++ b/packages/devtools_app/lib/src/screens/debugger/codeview_controller.dart @@ -533,6 +533,7 @@ class CodeViewSourceLocationNavigationState extends DevToolsNavigationState { DevToolsNavigationState state, ) : super(kind: type, state: state.state); + @visibleForTesting static CodeViewSourceLocationNavigationState? fromState( DevToolsNavigationState? state, ) { diff --git a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart index 69c96c48ffc..74cbe0137ad 100644 --- a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart +++ b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart @@ -589,19 +589,6 @@ class ScopeStack { /// Location where the next produced span should begin. ScopeStackLocation _nextLocation = ScopeStackLocation.zero; - /// Adds a scope for a given region. - /// - /// This method is the same as calling [push] and then [pop] with the same - /// args. - void add( - String? scope, { - required ScopeStackLocation start, - required ScopeStackLocation end, - }) { - push(scope, start); - pop(scope, end); - } - /// Pushes a new scope onto the stack starting at [location]. void push(String? scope, ScopeStackLocation location) { if (scope == null) return; @@ -721,6 +708,8 @@ class ScopeStackItem { ScopeStackItem(this.scope, this.location); final String scope; + + // ignore: unused-code, foundational to this data class. final ScopeStackLocation location; } diff --git a/packages/devtools_app/lib/src/screens/debugger/syntax_highlighter.dart b/packages/devtools_app/lib/src/screens/debugger/syntax_highlighter.dart index 4899a83f72f..82d2c785022 100644 --- a/packages/devtools_app/lib/src/screens/debugger/syntax_highlighter.dart +++ b/packages/devtools_app/lib/src/screens/debugger/syntax_highlighter.dart @@ -18,6 +18,7 @@ final _log = Logger('syntax_highlighter'); class SyntaxHighlighter { SyntaxHighlighter({String? source}) : source = source ?? ''; + @visibleForTesting SyntaxHighlighter.withGrammar({Grammar? grammar, String? source}) : source = source ?? '' { _grammar = grammar; diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_link_list_view.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_link_list_view.dart index 75a90841656..30ef0e59793 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_link_list_view.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_link_list_view.dart @@ -33,13 +33,12 @@ class DeepLinkListView extends StatefulWidget { } class _DeepLinkListViewState extends State { - late DeepLinksController controller; - @override void initState() { super.initState(); - controller = screenControllers.lookup() - ..firstLoadWithDefaultConfigurations(); + screenControllers + .lookup() + .firstLoadWithDefaultConfigurations(); } @override diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart index feaed091a20..7d035f1b04e 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_model.dart @@ -219,14 +219,6 @@ class AASAfileFormatSubCheck extends CommonError { ), ); - static final defaultsCaseSensitiveFormat = AASAfileFormatSubCheck( - 'Applinks defaults case sensitive format', - propertyTypeMessage( - property: 'applinks.defaults.caseSensitive', - expectedType: 'boolean', - ), - ); - static const detailsFormat = AASAfileFormatSubCheck( 'Applinks details format', 'This test checks that the `applinks.details` property is formatted properly. Ref - ' @@ -402,6 +394,7 @@ class Path { final String path; // TODO(hangyujin): display queryParams in path table. + // ignore: unused-code, outstanding TODO. final Map queryParams; /// A Boolean value that indicates whether to stop pattern matching and prevent the universal diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_screen.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_screen.dart index 07520397476..a54110953f7 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_screen.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_screen.dart @@ -18,9 +18,8 @@ class DeepLinksScreen extends Screen { static final id = ScreenMetaData.deepLinks.id; - // TODO(https://github.com/flutter/devtools/issues/6013): write documentation. - // @override - // String get docPageId => id; + @override + String get docPageId => id; @override String get docsUrl => 'https://flutter.dev/to/deep-link-tool'; diff --git a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_services.dart b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_services.dart index b260c74fe0c..e16accc0afb 100644 --- a/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_services.dart +++ b/packages/devtools_app/lib/src/screens/deep_link_validation/deep_links_services.dart @@ -109,6 +109,7 @@ final aasaFileFormatSubCheck = { class ValidateIosDomainResult { ValidateIosDomainResult(this.errorCode, this.domainErrors, this.paths); + // ignore: unused-code, this is addressed in a TODO below. final String errorCode; final Map> domainErrors; final Map> paths; diff --git a/packages/devtools_app/lib/src/screens/dtd/dtd_tools_model.dart b/packages/devtools_app/lib/src/screens/dtd/dtd_tools_model.dart index caeb1758ae8..a3303152419 100644 --- a/packages/devtools_app/lib/src/screens/dtd/dtd_tools_model.dart +++ b/packages/devtools_app/lib/src/screens/dtd/dtd_tools_model.dart @@ -21,12 +21,10 @@ class DtdServiceMethod implements Comparable { const DtdServiceMethod({ required this.service, required this.method, - this.capabilities, }); final String? service; final String method; - final Map? capabilities; String get displayName => [service, method].nonNulls.join('.'); diff --git a/packages/devtools_app/lib/src/screens/dtd/dtd_tools_screen.dart b/packages/devtools_app/lib/src/screens/dtd/dtd_tools_screen.dart index 774871f46a7..46779d295af 100644 --- a/packages/devtools_app/lib/src/screens/dtd/dtd_tools_screen.dart +++ b/packages/devtools_app/lib/src/screens/dtd/dtd_tools_screen.dart @@ -27,8 +27,6 @@ import 'shared.dart'; class DTDToolsScreen extends Screen { DTDToolsScreen() : super.fromMetaData(ScreenMetaData.dtdTools); - static final id = ScreenMetaData.dtdTools.id; - @override Widget buildScreenBody(BuildContext _) => const DTDToolsScreenBody(); } diff --git a/packages/devtools_app/lib/src/screens/dtd/services.dart b/packages/devtools_app/lib/src/screens/dtd/services.dart index a9dc28da97b..8a47a7a52cc 100644 --- a/packages/devtools_app/lib/src/screens/dtd/services.dart +++ b/packages/devtools_app/lib/src/screens/dtd/services.dart @@ -60,7 +60,6 @@ class ServicesController extends FeatureController { DtdServiceMethod( service: service.name, method: method.name, - capabilities: method.capabilities, ), ], ]; diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart index 6b8a1179b36..9db58faf8b8 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_screen.dart @@ -13,8 +13,6 @@ import 'inspector_screen_controller.dart'; class InspectorScreen extends Screen { InspectorScreen() : super.fromMetaData(ScreenMetaData.inspector); - static const minScreenWidthForText = 900.0; - static final id = ScreenMetaData.inspector.id; // There is not enough room to safely show the console in the embed view of diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart index a112e94250a..f61c22f8106 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_screen_body.dart @@ -53,7 +53,6 @@ class InspectorScreenBodyState extends State SearchTargetType searchTarget = SearchTargetType.widget; static const inspectorTreeKey = Key('Inspector Tree'); - static const minScreenWidthForText = 900.0; @override void initState() { diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart index bfd22ddd984..b11a6ff2aa7 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/box/box.dart @@ -6,7 +6,6 @@ import 'package:flutter/material.dart'; import '../../../../shared/diagnostics/diagnostics_node.dart'; import '../../../../shared/primitives/utils.dart'; -import '../../inspector_controller.dart'; import '../../inspector_data_models.dart'; import '../ui/free_space.dart'; import '../ui/theme.dart'; @@ -15,14 +14,12 @@ import '../ui/widget_constraints.dart'; import '../ui/widgets_theme.dart'; class BoxLayoutExplorerWidget extends StatelessWidget { - const BoxLayoutExplorerWidget( - this.inspectorController, { + const BoxLayoutExplorerWidget({ super.key, required this.layoutProperties, required this.selectedNode, }); - final InspectorController inspectorController; final LayoutProperties? layoutProperties; final RemoteDiagnosticsNode? selectedNode; @@ -230,56 +227,6 @@ class BoxLayoutExplorerWidget extends StatelessWidget { String _describeBoxName(LayoutProperties properties) => properties.node.description ?? ''; -/// Represents a box widget and its surrounding padding. -class BoxChildAndPaddingVisualizer extends StatelessWidget { - const BoxChildAndPaddingVisualizer({ - super.key, - required this.layoutProperties, - required this.renderProperties, - required this.isSelected, - }); - - final bool isSelected; - final LayoutProperties layoutProperties; - final RenderProperties renderProperties; - - LayoutProperties? get properties => renderProperties.layoutProperties; - - @override - Widget build(BuildContext context) { - final renderSize = renderProperties.size; - final renderOffset = renderProperties.offset; - - final propertiesLocal = properties!; - - return Positioned( - top: renderOffset.dy, - left: renderOffset.dx, - child: SizedBox( - width: safePositiveDouble(renderSize.width), - height: safePositiveDouble(renderSize.height), - child: WidgetVisualizer( - isSelected: isSelected, - layoutProperties: layoutProperties, - title: _describeBoxName(propertiesLocal), - // TODO(jacobr): consider surfacing the overflow size information - // if we determine - // overflowSide: properties.overflowSide, - - // We only show one child at a time so a large title is safe. - largeTitle: true, - child: VisualizeWidthAndHeightWithConstraints( - arrowHeadSize: arrowHeadSize, - properties: propertiesLocal, - warnIfUnconstrained: false, - child: const SizedBox.shrink(), - ), - ), - ), - ); - } -} - /// Widget that represents and visualize a direct child of Flex widget. class BoxChildVisualizer extends StatelessWidget { const BoxChildVisualizer({ diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart index 666a6d902ca..4a1b947a931 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/theme.dart @@ -68,11 +68,6 @@ const overflowBackgroundColorLight = Color(0xFFB00020); const overflowTextColorDark = Color(0xfff5846b); const overflowTextColorLight = Color(0xffdea089); -const backgroundColorSelectedDark = Color( - 0x4d474747, -); // TODO(jacobr): we would like Color(0x4dedeeef) but that makes the background show through. -const backgroundColorSelectedLight = Color(0x4dedeeef); - extension LayoutExplorerColorScheme on ColorScheme { Color get mainAxisColor => isLight ? mainAxisLightColor : mainAxisDarkColor; @@ -93,16 +88,10 @@ extension LayoutExplorerColorScheme on ColorScheme { Color get overflowTextColor => isLight ? overflowTextColorLight : overflowTextColorDark; - Color get backgroundColorSelected => - isLight ? backgroundColorSelectedLight : backgroundColorSelectedDark; - Color get unconstrainedColor => isLight ? unconstrainedLightColor : unconstrainedDarkColor; } -const backgroundColorDark = Color(0xff30302f); -const backgroundColorLight = Color(0xffffffff); - const unconstrainedDarkColor = Color(0xffdea089); const unconstrainedLightColor = Color(0xfff5846b); diff --git a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart index a492a1cddbb..c0a76886c8a 100644 --- a/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart +++ b/packages/devtools_app/lib/src/screens/inspector/layout_explorer/ui/widgets_theme.dart @@ -198,7 +198,6 @@ class WidgetTheme { class WidgetIcons { static const root = 'icons/inspector/widget_icons/root.png'; static const text = 'icons/inspector/widget_icons/text.png'; - static const icon = 'icons/inspector/widget_icons/icon.png'; static const image = 'icons/inspector/widget_icons/image.png'; static const floatingActionButton = 'icons/inspector/widget_icons/floatingab.png'; diff --git a/packages/devtools_app/lib/src/screens/inspector/widget_details.dart b/packages/devtools_app/lib/src/screens/inspector/widget_details.dart index 7f12ed522c0..369c657ce73 100644 --- a/packages/devtools_app/lib/src/screens/inspector/widget_details.dart +++ b/packages/devtools_app/lib/src/screens/inspector/widget_details.dart @@ -50,7 +50,7 @@ class _WidgetDetailsState extends State with AutoDisposeMixin { ); } - return DetailsTable(controller: controller, node: node); + return DetailsTable(controller: controller); }, ); } diff --git a/packages/devtools_app/lib/src/screens/inspector/widget_properties/properties_view.dart b/packages/devtools_app/lib/src/screens/inspector/widget_properties/properties_view.dart index 1822d718819..e33624c42e0 100644 --- a/packages/devtools_app/lib/src/screens/inspector/widget_properties/properties_view.dart +++ b/packages/devtools_app/lib/src/screens/inspector/widget_properties/properties_view.dart @@ -23,15 +23,11 @@ class DetailsTable extends StatefulWidget { const DetailsTable({ super.key, required this.controller, - required this.node, - this.extraTabs, }); static const gaPrefix = 'inspectorDetailsTable'; final InspectorController controller; - final RemoteDiagnosticsNode node; - final List? extraTabs; @override State createState() => _DetailsTableState(); @@ -44,9 +40,6 @@ class _DetailsTableState extends State { RemoteDiagnosticsNode? get selectedNode => widget.controller.selectedDiagnostic; - LayoutProperties? get layoutProperties => - widget.controller.selectedNodeProperties.value.layoutProperties; - final _widgetPropertiesTab = DevToolsTab.create( tabName: 'Widget properties', gaPrefix: DetailsTable.gaPrefix, @@ -269,7 +262,6 @@ class _PropertiesViewState extends State { height: PropertiesView.layoutExplorerHeight, width: PropertiesView.layoutExplorerWidth, child: BoxLayoutExplorerWidget( - widget.controller, selectedNode: selectedNode, layoutProperties: widget.layoutProperties, ), diff --git a/packages/devtools_app/lib/src/screens/logging/_logs_table.dart b/packages/devtools_app/lib/src/screens/logging/_logs_table.dart index c406a428d45..2643f2f06a6 100644 --- a/packages/devtools_app/lib/src/screens/logging/_logs_table.dart +++ b/packages/devtools_app/lib/src/screens/logging/_logs_table.dart @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import '../../shared/primitives/utils.dart'; @@ -17,8 +16,6 @@ class LogsTable extends StatelessWidget { required this.controller, required this.data, required this.selectionNotifier, - required this.searchMatchesNotifier, - required this.activeSearchMatchNotifier, }); static const _logRowHeight = 45.0; @@ -26,8 +23,6 @@ class LogsTable extends StatelessWidget { final LoggingController controller; final List data; final ValueNotifier selectionNotifier; - final ValueListenable> searchMatchesNotifier; - final ValueListenable activeSearchMatchNotifier; static const whenColumn = WhenColumn(); static const messageColumn = MessageColumn(); diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart index da6f1cedf8f..85cfe71e4b4 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -27,7 +27,6 @@ import '../../shared/primitives/message_bus.dart'; import '../../shared/primitives/utils.dart'; import '../../shared/ui/filter.dart'; import '../../shared/ui/search.dart'; -import '../inspector/inspector_tree_controller.dart'; import 'log_details_controller.dart'; import 'logging_screen.dart'; import 'metadata.dart'; @@ -40,12 +39,6 @@ final dateTimeFormat = DateFormat('HH:mm:ss.SSS (MM/dd/yy)'); bool _verboseDebugging = false; -typedef OnShowDetails = - void Function({String? text, InspectorTreeController? tree}); - -typedef CreateLoggingTree = - InspectorTreeController Function({VoidCallback? onSelectionChange}); - typedef ZoneDescription = ({String? name, int? identityHashCode}); Future _retrieveFullStringValue( @@ -820,8 +813,6 @@ class LoggingController extends DevToolsScreenController } extension type _LogRecord(Map json) { - int? get sequenceNumber => json['sequenceNumber']; - int? get level => json['level']; Map get loggerName => json['loggerName']; @@ -934,12 +925,6 @@ class StdoutEventHandler { } }); } - - @visibleForTesting - LogData? get buffer => _buffer; - - @visibleForTesting - Timer? get timer => _timer; } bool _isNotNull(InstanceRef? serviceRef) { @@ -977,7 +962,6 @@ class LogData with SearchableDataMixin { int? level, this.isError = false, this.detailsComputer, - this.node, this.isolateRef, this.zone, }) : level = level ?? (isError ? Level.SEVERE.value : Level.INFO.value) { @@ -1008,7 +992,6 @@ class LogData with SearchableDataMixin { _levelName ??= LogLevelMetadataChip.generateLogLevel(level).name; String? _levelName; - final RemoteDiagnosticsNode? node; String? _details; Future Function()? detailsComputer; diff --git a/packages/devtools_app/lib/src/screens/logging/logging_screen.dart b/packages/devtools_app/lib/src/screens/logging/logging_screen.dart index 79d2c7cfbe2..87adecacab6 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_screen.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_screen.dart @@ -80,8 +80,6 @@ class _LoggingScreenState extends State controller: controller, data: controller.filteredData.value, selectionNotifier: controller.selectedLog, - searchMatchesNotifier: controller.searchMatches, - activeSearchMatchNotifier: controller.activeSearchMatch, ), ), ValueListenableBuilder( diff --git a/packages/devtools_app/lib/src/screens/memory/panes/chart/data/charts.dart b/packages/devtools_app/lib/src/screens/memory/panes/chart/data/charts.dart index 35d74718e76..08273b61b4b 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/chart/data/charts.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/chart/data/charts.dart @@ -9,7 +9,6 @@ import 'package:flutter/material.dart'; import '../../../../../shared/charts/chart_trace.dart'; import '../../../../../shared/primitives/byte_utils.dart'; -import '../../../../../shared/primitives/utils.dart'; import '../../../shared/primitives/memory_timeline.dart'; /// Name of each trace being charted, index order is the trace index @@ -48,13 +47,6 @@ const customEvent = 'custom'; const customEventName = 'name'; const customEventData = 'data'; -const indexPayloadJson = 'index'; -const timestampPayloadJson = 'timestamp'; -const prettyTimestampPayloadJson = 'prettyTimestamp'; -const eventPayloadJson = 'event'; -const vmPayloadJson = 'vm'; -const androidPayloadJson = 'android'; - /// VM Data const rssJsonName = 'rss'; const capacityJsonName = 'capacity'; @@ -156,17 +148,6 @@ class ChartsValues { final _android = {}; - Map toJson() { - return { - indexPayloadJson: index, - timestampPayloadJson: timestamp, - prettyTimestampPayloadJson: prettyTimestamp(timestamp), - eventPayloadJson: _event, - vmPayloadJson: _vm, - androidPayloadJson: _android, - }; - } - int get eventCount => _event.entries.length - (extensionEventsLength > 0 ? 1 : 0) + diff --git a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/instances.dart b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/instances.dart index 38a1af79c46..eb2b1b61774 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/instances.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/diff/widgets/instances.dart @@ -66,8 +66,7 @@ class _StoreAllAsVariableMenu extends StatelessWidget { final SnapshotClassSampler sampler; - // TODO(https://github.com/flutter/devtools/issues/7905): this is a bug that - // this is unused. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/7905) this is a bug that this is unused. final bool liveItemsEnabled; @override diff --git a/packages/devtools_app/lib/src/screens/memory/panes/profile/instances.dart b/packages/devtools_app/lib/src/screens/memory/panes/profile/instances.dart index 4c11d85e80b..9aa189480b3 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/profile/instances.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/profile/instances.dart @@ -25,8 +25,7 @@ class ProfileInstanceTableCell extends StatelessWidget { required this.count, }) : _shouldShowMenu = isSelected && count > 0; - // TODO(https://github.com/flutter/devtools/issues/7905): this is a bug that - // this is unused. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/7905): this is a bug that this is unused. final MemoryAreas gaContext; final int count; final bool _shouldShowMenu; diff --git a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart index 675da928e4f..93f3fa3ec37 100644 --- a/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart +++ b/packages/devtools_app/lib/src/screens/memory/panes/tracing/tracing_pane_controller.dart @@ -68,6 +68,7 @@ class TracePaneController extends DisposableController ); /// A Future tracking whether the controller has been initialized. + @visibleForTesting Future get initialized => _initialized.future; final _initialized = Completer(); diff --git a/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart b/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart index 8300073fd8f..45925c1f838 100644 --- a/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart +++ b/packages/devtools_app/lib/src/screens/memory/shared/primitives/memory_timeline.dart @@ -30,8 +30,6 @@ class MemoryTimeline extends Disposable with Serializable { static const _jsonData = 'data'; - int get endingIndex => data.isNotEmpty ? data.length - 1 : -1; - /// Raw Heap sampling data from the VM. late final List data; diff --git a/packages/devtools_app/lib/src/screens/network/constants.dart b/packages/devtools_app/lib/src/screens/network/constants.dart index e8fa703e4be..be66652e00d 100644 --- a/packages/devtools_app/lib/src/screens/network/constants.dart +++ b/packages/devtools_app/lib/src/screens/network/constants.dart @@ -7,15 +7,8 @@ enum NetworkEventKeys { version, creator, name, - pages, startedDateTime, - id, - title, - pageTimings, - onContentLoad, - onLoad, entries, - pageref, time, request, method, @@ -44,7 +37,6 @@ enum NetworkEventKeys { wait, receive, ssl, - serverIPAddress, connection, comment, value, @@ -62,8 +54,6 @@ enum NetworkEventKeys { class NetworkEventDefaults { static const logVersion = '1.2'; static const creatorName = 'devtools'; - static const onContentLoad = -1; - static const onLoad = -1; static const httpVersion = 'HTTP/1.1'; static const responseHttpVersion = 'http/2.0'; static const blocked = -1; diff --git a/packages/devtools_app/lib/src/screens/network/har_network_data.dart b/packages/devtools_app/lib/src/screens/network/har_network_data.dart index 7895e008e04..f8519bcf91b 100644 --- a/packages/devtools_app/lib/src/screens/network/har_network_data.dart +++ b/packages/devtools_app/lib/src/screens/network/har_network_data.dart @@ -3,6 +3,7 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. import 'package:devtools_shared/devtools_shared.dart'; +import 'package:meta/meta.dart'; import '../../shared/http/http_request_data.dart'; import 'constants.dart'; import 'har_builder.dart'; @@ -28,6 +29,7 @@ class HarNetworkData with Serializable { /// ```dart /// final harData = HarNetworkData.fromJson(json); /// ``` + @visibleForTesting factory HarNetworkData.fromJson(Map json) { final entries = ((json[NetworkEventKeys.log.name] diff --git a/packages/devtools_app/lib/src/screens/network/network_model.dart b/packages/devtools_app/lib/src/screens/network/network_model.dart index 9ccc3c5217a..3d7fa035607 100644 --- a/packages/devtools_app/lib/src/screens/network/network_model.dart +++ b/packages/devtools_app/lib/src/screens/network/network_model.dart @@ -192,8 +192,6 @@ class Socket extends NetworkRequest { @override int get hashCode => id.hashCode; - SocketStatistic get socketData => _socket; - @override Map toJson() { return { diff --git a/packages/devtools_app/lib/src/screens/network/network_screen.dart b/packages/devtools_app/lib/src/screens/network/network_screen.dart index 81202fb34e6..8230e002baa 100644 --- a/packages/devtools_app/lib/src/screens/network/network_screen.dart +++ b/packages/devtools_app/lib/src/screens/network/network_screen.dart @@ -6,7 +6,6 @@ import 'dart:async'; import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; @@ -321,9 +320,7 @@ class _NetworkProfilerBody extends StatelessWidget { valueListenable: controller.filteredData, builder: (context, filteredRequests, _) { return NetworkRequestsTable( - requests: filteredRequests, - searchMatchesNotifier: controller.searchMatches, - activeSearchMatchNotifier: controller.activeSearchMatch, + requests: filteredRequests ); }, ), @@ -337,8 +334,6 @@ class NetworkRequestsTable extends StatelessWidget { const NetworkRequestsTable({ super.key, required this.requests, - required this.searchMatchesNotifier, - required this.activeSearchMatchNotifier, }); static const methodColumn = MethodColumn(); @@ -361,8 +356,6 @@ class NetworkRequestsTable extends StatelessWidget { ]; final List requests; - final ValueListenable> searchMatchesNotifier; - final ValueListenable activeSearchMatchNotifier; @override Widget build(BuildContext context) { diff --git a/packages/devtools_app/lib/src/screens/network/offline_network_data.dart b/packages/devtools_app/lib/src/screens/network/offline_network_data.dart index ce6855ac382..2a7cc91aa57 100644 --- a/packages/devtools_app/lib/src/screens/network/offline_network_data.dart +++ b/packages/devtools_app/lib/src/screens/network/offline_network_data.dart @@ -3,6 +3,7 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. import 'package:devtools_shared/devtools_shared.dart'; +import 'package:meta/meta.dart'; import '../../shared/http/http_request_data.dart'; import '../network/network_controller.dart'; @@ -65,6 +66,7 @@ class OfflineNetworkData with Serializable { ); } + @visibleForTesting bool get isEmpty => httpRequestData.isEmpty && socketData.isEmpty; /// List of current [DartIOHttpRequestData] network requests. diff --git a/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frame_model.dart b/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frame_model.dart index 9b199dbea87..04b4cf790a5 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frame_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frame_model.dart @@ -165,10 +165,6 @@ class FlutterFrame { timelineEventData.rasterEvent?.writeTrackEventsToBuffer(buf); return buf.toString(); } - - FlutterFrame shallowCopy() { - return FlutterFrame.fromJson(json); - } } class FrameTimelineEventData { diff --git a/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_controller.dart b/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_controller.dart index ff970282c2c..309b5c7b4a4 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/flutter_frames/flutter_frames_controller.dart @@ -61,11 +61,6 @@ class FlutterFramesController extends PerformanceFeatureController { /// frame id in the corresponding [FlutterTimelineEvent]s. final _unassignedFlutterFrames = {}; - /// Tracks the current frame undergoing selection so that we can equality - /// check after async operations and bail out early if another frame has been - /// selected during awaits. - FlutterFrame? currentFrameBeingSelected; - @override Future init() async { if (!offlineDataController.showingOfflineData.value) { @@ -184,8 +179,6 @@ class FlutterFramesController extends PerformanceFeatureController { @override void handleSelectedFrame(FlutterFrame frame) { - currentFrameBeingSelected = frame; - // Unselect [frame] if is already selected. if (_selectedFrameNotifier.value == frame) { _selectedFrameNotifier.value = null; diff --git a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis_model.dart b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis_model.dart index 0e82e25d060..b2495ef211d 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/frame_analysis/frame_analysis_model.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +import 'package:meta/meta.dart'; + import '../../../../shared/primitives/trees.dart'; import '../../../../shared/primitives/utils.dart'; import '../../performance_model.dart'; @@ -128,6 +130,7 @@ class FrameAnalysis { return longest; } + @visibleForTesting bool get hasExpensiveOperations => saveLayerCount + intrinsicOperationsCount > 0; diff --git a/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats_model.dart b/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats_model.dart index 153778fa520..91c1d0a63c4 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/rebuild_stats/rebuild_stats_model.dart @@ -211,8 +211,6 @@ class RebuildCountModel { return _rebuildsForFrame[frameNumber]; } - bool get isNotEmpty => _rebuildsForFrame.isNotEmpty; - Map? toJson() { if (_rebuildsForFrame.isEmpty) { // No need to encode data unless there were actually rebuilds reported. diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_controller_web.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_controller_web.dart index c032ba10887..e284d9d2ebf 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_controller_web.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_controller_web.dart @@ -159,6 +159,7 @@ class PerfettoControllerImpl extends PerfettoController { final perfettoPostEventStream = StreamController.broadcast(); + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907) false positive. bool _initialized = false; @override diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_desktop.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_desktop.dart index 1315d9589b2..7f0881ab4b4 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_desktop.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/_perfetto_desktop.dart @@ -7,9 +7,7 @@ import 'package:flutter/material.dart'; import 'perfetto_controller.dart'; class Perfetto extends StatelessWidget { - const Perfetto({super.key, required this.perfettoController}); - - final PerfettoController perfettoController; + const Perfetto({super.key, required PerfettoController perfettoController}); @override Widget build(BuildContext context) { diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/tracing/model.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/tracing/model.dart index c2ec2f4d12b..e3ddac11beb 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/tracing/model.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/perfetto/tracing/model.dart @@ -101,6 +101,7 @@ class PerfettoTrackEvent extends _PerfettoTracePacket ].nonNulls, ); + @visibleForTesting List get categories => event.categories; /// The id of the Perfetto track that this event is included in. diff --git a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_controller.dart b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_controller.dart index 53830788d5d..c37291140d6 100644 --- a/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_controller.dart +++ b/packages/devtools_app/lib/src/screens/performance/panes/timeline_events/timeline_events_controller.dart @@ -49,7 +49,6 @@ class TimelineEventsController extends PerformanceFeatureController static const uiThreadSuffix = '.ui'; static const rasterThreadSuffix = '.raster'; - static const gpuThreadSuffix = '.gpu'; static const platformThreadSuffix = '.platform'; static const flutterTestThreadSuffix = '.flutter.test..ui'; static final _refreshWorkTrackerDelay = const Duration( diff --git a/packages/devtools_app/lib/src/screens/performance/performance_model.dart b/packages/devtools_app/lib/src/screens/performance/performance_model.dart index a965879822c..89c310747ff 100644 --- a/packages/devtools_app/lib/src/screens/performance/performance_model.dart +++ b/packages/devtools_app/lib/src/screens/performance/performance_model.dart @@ -163,16 +163,6 @@ class FlutterTimelineEvent extends TreeNode { timeBuilder: _timeBuilder.copy(), ); - @visibleForTesting - FlutterTimelineEvent deepCopy() { - final copy = shallowCopy(); - copy.parent = parent; - for (final child in children) { - copy.addChild(child.deepCopy()); - } - return copy; - } - @override String toString() { final buf = StringBuffer(); diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart index f1eb442f8e4..82b0f1fc975 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profile_model.dart @@ -577,7 +577,6 @@ class CpuProfileData with Serializable { final stackFrames = await _CpuStackFrameGenerator( isolateId: isolateId, - cpuSamples: cpuSamples, profileMetaData: profileMetaData, ).generate( treeRoot: _CpuProfileTimelineTree.fromCpuSamples( @@ -1175,11 +1174,6 @@ class CpuProfileStore { _profilesByTime.clear(); _profilesByLabel.clear(); } - - void debugPrintKeys() { - _log.info('_profilesByLabel: ${_profilesByLabel.keys}'); - _log.info('_profilesByTime: ${_profilesByTime.keys}'); - } } class _CpuProfileTimelineTree { @@ -1329,7 +1323,7 @@ class _CpuProfileTimelineTree { } /// A generator class for creating a set of [CpuStackFrame]s from a -/// [vm_service.CpuSamples] object. +/// [_CpuProfileTimelineTree] object. /// /// This class is responsible for traversing the call stacks of a CPU profile, /// creating a [CpuStackFrame] for each unique frame, and assigning a unique @@ -1339,12 +1333,10 @@ class _CpuProfileTimelineTree { class _CpuStackFrameGenerator { _CpuStackFrameGenerator({ required this.isolateId, - required this.cpuSamples, required this.profileMetaData, }); final String isolateId; - final vm_service.CpuSamples cpuSamples; final CpuProfileMetaData profileMetaData; final _stackFrames = {}; diff --git a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler_controller.dart b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler_controller.dart index 4caea9b1072..4274eb2422f 100644 --- a/packages/devtools_app/lib/src/screens/profiler/cpu_profiler_controller.dart +++ b/packages/devtools_app/lib/src/screens/profiler/cpu_profiler_controller.dart @@ -411,6 +411,7 @@ class CpuProfilerController extends DisposableController return '$label${filterTag.isNotEmpty ? '-$filterTag' : ''}'; } + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) seems like a bug. Future loadAppStartUpProfile() async { Future loadAppStartUpProfileHelper() async { // Look up the stored app start up profiles before calling [reset]. This diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_screen_controls.dart b/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_screen_controls.dart index fbc7cb06d38..c1c5b244514 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_screen_controls.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/controls/profiler_screen_controls.dart @@ -18,7 +18,6 @@ class ProfilerScreenControls extends StatelessWidget { required this.controller, required this.recording, required this.processing, - required this.offline, }); final ProfilerScreenController controller; @@ -27,8 +26,6 @@ class ProfilerScreenControls extends StatelessWidget { final bool processing; - final bool offline; - @override Widget build(BuildContext context) { return OfflineAwareControls( diff --git a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_model.dart b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_model.dart index d7e78bed259..93b7cc9c236 100644 --- a/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_model.dart +++ b/packages/devtools_app/lib/src/screens/profiler/panes/method_table/method_table_model.dart @@ -3,6 +3,7 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. import 'package:collection/collection.dart'; +import 'package:meta/meta.dart'; import '../../../../shared/primitives/graph.dart'; import '../../../../shared/primitives/utils.dart'; @@ -136,6 +137,7 @@ $display ($totalCount samples) '''; } + @visibleForTesting MethodTableGraphNode copy() { return MethodTableGraphNode( name: name, diff --git a/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart b/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart index cf473f55f24..ae60c9aa1c8 100644 --- a/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart +++ b/packages/devtools_app/lib/src/screens/profiler/profiler_screen.dart @@ -142,7 +142,6 @@ class _ProfilerScreenBodyState extends State controller: controller, recording: recording, processing: profilerBusy, - offline: offlineDataController.showingOfflineData.value, ), const SizedBox(height: intermediateSpacing), Expanded( diff --git a/packages/devtools_app/lib/src/screens/provider/provider_screen.dart b/packages/devtools_app/lib/src/screens/provider/provider_screen.dart index e4f077ad8f2..027ee4eda19 100644 --- a/packages/devtools_app/lib/src/screens/provider/provider_screen.dart +++ b/packages/devtools_app/lib/src/screens/provider/provider_screen.dart @@ -11,8 +11,6 @@ import '../../shared/ui/common_widgets.dart'; class ProviderScreen extends Screen { ProviderScreen() : super.fromMetaData(ScreenMetaData.provider); - static final id = ScreenMetaData.provider.id; - @override Widget buildScreenBody(BuildContext context) { return CenteredMessage( diff --git a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/inbound_references_tree.dart b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/inbound_references_tree.dart index c48c3c32a83..56d31243d55 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/inbound_references_tree.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/object_inspector/inbound_references_tree.dart @@ -26,6 +26,7 @@ class InboundReferencesTreeNode extends TreeNode { @override bool get isExpandable => ref.source != null; + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) this seems like a bug. late final description = _inboundRefDescription(ref, null); /// Wrapper to get the name of an [ObjRef] depending on its type. diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart index e30f8cdae62..e544efde766 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_developer_tools_screen.dart @@ -37,8 +37,6 @@ abstract class VMDeveloperView { class VMDeveloperToolsScreen extends Screen { VMDeveloperToolsScreen() : super.fromMetaData(ScreenMetaData.vmTools); - static final id = ScreenMetaData.vmTools.id; - @override ValueListenable get showIsolateSelector => VMDeveloperToolsController.showIsolateSelector; diff --git a/packages/devtools_app/lib/src/screens/vm_developer/vm_service_private_extensions.dart b/packages/devtools_app/lib/src/screens/vm_developer/vm_service_private_extensions.dart index 7b8c3c4d9fb..9a77b16fd30 100644 --- a/packages/devtools_app/lib/src/screens/vm_developer/vm_service_private_extensions.dart +++ b/packages/devtools_app/lib/src/screens/vm_developer/vm_service_private_extensions.dart @@ -55,33 +55,7 @@ extension IsolatePrivateViewExtension on Isolate { (json!['_heaps'] as Map).cast(); } -/// An extension on [Class] which allows for access to VM internal fields. -extension ClassPrivateViewExtension on Class { - /// The internal name of the [Class]. - String get vmName => json![_vmNameKey]; -} - -/// An extension on [InboundReferences] which allows for access to -/// VM internal fields. -extension InboundReferenceExtension on InboundReferences { - static const _referencesKey = 'references'; - static const _parentWordOffsetKey = '_parentWordOffset'; - - int? parentWordOffset(int inboundReferenceIndex) { - final references = (json![_referencesKey] as List?)?.cast(); - final inboundReference = (references?[inboundReferenceIndex] as Map?) - ?.cast(); - return inboundReference?[_parentWordOffsetKey] as int?; - } -} - class HeapStats { - const HeapStats({ - required this.count, - required this.size, - required this.externalSize, - }); - const HeapStats.empty() : count = 0, size = 0, externalSize = 0; HeapStats.parse(List stats) @@ -172,10 +146,6 @@ extension ObjRefPrivateViewExtension on ObjRef { /// `true` if this object is an instance of [SubtypeTestCacheRef]. bool get isSubtypeTestCache => vmType == _subtypeTestCache; - /// Casts the current [ObjRef] into an instance of [SubtypeTestCacheRef]. - SubtypeTestCacheRef get asSubtypeTestCache => - SubtypeTestCacheRef.fromJson(json!); - /// `true` if this object is an instance of [WeakArrayRef]. bool get isWeakArray => vmType == _weakArrayType; @@ -273,9 +243,6 @@ class WeakArray extends WeakArrayRef implements Obj { class SubtypeTestCacheRef implements ObjRef { SubtypeTestCacheRef({required this.id, required this.json}); - factory SubtypeTestCacheRef.fromJson(Map json) => - SubtypeTestCacheRef(id: json['id'], json: json); - @override bool? fixedId; @@ -540,22 +507,15 @@ enum FunctionKind { /// An extension on [Code] which allows for access to VM internal fields. extension CodePrivateViewExtension on Code { static const _disassemblyKey = '_disassembly'; - static const _kindKey = 'kind'; static const _objectPoolKey = '_objectPool'; /// Returns the disassembly of the [Code], which is the generated assembly /// instructions for the code's function. Disassembly get disassembly => Disassembly.parse(json![_disassemblyKey]); + @visibleForTesting set disassembly(Disassembly disassembly) => json![_disassemblyKey] = disassembly.toJson(); - /// The kind of code object represented by this instance. - /// - /// Can be one of: - /// - Dart - /// - Stub - String get kind => json![_kindKey]; - ObjectPoolRef get objectPool => ObjectPoolRef.parse(json![_objectPoolKey]); bool get hasInliningData => json!.containsKey(InliningData.kInlinedFunctions); @@ -676,20 +636,6 @@ enum ObjectPoolEntryKind { static const _kObject = 'Object'; static const _kImm = 'Immediate'; - static const _kNativeFunction = 'NativeFunction'; - - static ObjectPoolEntryKind fromString(String type) { - switch (type) { - case _kObject: - return object; - case _kImm: - return immediate; - case _kNativeFunction: - return nativeFunction; - default: - throw UnsupportedError('Unsupported ObjectPoolType: $type'); - } - } @override String toString() { @@ -707,24 +653,19 @@ enum ObjectPoolEntryKind { class ObjectPoolEntry { const ObjectPoolEntry({ required this.offset, - required this.kind, required this.value, }); static const _offsetKey = 'offset'; - static const _kindKey = 'kind'; static const _valueKey = 'value'; static ObjectPoolEntry parse(Map json) => ObjectPoolEntry( offset: json[_offsetKey], - kind: ObjectPoolEntryKind.fromString(json[_kindKey]), value: createServiceObject(json[_valueKey], [])!, ); final int offset; - final ObjectPoolEntryKind kind; - final Object value; } @@ -850,14 +791,6 @@ class ObjectStore { /// /// See [CpuSamples]. class ProfileCode { - ProfileCode({ - this.kind, - this.inclusiveTicks, - this.exclusiveTicks, - this.code, - this.ticks, - }); - ProfileCode._fromJson(Map json) { kind = json['kind'] ?? ''; inclusiveTicks = json['inclusiveTicks'] ?? -1; @@ -883,6 +816,7 @@ class ProfileCode { List? ticks; + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) seems like a bug. Map toJson() { final json = {}; json.addAll({ @@ -915,10 +849,6 @@ extension CpuSamplesPrivateView on CpuSamples { static const _kCodesKey = '_codes'; - bool get hasCodes { - return _expando[this] != null || json!.containsKey(_kCodesKey); - } - List get codes { return _expando[this] ??= (json![_kCodesKey] as List) .cast>() @@ -936,13 +866,11 @@ extension ProfileDataRanges on SourceReport { class ProfileReportEntry { const ProfileReportEntry({ required this.sampleCount, - required this.line, required this.inclusive, required this.exclusive, }); final int sampleCount; - final int line; final int inclusive; final int exclusive; @@ -970,7 +898,6 @@ class ProfileReportRange { final line = lines[i]; entries[line] = ProfileReportEntry( sampleCount: json.sampleCount, - line: line, inclusive: inclusiveTicks[i], exclusive: exclusiveTicks[i], ); diff --git a/packages/devtools_app/test/screens/debugger/debugger_screen_breakpoints_test.dart b/packages/devtools_app/test/screens/debugger/debugger_screen_breakpoints_test.dart index 7470497d0f9..90594f9ccc1 100644 --- a/packages/devtools_app/test/screens/debugger/debugger_screen_breakpoints_test.dart +++ b/packages/devtools_app/test/screens/debugger/debugger_screen_breakpoints_test.dart @@ -56,9 +56,6 @@ void main() { ), ]; final codeViewController = debuggerController.codeViewController; - when( - mockBreakpointManager.breakpoints, - ).thenReturn(ValueNotifier(breakpoints)); when( mockBreakpointManager.breakpointsWithLocation, ).thenReturn(ValueNotifier(breakpointsWithLocation)); diff --git a/packages/devtools_test/lib/src/helpers/utils.dart b/packages/devtools_test/lib/src/helpers/utils.dart index a11e3657368..510471bb1b9 100644 --- a/packages/devtools_test/lib/src/helpers/utils.dart +++ b/packages/devtools_test/lib/src/helpers/utils.dart @@ -35,21 +35,6 @@ const safePumpDuration = Duration(seconds: 3); const longPumpDuration = Duration(seconds: 6); const veryLongPumpDuration = Duration(seconds: 9); -final screenIds = [ - AppSizeScreen.id, - DebuggerScreen.id, - DeepLinksScreen.id, - InspectorScreen.id, - LoggingScreen.id, - MemoryScreen.id, - NetworkScreen.id, - PerformanceScreen.id, - ProfilerScreen.id, - ProviderScreen.id, - VMDeveloperToolsScreen.id, - DTDToolsScreen.id, -]; - /// Scoping method which registers `listener` as a listener for `listenable`, /// invokes `callback`, and then removes the `listener`. /// diff --git a/packages/devtools_test/lib/src/mocks/fake_service_manager.dart b/packages/devtools_test/lib/src/mocks/fake_service_manager.dart index 35efaa85615..1b4027fedea 100644 --- a/packages/devtools_test/lib/src/mocks/fake_service_manager.dart +++ b/packages/devtools_test/lib/src/mocks/fake_service_manager.dart @@ -13,7 +13,6 @@ import 'package:flutter/foundation.dart'; import 'package:mockito/mockito.dart'; import 'package:vm_service/vm_service.dart'; -import '../helpers/utils.dart'; import 'fake_isolate_manager.dart'; import 'fake_service_extension_manager.dart'; import 'fake_vm_service_wrapper.dart'; @@ -39,7 +38,8 @@ class FakeServiceConnectionManager extends Fake availableServices: availableServices, rootLibrary: rootLibrary, ); - for (final screenId in screenIds) { + for (final screen in ScreenMetaData.values) { + final screenId = screen.id; when(errorBadgeManager.erroredItemsForPage(screenId)).thenReturn( FixedValueListenable(LinkedHashMap()), ); diff --git a/packages/devtools_test/lib/src/mocks/mocks.dart b/packages/devtools_test/lib/src/mocks/mocks.dart index d4fd88878fb..ca204b350f6 100644 --- a/packages/devtools_test/lib/src/mocks/mocks.dart +++ b/packages/devtools_test/lib/src/mocks/mocks.dart @@ -237,6 +237,7 @@ Script? _loadScript(String scriptName) { return Script.parse(jsonDecode(script.readAsStringSync())); } +// ignore: invalid_use_of_visible_for_testing_member, devtools_test is only used in tests. final mockSyntaxHighlighter = SyntaxHighlighter.withGrammar( grammar: mockGrammar, source: mockScript!.source, @@ -249,10 +250,10 @@ const coverageMissLines = {2, 5}; const executableLines = {...coverageHitLines, ...coverageMissLines}; const profilerEntries = { - 1: ProfileReportEntry(sampleCount: 5, line: 1, inclusive: 2, exclusive: 2), - 3: ProfileReportEntry(sampleCount: 5, line: 3, inclusive: 1, exclusive: 1), - 4: ProfileReportEntry(sampleCount: 5, line: 4, inclusive: 1, exclusive: 1), - 7: ProfileReportEntry(sampleCount: 5, line: 7, inclusive: 1, exclusive: 1), + 1: ProfileReportEntry(sampleCount: 5, inclusive: 2, exclusive: 2), + 3: ProfileReportEntry(sampleCount: 5, inclusive: 1, exclusive: 1), + 4: ProfileReportEntry(sampleCount: 5, inclusive: 1, exclusive: 1), + 7: ProfileReportEntry(sampleCount: 5, inclusive: 1, exclusive: 1), }; final mockParsedScript = ParsedScript( From 582da8ce602027f918aac99dc0ff355620cd5ccd Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Tue, 21 Jul 2026 16:57:51 -0700 Subject: [PATCH 12/19] fix test --- .../object_inspector/vm_object_pool_display_test.dart | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_object_pool_display_test.dart b/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_object_pool_display_test.dart index d0541ed1505..3c9c4eae83a 100644 --- a/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_object_pool_display_test.dart +++ b/packages/devtools_app/test/screens/vm_developer/object_inspector/vm_object_pool_display_test.dart @@ -37,7 +37,6 @@ void main() { final objectPoolEntries = [ ObjectPoolEntry( offset: 0, - kind: ObjectPoolEntryKind.object, value: InstanceRef( id: 'fake-inst', kind: InstanceKind.kList, @@ -46,12 +45,10 @@ void main() { ), const ObjectPoolEntry( offset: 10, - kind: ObjectPoolEntryKind.immediate, value: 42, ), ObjectPoolEntry( offset: 20, - kind: ObjectPoolEntryKind.nativeFunction, value: FuncRef(id: 'func-id', name: 'Foo'), ), ]; From 1d6d8c7e11f308c512c6aba33e6c44e125a32a82 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 10:15:30 -0700 Subject: [PATCH 13/19] Resolve integration_test/ findings --- analysis_options.yaml | 1 - .../integration_test/test_infra/run/_test_app_driver.dart | 2 -- 2 files changed, 3 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 070a4f5e864..2444597de86 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -163,7 +163,6 @@ dart_code_metrics: # devtools_app/. # TODO(https://github.com/flutter/devtools/issues/9906) remove these # excludes as findings are resolved. - - integration_test/** # Investigate internal usages of inspector_controller before removing. - lib/src/screens/inspector/**_controller.dart - lib/src/service/** diff --git a/packages/devtools_app/integration_test/test_infra/run/_test_app_driver.dart b/packages/devtools_app/integration_test/test_infra/run/_test_app_driver.dart index cd3c843a291..4906faef256 100644 --- a/packages/devtools_app/integration_test/test_infra/run/_test_app_driver.dart +++ b/packages/devtools_app/integration_test/test_infra/run/_test_app_driver.dart @@ -389,11 +389,9 @@ final class FlutterDaemonConstants { static const paramsKey = 'params'; static const traceKey = 'trace'; static const wsUriKey = 'wsUri'; - static const pidKey = 'pid'; static const appStopKey = 'app.stop'; static const appStartedKey = 'app.started'; static const appDebugPortKey = 'app.debugPort'; - static const daemonConnectedKey = 'daemon.connected'; } enum TestAppDevice { From b6d8bb22d2323edf21624c95c09f5f153080913e Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:23:43 -0700 Subject: [PATCH 14/19] Remove unused code from `shared` --- analysis_options.yaml | 6 +- .../benchmark/devtools_benchmarks_test.dart | 7 +- .../benchmark/scripts/compare_benchmarks.dart | 3 +- .../src/screens/app_size/app_size_screen.dart | 3 + .../lib/src/screens/debugger/span_parser.dart | 7 +- .../inspector/inspector_tree_controller.dart | 16 +- .../screens/logging/logging_controller.dart | 6 +- .../src/shared/analytics/_analytics_web.dart | 1 + .../analytics/analytics_controller.dart | 3 +- .../lib/src/shared/analytics/constants.dart | 7 - .../constants/_cpu_profiler_constants.dart | 1 - .../constants/_performance_constants.dart | 4 - .../lib/src/shared/analytics/metrics.dart | 1 - .../lib/src/shared/charts/chart_trace.dart | 22 +- .../lib/src/shared/charts/flame_chart.dart | 147 +-- .../lib/src/shared/charts/treemap.dart | 17 +- .../drag_and_drop/drag_and_drop.dart | 14 - .../_framework_initialize_desktop.dart | 4 +- .../import_export/_file_desktop.dart | 73 -- .../import_export/import_export.dart | 1 - .../post_message/_post_message_stub.dart | 1 + .../post_message/_post_message_web.dart | 4 +- .../post_message/post_message.dart | 3 +- .../shared/console/eval/inspector_tree.dart | 36 +- .../console/primitives/eval_history.dart | 3 + .../shared/console/widgets/description.dart | 2 +- .../console/widgets/display_provider.dart | 1 + .../src/shared/console/widgets/evaluate.dart | 3 - .../lib/src/shared/development_helpers.dart | 1 + .../shared/diagnostics/dart_object_node.dart | 5 +- .../shared/diagnostics/diagnostics_node.dart | 4 - .../lib/src/shared/editor/api_classes.dart | 1 - .../lib/src/shared/editor/editor_client.dart | 2 + .../lib/src/shared/feature_flags.dart | 2 + .../shared/framework/app_error_handling.dart | 3 + .../lib/src/shared/framework/routing.dart | 5 +- .../lib/src/shared/framework/screen.dart | 2 + .../devtools_app/lib/src/shared/globals.dart | 8 +- .../lib/src/shared/http/_http_cookies.dart | 13 - .../lib/src/shared/http/constants.dart | 41 - .../src/shared/http/http_request_data.dart | 1 + .../src/shared/managers/banner_messages.dart | 33 +- .../src/shared/managers/script_manager.dart | 10 - .../lib/src/shared/memory/class_name.dart | 1 + .../lib/src/shared/memory/heap_data.dart | 1 - .../src/shared/memory/heap_graph_loader.dart | 2 + .../lib/src/shared/memory/retaining_path.dart | 25 +- .../preferences/_logging_preferences.dart | 2 - .../src/shared/preferences/preferences.dart | 10 - .../lib/src/shared/primitives/ansi_utils.dart | 28 - .../custom_pointer_scroll_view.dart | 1 + .../linked_scroll_controller.dart | 2 + .../primitives/list_queue_value_notifier.dart | 2 + .../src/shared/primitives/simple_items.dart | 2 - .../src/shared/primitives/trace_event.dart | 2 + .../lib/src/shared/primitives/trees.dart | 17 +- .../lib/src/shared/primitives/utils.dart | 311 +----- .../lib/src/shared/server/server.dart | 2 - .../lib/src/shared/table/_tree_table.dart | 1 + .../lib/src/shared/ui/colors.dart | 24 - .../lib/src/shared/ui/common_widgets.dart | 313 +------ .../lib/src/shared/ui/filter.dart | 1 + .../devtools_app/lib/src/shared/ui/icons.dart | 98 +- .../lib/src/shared/ui/search.dart | 9 +- .../devtools_app/lib/src/shared/ui/utils.dart | 1 + .../lib/src/shared/utils/utils.dart | 7 +- .../cpu_profiler/profiler_screen_test.dart | 3 +- .../test/shared/ansi_output_test.dart | 34 + .../test/shared/primitives/utils_test.dart | 886 ++++-------------- .../test/shared/ui/common_widgets_test.dart | 37 - .../test/shared/utils/utils_test.dart | 4 + .../property_editor/utils_test.dart | 6 - 72 files changed, 321 insertions(+), 2038 deletions(-) diff --git a/analysis_options.yaml b/analysis_options.yaml index 2444597de86..240a2aa98a9 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -163,10 +163,12 @@ dart_code_metrics: # devtools_app/. # TODO(https://github.com/flutter/devtools/issues/9906) remove these # excludes as findings are resolved. - # Investigate internal usages of inspector_controller before removing. + # Investigate internal usages of inspector logic before removing. - lib/src/screens/inspector/**_controller.dart + - lib/src/shared/diagnostics/inspector_service.dart + - lib/src/shared/diagnostics/diagnostics_node.dart + - lib/src/service/** - - lib/src/shared/** - lib/src/standalone_ui/** - test/** rules: diff --git a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart index 15cf0a656d1..78bab65b0cc 100644 --- a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart +++ b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart @@ -5,10 +5,10 @@ // Note: this test was modeled after the example test from Flutter Gallery: // https://github.com/flutter/gallery/blob/master/test_benchmarks/benchmarks_test.dart -import 'dart:convert' show JsonEncoder; import 'dart:io'; import 'package:collection/collection.dart'; +import 'package:devtools_app/src/shared/primitives/utils.dart'; import 'package:devtools_test/helpers.dart'; import 'package:test/test.dart'; import 'package:web_benchmarks/metrics.dart'; @@ -92,10 +92,7 @@ Future _runBenchmarks({bool useWasm = false}) async { stdout.writeln('Web benchmark tests finished.'); - expect( - const JsonEncoder.withIndent(' ').convert(taskResult.toJson()), - isA(), - ); + expect(taskResult.toJson().prettyPrint(), isA()); expect(taskResult.scores.keys, hasLength(DevToolsBenchmark.values.length)); for (final devToolsBenchmark in DevToolsBenchmark.values) { diff --git a/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart b/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart index 6b919c910ef..68e9c1c9f90 100644 --- a/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart +++ b/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:devtools_app/src/shared/primitives/utils.dart'; import 'package:web_benchmarks/analysis.dart'; import 'utils.dart'; @@ -61,6 +62,6 @@ void compareBenchmarks( stdout.writeln('Baseline comparison finished.'); stdout ..writeln('==== Comparison with baseline $baselineSource ====') - ..writeln(const JsonEncoder.withIndent(' ').convert(delta.toJson())) + ..writeln(delta.toJson().prettyPrint()) ..writeln('==== End of baseline comparison ===='); } diff --git a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart index 236f91edb39..f32897995b6 100644 --- a/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart +++ b/packages/devtools_app/lib/src/screens/app_size/app_size_screen.dart @@ -212,6 +212,7 @@ class _AppSizeBodyState extends State if (currentTab.key == AppSizeScreen.diffTabKey) ...[ const SizedBox(width: defaultSpacing), DiffTreeTypeDropdown( + value: controller.activeDiffTreeType.value, onChanged: (newDiffTreeType) { controller.changeActiveDiffTreeType(newDiffTreeType!); }, @@ -278,9 +279,11 @@ class AppUnitDropdown extends StatelessWidget { class DiffTreeTypeDropdown extends StatelessWidget { const DiffTreeTypeDropdown({ super.key, + required this.value, required this.onChanged, }); + final DiffTreeType value; final ValueChanged? onChanged; @override diff --git a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart index 74cbe0137ad..b5a92c54a26 100644 --- a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart +++ b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart @@ -3,11 +3,12 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. import 'dart:collection'; -import 'dart:convert'; import 'package:collection/collection.dart'; import 'package:string_scanner/string_scanner.dart'; +import '../../shared/primitives/utils.dart'; + //TODO(jacobr): cleanup. /// A namespace for [SpanParser] utilities. extension SpanParser on Never { @@ -68,12 +69,12 @@ class Grammar { @override String toString() { - return const JsonEncoder.withIndent(' ').convert({ + return { 'name': name, 'scopeName': scopeName, 'topLevelMatcher': topLevelMatcher.toJson(), 'repository': repository.toJson(), - }); + }.prettyPrint(); } } diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart index 130bec6a5a2..1d57584ef96 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart @@ -121,7 +121,7 @@ class InspectorTreeController extends DisposableController final int? gaId; InspectorTreeNode createNode() => - InspectorTreeNode(whenDirty: _handleDirtyNode); + InspectorTreeNode(); SearchTargetType _searchTarget = SearchTargetType.widget; int _rootSetCount = 0; @@ -284,15 +284,6 @@ class InspectorTreeController extends DisposableController } } - /// Resets the state if the root has been marked as dirty. - void _handleDirtyNode(InspectorTreeNode node) { - if (node == root) { - _cachedSelectedRow = null; - lastContentWidth = null; - _updateRows(); - } - } - void setSearchTarget(SearchTargetType searchTarget) { _searchTarget = searchTarget; refreshSearchMatches(); @@ -448,10 +439,6 @@ class InspectorTreeController extends DisposableController return inspectorRowHeight * index; } - void nodeChanged(InspectorTreeNode node) { - node.isDirty = true; - } - void removeNodeFromParent(InspectorTreeNode node) { node.parent?.removeChild(node); } @@ -767,7 +754,6 @@ class InspectorTreeController extends DisposableController setupChildren(diagnostic, treeNode, children, expandChildren: true); refreshTree( updateTreeAction: () { - nodeChanged(treeNode); if (treeNode == selection) { expandPath(treeNode); } diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart index e92a3829ccf..06d65020970 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -1016,8 +1016,6 @@ class LogData with SearchableDataMixin { String? _details; Future Function()? detailsComputer; - static const prettyPrinter = JsonEncoder.withIndent(' '); - String? get details => _details; bool get needsComputing => !detailsComputed.isCompleted; @@ -1040,8 +1038,8 @@ class LogData with SearchableDataMixin { } try { - return prettyPrinter - .convert(jsonDecode(details!)) + return (jsonDecode(details!) as Object?) + .prettyPrint() .replaceAll(r'\n', '\n') .trim(); } catch (_) { diff --git a/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart b/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart index aef066c8670..a6f371a3590 100644 --- a/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart +++ b/packages/devtools_app/lib/src/shared/analytics/_analytics_web.dart @@ -3,6 +3,7 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. // ignore_for_file: non_constant_identifier_names +// ignore_for_file: unused-code, platform specific imports. import 'dart:async'; diff --git a/packages/devtools_app/lib/src/shared/analytics/analytics_controller.dart b/packages/devtools_app/lib/src/shared/analytics/analytics_controller.dart index 52bb5710d0a..9d7c9684284 100644 --- a/packages/devtools_app/lib/src/shared/analytics/analytics_controller.dart +++ b/packages/devtools_app/lib/src/shared/analytics/analytics_controller.dart @@ -43,8 +43,6 @@ bool get isAnalyticsEnabled => /// Whether the analytics controller has been initialized. bool get isAnalyticsControllerInitialized => _analyticsController != null; -typedef AsyncAnalyticsCallback = FutureOr Function(); - class AnalyticsController { AnalyticsController({ required bool enabled, @@ -67,6 +65,7 @@ class AnalyticsController { ValueListenable get shouldPrompt => _shouldPrompt; final ValueNotifier _shouldPrompt; + @visibleForTesting bool get analyticsInitialized => _analyticsInitialized; bool _analyticsInitialized = false; diff --git a/packages/devtools_app/lib/src/shared/analytics/constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants.dart index c56654fc5c2..1eb14d8df3d 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants.dart @@ -99,13 +99,6 @@ const inspectorSettings = 'inspectorSettings'; const loggingSettings = 'loggingSettings'; const refreshPubRoots = 'refreshPubRoots'; -enum InspectorDetailsViewType { layoutExplorer, widgetDetailsTree } - -final defaultDetailsViewToLayoutExplorer = - InspectorDetailsViewType.layoutExplorer.name; -final defaultDetailsViewToWidgetDetails = - InspectorDetailsViewType.widgetDetailsTree.name; - enum HomeScreenEvents { connectToApp, connectToNewApp, viewVmFlags } // Logging UX actions: diff --git a/packages/devtools_app/lib/src/shared/analytics/constants/_cpu_profiler_constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants/_cpu_profiler_constants.dart index 9920f33bb01..4a7c7ced742 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants/_cpu_profiler_constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants/_cpu_profiler_constants.dart @@ -7,7 +7,6 @@ part of '../constants.dart'; enum CpuProfilerEvents { profileGranularity, loadAllCpuSamples, - profileAppStartUp, cpuProfileFlameChartHelp, cpuProfileProcessingTime, openDataFile, diff --git a/packages/devtools_app/lib/src/shared/analytics/constants/_performance_constants.dart b/packages/devtools_app/lib/src/shared/analytics/constants/_performance_constants.dart index 1b548e82749..3b9bafb1a62 100644 --- a/packages/devtools_app/lib/src/shared/analytics/constants/_performance_constants.dart +++ b/packages/devtools_app/lib/src/shared/analytics/constants/_performance_constants.dart @@ -20,9 +20,6 @@ enum PerformanceEvents { disableOpacityLayers, disablePhysicalShapeLayers, countWidgetBuilds('trackRebuildWidgets'), - collectRasterStats, - clearRasterStats, - fullScreenLayerImage, clearRebuildStats, perfettoLoadTrace, perfettoScrollToTimeRange, @@ -55,6 +52,5 @@ enum PerformanceDocs { shaderCompilationDocs, shaderCompilationDocsTooltipLink, impellerDocsLink, - impellerDocsLinkFromRasterStats, platformChannelsDocs, } diff --git a/packages/devtools_app/lib/src/shared/analytics/metrics.dart b/packages/devtools_app/lib/src/shared/analytics/metrics.dart index 70a846566ce..595c0a1de61 100644 --- a/packages/devtools_app/lib/src/shared/analytics/metrics.dart +++ b/packages/devtools_app/lib/src/shared/analytics/metrics.dart @@ -74,7 +74,6 @@ class InspectorScreenMetrics extends ScreenAnalyticsMetrics { }); static const summaryTreeGaId = 0; - static const detailsTreeGaId = 1; /// The number of times the root has been set, since the /// [InspectorTreeController] with id [inspectorTreeControllerId], has been diff --git a/packages/devtools_app/lib/src/shared/charts/chart_trace.dart b/packages/devtools_app/lib/src/shared/charts/chart_trace.dart index d95f0b2e861..9fa2910ce31 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart_trace.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart_trace.dart @@ -34,7 +34,6 @@ class PaintCharacteristics { this.concentricCenterDiameter = 1, this.width = 1, this.height = 1, - this.fixedMinY, this.fixedMaxY, }); @@ -48,14 +47,9 @@ class PaintCharacteristics { this.concentricCenterDiameter = 1, this.width = 1, this.height = 1, - this.fixedMinY, this.fixedMaxY, }); - /// If specified Y scale is computed and min value is fixed. - /// Will assert if new data point is less than min specified. - double? fixedMinY; - /// If specified Y scale is computed and max value is fixed. /// Will assert if new data point is more than max specified. double? fixedMaxY; @@ -88,11 +82,7 @@ class PaintCharacteristics { } class Trace { - Trace(this.controller, this._chartType, this.characteristics) { - final minY = characteristics.fixedMinY ?? 0.0; - final maxY = characteristics.fixedMaxY ?? 0.0; - yAxis = AxisScale(minY, maxY, 30); - } + Trace(this.controller, this._chartType, this.characteristics); final ChartController controller; @@ -113,6 +103,7 @@ class Trace { /// ------------------------------- late bool stacked; + // ignore: unused-code, false positive used in asserts. String? name; double dataYMax = 0; @@ -155,8 +146,6 @@ class Trace { ChartType get chartType => _chartType; - AxisScale? yAxis; - void clearData() { _data.clear(); controller.dirty = true; @@ -173,7 +162,6 @@ class Trace { ); } else if (datum.y > dataYMax) { dataYMax = datum.y.toDouble(); - yAxis = AxisScale(0, dataYMax, 30); } if (datum.y > controller.yMaxValue) { @@ -298,7 +286,6 @@ class AxisScale { fraction = 0; } return AxisScale._( - minPoint: minPoint, maxPoint: maxPoint, maxTicks: maxTicks, tickSpacing: tickSpacing, @@ -308,7 +295,6 @@ class AxisScale { } AxisScale._({ - required this.minPoint, required this.maxPoint, required this.maxTicks, required this.tickSpacing, @@ -316,8 +302,10 @@ class AxisScale { required this.labelTicks, }); - final double minPoint, maxPoint; + @visibleForTesting + final double maxPoint; + @visibleForTesting final double maxTicks; final double tickSpacing; diff --git a/packages/devtools_app/lib/src/shared/charts/flame_chart.dart b/packages/devtools_app/lib/src/shared/charts/flame_chart.dart index bff073a30dd..5456792780d 100644 --- a/packages/devtools_app/lib/src/shared/charts/flame_chart.dart +++ b/packages/devtools_app/lib/src/shared/charts/flame_chart.dart @@ -17,7 +17,6 @@ import '../primitives/extent_delegate_list.dart'; import '../primitives/flutter_widgets/linked_scroll_controller.dart'; import '../primitives/trees.dart'; import '../primitives/utils.dart'; -import '../ui/colors.dart'; import '../ui/common_widgets.dart'; import '../ui/search.dart'; import '../ui/utils.dart'; @@ -60,16 +59,8 @@ abstract class FlameChart extends StatefulWidget { }); static const minZoomLevel = 1.0; - static const zoomMultiplier = 0.01; static const minScrollOffset = 0.0; static const rowOffsetForBottomPadding = 1; - static const rowOffsetForSectionSpacer = 1; - - /// Maximum scroll delta allowed for scroll wheel based zooming. - /// - /// This isn't really needed but is a reasonable for safety in case we - /// aren't handling some mouse based scroll wheel behavior well, etc. - static const maxScrollWheelDelta = 20.0; final T data; @@ -103,7 +94,7 @@ abstract class FlameChartState< V extends FlameChartDataMixin > extends State - with AutoDisposeMixin, FlameChartColorMixin, TickerProviderStateMixin { + with AutoDisposeMixin, TickerProviderStateMixin { int get rowOffsetForTopPadding => 2; // The "top" positional value for each flame chart node will be 0.0 because @@ -112,8 +103,6 @@ abstract class FlameChartState< final rows = >[]; - final sections = []; - // ignore: dispose-fields, false positive. Disposed via autoDisposeFocusNode. final focusNode = FocusNode(debugLabel: 'flame-chart'); @@ -158,31 +147,6 @@ abstract class FlameChartState< double get widthWithZoom => contentWidthWithZoom + widget.startInset + widget.endInset; - TimeRange get visibleTimeRange { - final horizontalScrollOffset = horizontalControllerGroup.offset; - final startMicros = horizontalScrollOffset < widget.startInset - ? startTimeOffset - : startTimeOffset + - (horizontalScrollOffset - widget.startInset) / - currentZoom / - startingPxPerMicro; - - final endMicros = - startTimeOffset + - (horizontalScrollOffset - widget.startInset + widget.containerWidth) / - currentZoom / - startingPxPerMicro; - - return TimeRange(start: startMicros.round(), end: endMicros.round()); - } - - /// Starting pixels per microsecond in order to fit all the data in view at - /// start. - double get startingPxPerMicro => - widget.startingContentWidth / widget.time.duration.inMicroseconds; - - int get startTimeOffset => widget.time.start; - double get maxZoomLevel { // The max zoom level is hit when 1 microsecond is the width of each grid // interval (this may bottom out at 2 micros per interval due to rounding). @@ -368,13 +332,12 @@ abstract class FlameChartState< @mustCallSuper void initFlameChartElements() { rows.clear(); - sections.clear(); } void expandRows(int newRowLength) { final currentLength = rows.length; for (int i = currentLength; i < newRowLength; i++) { - rows.add(FlameChartRow(i)); + rows.add(FlameChartRow()); } } @@ -580,46 +543,6 @@ abstract class FlameChartState< await scrollToX(offset); } - Future zoomAndScrollToData({ - required int startMicros, - required int durationMicros, - required V data, - bool scrollVertically = true, - bool jumpZoom = false, - }) async { - await zoomToTimeRange( - startMicros: startMicros, - durationMicros: durationMicros, - jump: jumpZoom, - ); - // Call these in a post frame callback so that the scroll controllers have - // had time to update their scroll extents. Otherwise, we can hit a race - // where are trying to scroll to an offset that is beyond what the scroll - // controller thinks its max scroll extent is. - WidgetsBinding.instance.addPostFrameCallback((_) { - if (mounted) { - unawaited(scrollHorizontallyToData(data)); - if (scrollVertically) unawaited(scrollVerticallyToData(data)); - } - }); - } - - Future zoomToTimeRange({ - required int startMicros, - required int durationMicros, - double? targetWidth, - bool jump = false, - }) async { - targetWidth ??= widget.containerWidth * 0.8; - final startingWidth = durationMicros * startingPxPerMicro; - final zoom = targetWidth / startingWidth; - final mouseXForZoom = - (startMicros - startTimeOffset + durationMicros / 2) * - startingPxPerMicro + - widget.startInset; - await zoomTo(zoom, forceMouseX: mouseXForZoom, jump: jump); - } - bool isDataVerticallyInView(V data); bool isDataHorizontallyInView(V data); @@ -696,9 +619,6 @@ class ScrollingFlameChartRowState> chartStartInset: widget.startInset, chartWidth: widget.width, ), - zoom: widget.zoom, - chartStartInset: widget.startInset, - chartWidth: widget.width, ); _initNodeDataList(); @@ -748,9 +668,6 @@ class ScrollingFlameChartRowState> chartStartInset: widget.startInset, chartWidth: widget.width, ), - zoom: widget.zoom, - chartStartInset: widget.startInset, - chartWidth: widget.width, ); } _resetHovered(); @@ -976,25 +893,9 @@ extension FlameChartUtils on Never { } } -class FlameChartSection { - FlameChartSection(this.index, {required this.startRow, required this.endRow}); - - final int index; - - /// Start row (inclusive) for this section. - final int startRow; - - /// End row (exclusive) for this section. - final int endRow; -} - class FlameChartRow> { - FlameChartRow(this.index); - final nodes = >[]; - final int index; - /// Adds a node to [nodes] and assigns `this` to the node's `row` property. /// /// If [index] is specified and in range of the list, [node] will be added at @@ -1005,7 +906,6 @@ class FlameChartRow> { } else { nodes.add(node); } - node.row = this; } } @@ -1043,8 +943,6 @@ class FlameChartNode> { final void Function(T) onSelected; final bool selectable; - late FlameChartRow row; - int sectionIndex; Widget buildWidget({ @@ -1147,54 +1045,17 @@ class FlameChartNode> { } } -mixin FlameChartColorMixin { - ColorPair nextUiColor(int row) { - return uiColorPalette[row % uiColorPalette.length]; - } - - ColorPair nextRasterColor(int row) { - return rasterColorPalette[row % rasterColorPalette.length]; - } - - ColorPair nextAsyncColor(int row) { - return asyncColorPalette[row % asyncColorPalette.length]; - } - - ColorPair nextUnknownColor(int row) { - return unknownColorPalette[row % unknownColorPalette.length]; - } -} - /// [ExtentDelegate] implementation for the case where size and position is /// known for each list item. class _ScrollingFlameChartRowExtentDelegate extends ExtentDelegate { - _ScrollingFlameChartRowExtentDelegate({ - required this.nodeIntervals, - required this.zoom, - required this.chartStartInset, - required this.chartWidth, - }) { + _ScrollingFlameChartRowExtentDelegate({required this.nodeIntervals}) { recompute(); } List nodeIntervals = []; - double zoom; - - double chartStartInset; - - double chartWidth; - - void recomputeWith({ - required List nodeIntervals, - required double zoom, - required double chartStartInset, - required double chartWidth, - }) { + void recomputeWith({required List nodeIntervals}) { this.nodeIntervals = nodeIntervals; - this.zoom = zoom; - this.chartStartInset = chartStartInset; - this.chartWidth = chartWidth; recompute(); } diff --git a/packages/devtools_app/lib/src/shared/charts/treemap.dart b/packages/devtools_app/lib/src/shared/charts/treemap.dart index 9b0db9a44ac..f6a77d5c415 100644 --- a/packages/devtools_app/lib/src/shared/charts/treemap.dart +++ b/packages/devtools_app/lib/src/shared/charts/treemap.dart @@ -6,7 +6,6 @@ import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; -import 'package:logging/logging.dart'; import '../primitives/byte_utils.dart'; import '../primitives/trees.dart'; @@ -15,8 +14,6 @@ import '../ui/common_widgets.dart'; enum PivotType { pivotByMiddle, pivotBySize } -final _log = Logger('charts/treemap'); - class Treemap extends StatefulWidget { // TODO(peterdjlee): Consider auto-expanding rootNode named 'src'. const Treemap.fromRoot({ @@ -683,7 +680,10 @@ class TreemapNode extends TreeNode { }); final String name; + + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) seems like a bug. final Map childrenMap; + int byteSize; final bool showDiff; @@ -794,17 +794,6 @@ class TreemapNode extends TreeNode { return []; } - void printTree() { - printTreeHelper(this, ''); - } - - void printTreeHelper(TreemapNode root, String tabs) { - _log.info('$tabs$root'); - for (final child in root.children) { - printTreeHelper(child, '$tabs\t'); - } - } - @override String toString() { return '{name: $name, size: $byteSize}'; diff --git a/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/drag_and_drop.dart b/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/drag_and_drop.dart index 233de4798b0..9ba1f8f0aeb 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/drag_and_drop.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/drag_and_drop/drag_and_drop.dart @@ -24,8 +24,6 @@ abstract class DragAndDropManager { int get viewId => _viewId; final int _viewId; - final _dragAndDropStates = {}; - DragAndDropState? activeState; /// The method is abstract, because we want to force descendants to define it. @@ -37,18 +35,9 @@ abstract class DragAndDropManager { @mustCallSuper void dispose() { - _dragAndDropStates.clear(); activeState = null; } - void registerDragAndDrop(DragAndDropState state) { - _dragAndDropStates.add(state); - } - - void unregisterDragAndDrop(DragAndDropState state) { - _dragAndDropStates.remove(state); - } - void dragOver(double x, double y) { hitTestAndUpdateActiveId(x, y); activeState?.dragOver(); @@ -126,12 +115,10 @@ class DragAndDropState extends State { // Already registered to the right drag and drop manager, so do nothing. if (oldViewId == viewId) return; - _dragAndDropManager?.unregisterDragAndDrop(this); _dragAndDropManager = null; } _dragAndDropManager = DragAndDropManager.getInstance(viewId); - _dragAndDropManager!.registerDragAndDrop(this); } @override @@ -141,7 +128,6 @@ class DragAndDropState extends State { @override void dispose() { - _dragAndDropManager?.unregisterDragAndDrop(this); _dragAndDropManager = null; _dragging.dispose(); super.dispose(); diff --git a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart index b1f9630f12a..494869a8123 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart @@ -10,6 +10,7 @@ import 'package:logging/logging.dart'; import 'package:path/path.dart' as path; import '../../primitives/storage.dart'; +import '../../primitives/utils.dart'; final _log = Logger('_framework_initialize_desktop'); @@ -32,12 +33,11 @@ class FlutterDesktopStorage implements Storage { Future setValue(String key, String value) async { _values[key] = value; - const encoder = JsonEncoder.withIndent(' '); if (!_fileAndDirVerified) { File(_preferencesFile.path).createSync(recursive: true); _fileAndDirVerified = true; } - _preferencesFile.writeAsStringSync('${encoder.convert(_values)}\n'); + _preferencesFile.writeAsStringSync('${_values.prettyPrint()}\n'); } Map _readValues() { diff --git a/packages/devtools_app/lib/src/shared/config_specific/import_export/_file_desktop.dart b/packages/devtools_app/lib/src/shared/config_specific/import_export/_file_desktop.dart index 11179bde55d..eaa737091e2 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/import_export/_file_desktop.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/import_export/_file_desktop.dart @@ -6,18 +6,11 @@ import 'dart:typed_data'; import 'package:file/file.dart'; import 'package:file/local.dart'; -import 'package:logging/logging.dart'; -import 'package:path/path.dart' as path; - -final _log = Logger('_file_desktop'); /// Abstracted local file system access for Flutter Desktop. class FileSystemDesktop { final _fs = const LocalFileSystem(); - String exportDirectoryName({bool isMemory = false}) => - _exportDirectory(isMemory: isMemory).path; - /// Flutter Desktop MacOS systemTempDirectory is in Downloads /// for memory files location is $TMPDIR. /// Flutter Desktop Linux systemTempDirectory is \tmp @@ -54,70 +47,4 @@ class FileSystemDesktop { throw StateError('Unsupported content type: $T'); } } - - /// Returns content of filename or null if file is unknown or content empty. - String readStringFromFile(String filename, {bool isMemory = false}) { - final previousCurrentDirectory = _fs.currentDirectory; - - // TODO(terry): Use path_provider when available? - _fs.currentDirectory = _exportDirectory(isMemory: isMemory); - - final logFile = _fs.currentDirectory.childFile(filename); - - final jsonPayload = logFile.readAsStringSync(); - - _fs.currentDirectory = previousCurrentDirectory; - - return jsonPayload; - } - - /// List of files (basename only). - List list({required String prefix, bool isMemory = false}) { - final logs = []; - - try { - // TODO(terry): Use path_provider when available? - final directory = _exportDirectory(isMemory: isMemory); - - if (!directory.existsSync()) { - return logs; - } - - final allFiles = directory.listSync(followLinks: false); - for (final entry in allFiles) { - final basename = path.basename(entry.path); - if (_fs.isFileSync(entry.path) && basename.startsWith(prefix)) { - logs.add(basename); - } - } - - // Sort by newest file top-most (DateTime is in the filename). - logs.sort((a, b) => b.compareTo(a)); - } on FileSystemException catch (e, st) { - // TODO(jacobr): prompt the user to grant permission to access the - // directory if Flutter ever provides that option or consider using an - // alternate directory. This error should generally only occur on MacOS - // desktop Catalina and later where access to the Downloads folder - // is not granted by default. - _log.info(e, e, st); - } - - return logs; - } - - /// Delete exported files created for testing only. - bool deleteFile(String path, {bool isMemory = false}) { - final previousCurrentDirectory = _fs.currentDirectory; - - // TODO(terry): Use path_provider when available? - _fs.currentDirectory = _exportDirectory(isMemory: isMemory); - - if (!_fs.isFileSync(path)) return false; - - _fs.file(path).deleteSync(); - - _fs.currentDirectory = previousCurrentDirectory; - - return true; - } } diff --git a/packages/devtools_app/lib/src/shared/config_specific/import_export/import_export.dart b/packages/devtools_app/lib/src/shared/config_specific/import_export/import_export.dart index 442151fb282..eed968af961 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/import_export/import_export.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/import_export/import_export.dart @@ -113,7 +113,6 @@ extension type _DevToolsOfflineData(Map json) { enum ExportFileType { json, csv, - yaml, data, har; diff --git a/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_stub.dart b/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_stub.dart index a84be62e287..6f3dfb0a40d 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_stub.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_stub.dart @@ -7,5 +7,6 @@ import 'post_message.dart'; Stream get onPostMessage => throw UnsupportedError('unsupported platform'); +// ignore: unused-code, currently unused but an important helper to keep. void postMessage(Object? _, String _) => throw UnsupportedError('unsupported platform'); diff --git a/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart b/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart index b59605a3f95..0bbc6edeaa1 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +// ignore_for_file: unused-code, platform specific imports. + import 'dart:js_interop'; import 'package:web/web.dart'; @@ -11,7 +13,7 @@ import 'post_message.dart'; Stream get onPostMessage { return window.onMessage.map( (message) => - PostMessageEvent(origin: message.origin, data: message.data.dartify()), + PostMessageEvent(data: message.data.dartify()), ); } diff --git a/packages/devtools_app/lib/src/shared/config_specific/post_message/post_message.dart b/packages/devtools_app/lib/src/shared/config_specific/post_message/post_message.dart index bf9ba98cc7c..fc3071dd9d1 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/post_message/post_message.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/post_message/post_message.dart @@ -6,8 +6,7 @@ export '_post_message_stub.dart' if (dart.library.js_interop) '_post_message_web.dart'; class PostMessageEvent { - PostMessageEvent({required this.origin, required this.data}); + PostMessageEvent({required this.data}); - final String origin; final Object? data; } diff --git a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart index c505152acad..9751df42200 100644 --- a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart +++ b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart @@ -34,36 +34,15 @@ const inspectorRowHeight = 20.0; // TODO(kenz): extend TreeNode class to share tree logic. class InspectorTreeNode { InspectorTreeNode({ - InspectorTreeNode? parent, + this.parent, bool expandChildren = true, - this.whenDirty, }) : _children = [], - _parent = parent, _isExpanded = expandChildren; - /// Callback that is called when the node is marked as dirty. - void Function(InspectorTreeNode node)? whenDirty; - bool get showLinesToChildren { return _children.length > 1 && !_children.last.isProperty; } - bool get isDirty => _isDirty; - bool _isDirty = true; - - set isDirty(bool dirty) { - if (dirty) { - _isDirty = true; - _shouldShow = null; - if (parent != null) { - parent!.isDirty = true; - } - whenDirty?.call(this); - } else { - _isDirty = false; - } - } - /// Returns whether the node is currently visible in the tree. void updateShouldShow(bool value) { if (value != _shouldShow) { @@ -108,7 +87,6 @@ class InspectorTreeNode { set isExpanded(bool value) { if (value != _isExpanded) { _isExpanded = value; - isDirty = true; if (_shouldShow ?? false) { for (final child in children) { child.updateShouldShow(value); @@ -117,13 +95,7 @@ class InspectorTreeNode { } } - InspectorTreeNode? get parent => _parent; - InspectorTreeNode? _parent; - - set parent(InspectorTreeNode? value) { - _parent = value; - _parent?.isDirty = true; - } + InspectorTreeNode? parent; RemoteDiagnosticsNode? get diagnostic => _diagnostic; @@ -131,7 +103,6 @@ class InspectorTreeNode { final value = v!; _diagnostic = value; _isExpanded = value.childrenReady; - isDirty = true; } bool get hasPlaceholderChildren { @@ -142,18 +113,15 @@ class InspectorTreeNode { child.parent = null; final removed = _children.remove(child); assert(removed); - isDirty = true; } void appendChild(InspectorTreeNode child) { _children.add(child); child.parent = this; - isDirty = true; } void clearChildren() { _children.clear(); - isDirty = true; } } diff --git a/packages/devtools_app/lib/src/shared/console/primitives/eval_history.dart b/packages/devtools_app/lib/src/shared/console/primitives/eval_history.dart index a94ec5f1a21..39c7763af88 100644 --- a/packages/devtools_app/lib/src/shared/console/primitives/eval_history.dart +++ b/packages/devtools_app/lib/src/shared/console/primitives/eval_history.dart @@ -2,11 +2,14 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +import 'package:meta/meta.dart'; + /// Store and manipulate the expression evaluation history. class EvalHistory { var _historyPosition = -1; /// Get the expression evaluation history. + @visibleForTesting List get evalHistory => _evalHistory.toList(); final _evalHistory = []; diff --git a/packages/devtools_app/lib/src/shared/console/widgets/description.dart b/packages/devtools_app/lib/src/shared/console/widgets/description.dart index 1d914afccd6..2344aed2cce 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/description.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/description.dart @@ -111,7 +111,7 @@ class DiagnosticsNodeDescription extends StatelessWidget { TextSpan(text: name, style: textStyle), ); } else { - final approximateIconWidth = IconKind.info.icon.width + iconPadding; + final approximateIconWidth = infoIcon.width + iconPadding; // When there is no name, an icon will be shown with the text spans. spanWidth += approximateIconWidth; diff --git a/packages/devtools_app/lib/src/shared/console/widgets/display_provider.dart b/packages/devtools_app/lib/src/shared/console/widgets/display_provider.dart index 4e389efb5e3..91fd7ac7fee 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/display_provider.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/display_provider.dart @@ -255,6 +255,7 @@ class DapDisplayProvider extends StatelessWidget { }); final DapObjectNode node; + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/6056) implement onTap. final VoidCallback onTap; @override diff --git a/packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart b/packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart index e7c07d9704a..ea2437306cd 100644 --- a/packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart +++ b/packages/devtools_app/lib/src/shared/console/widgets/evaluate.dart @@ -46,8 +46,6 @@ class ExpressionEvalFieldState extends State final _autoCompleteController = AutoCompleteController(evalTextFieldKey); - int historyPosition = -1; - String _activeWord = ''; List _matches = []; @@ -318,7 +316,6 @@ class ExpressionEvalFieldState extends State serviceConnection.consoleService.appendStdio('> $expressionText\n'); setState(() { - historyPosition = -1; serviceConnection.appState.evalHistory.pushEvalHistory(expressionText); }); diff --git a/packages/devtools_app/lib/src/shared/development_helpers.dart b/packages/devtools_app/lib/src/shared/development_helpers.dart index 42c10f19f9d..072e8049905 100644 --- a/packages/devtools_app/lib/src/shared/development_helpers.dart +++ b/packages/devtools_app/lib/src/shared/development_helpers.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 or at https://developers.google.com/open-source/licenses/bsd. +// ignore_for_file: unused-code, intentional helpers for development only. import 'dart:async'; import 'package:devtools_shared/devtools_extensions.dart'; diff --git a/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart b/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart index f6cc1a7f01f..5b0ac2a9129 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart @@ -8,7 +8,6 @@ library; import 'dart:async'; import 'package:devtools_app_shared/utils.dart'; -import 'package:flutter/foundation.dart'; import 'package:vm_service/vm_service.dart'; import '../globals.dart'; @@ -33,9 +32,7 @@ class DartObjectNode extends TreeNode { this.artificialValue = false, this.isRerootable = false, }) : _offset = offset, - _childCount = childCount { - indentChildren = ref?.diagnostic?.style != DiagnosticsTreeStyle.flat; - } + _childCount = childCount; /// Creates a variable from a value that must be an VM service type or a /// primitive type. diff --git a/packages/devtools_app/lib/src/shared/diagnostics/diagnostics_node.dart b/packages/devtools_app/lib/src/shared/diagnostics/diagnostics_node.dart index 9f07dbbdb40..128f2cba2be 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/diagnostics_node.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/diagnostics_node.dart @@ -83,8 +83,6 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { /// This node's parent (if it's been set). RemoteDiagnosticsNode? parent; - Future? propertyDocFuture; - List? cachedProperties; /// Service used to retrieve more detailed information about the value of @@ -101,8 +99,6 @@ class RemoteDiagnosticsNode extends DiagnosticableTree { // TODO(albertusangga): Refactor to cleaner/more robust solution bool get isFlex => ['Row', 'Column', 'Flex'].contains(widgetRuntimeType); - bool get isBox => json['isBox'] == true; - int? get flexFactor => json['flexFactor'] as int?; FlexFit get flexFit => deserializeFlexFit(json['flexFit'] as String?); diff --git a/packages/devtools_app/lib/src/shared/editor/api_classes.dart b/packages/devtools_app/lib/src/shared/editor/api_classes.dart index b30b3a32c20..3231269b698 100644 --- a/packages/devtools_app/lib/src/shared/editor/api_classes.dart +++ b/packages/devtools_app/lib/src/shared/editor/api_classes.dart @@ -139,7 +139,6 @@ abstract class Field { static const isEditable = 'isEditable'; static const isNullable = 'isNullable'; static const isRequired = 'isRequired'; - static const kind = 'kind'; static const line = 'line'; static const name = 'name'; static const options = 'options'; diff --git a/packages/devtools_app/lib/src/shared/editor/editor_client.dart b/packages/devtools_app/lib/src/shared/editor/editor_client.dart index 951790de13d..9dab74c5fad 100644 --- a/packages/devtools_app/lib/src/shared/editor/editor_client.dart +++ b/packages/devtools_app/lib/src/shared/editor/editor_client.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +// ignore_for_file: unused-code, this file represents the full editor API. + import 'dart:async'; import 'package:devtools_app_shared/service.dart'; diff --git a/packages/devtools_app/lib/src/shared/feature_flags.dart b/packages/devtools_app/lib/src/shared/feature_flags.dart index 937c75108a6..ca86bb35c1b 100644 --- a/packages/devtools_app/lib/src/shared/feature_flags.dart +++ b/packages/devtools_app/lib/src/shared/feature_flags.dart @@ -93,6 +93,7 @@ extension FeatureFlags on Never { static final _flutterChannelFlags = {}; /// A helper to print the status of all the feature flags. + // ignore: unused-code, debug only method to be used as needed. static void debugPrintFeatureFlags({ConnectedApp? connectedApp}) { for (final entry in _booleanFlags) { _log.config(entry.toString()); @@ -141,6 +142,7 @@ class BooleanFeatureFlag { /// TODO(https://github.com/flutter/devtools/issues/9439): Restrict features /// based on the user's Dart version instead of Flutter version to allow for /// shared experiments across Dart and Flutter. +// ignore: unused-code, we want to support this type of feature flag. class FlutterChannelFeatureFlag { const FlutterChannelFeatureFlag({ required this.name, diff --git a/packages/devtools_app/lib/src/shared/framework/app_error_handling.dart b/packages/devtools_app/lib/src/shared/framework/app_error_handling.dart index 68ad3953e21..dbfbf6a5ba1 100644 --- a/packages/devtools_app/lib/src/shared/framework/app_error_handling.dart +++ b/packages/devtools_app/lib/src/shared/framework/app_error_handling.dart @@ -109,7 +109,10 @@ Future _reportError( } } +// ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) seems like a bug. SingleMapping? _cachedJsSourceMapping; + +// ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) seems like a bug. SingleMapping? _cachedWasmSourceMapping; Future _fetchSourceMapping() async { diff --git a/packages/devtools_app/lib/src/shared/framework/routing.dart b/packages/devtools_app/lib/src/shared/framework/routing.dart index d72d7e1c196..eb4f84f9bc9 100644 --- a/packages/devtools_app/lib/src/shared/framework/routing.dart +++ b/packages/devtools_app/lib/src/shared/framework/routing.dart @@ -34,6 +34,7 @@ class DevToolsRouteInformationParser DevToolsRouteInformationParser() : _testQueryParams = null; @visibleForTesting + // ignore: unused-code, used in packages/devtools_test DevToolsRouteInformationParser.test(this._testQueryParams); /// Query parameters that can be set on DevTools routes for testing purposes. @@ -103,6 +104,7 @@ class DevToolsRouterDelegate extends RouterDelegate _isTestMode = false; @visibleForTesting + // ignore: unused-code, used in packages/devtools_test DevToolsRouterDelegate.test(this._getPage, [GlobalKey? key]) : navigatorKey = key ?? GlobalKey(), _isTestMode = true; @@ -273,6 +275,7 @@ class DevToolsRouterDelegate extends RouterDelegate await updateArgsIfChanged({'uri': null}); } + @visibleForTesting Future replaceState(DevToolsNavigationState state) async { final currentConfig = currentConfiguration!; await _replaceStack( @@ -380,8 +383,6 @@ class DevToolsNavigationState { @override String toString() => _state.toString(); - - Map toJson() => _state; } /// Mixin that gives controllers the ability to respond to changes in router diff --git a/packages/devtools_app/lib/src/shared/framework/screen.dart b/packages/devtools_app/lib/src/shared/framework/screen.dart index 2bfe341a5fd..6e090ff7bc0 100644 --- a/packages/devtools_app/lib/src/shared/framework/screen.dart +++ b/packages/devtools_app/lib/src/shared/framework/screen.dart @@ -73,6 +73,8 @@ enum ScreenMetaData { debugger( 'debugger', title: 'Debugger', + // TODO(kenz): see if we can use a meterial icon or an asset icon so that + // we can remove the Octicons font family. icon: Octicons.bug, requiresDebugBuild: true, tutorialVideoTimestamp: '?t=513', diff --git a/packages/devtools_app/lib/src/shared/globals.dart b/packages/devtools_app/lib/src/shared/globals.dart index d4f70552d42..23f23257e7f 100644 --- a/packages/devtools_app/lib/src/shared/globals.dart +++ b/packages/devtools_app/lib/src/shared/globals.dart @@ -5,7 +5,6 @@ import 'package:devtools_app_shared/service.dart'; import 'package:devtools_app_shared/utils.dart'; import 'package:flutter/foundation.dart'; -import 'package:flutter/widgets.dart'; import '../extensions/extension_service.dart'; import '../screens/debugger/breakpoint_manager.dart'; @@ -26,6 +25,8 @@ import 'primitives/storage.dart'; /// Whether this DevTools build is external. bool get isExternalBuild => _isExternalBuild; bool _isExternalBuild = true; + +// ignore: unused-code, used in g3. void setInternalBuild() => _isExternalBuild = false; ScreenControllers get screenControllers => @@ -70,9 +71,6 @@ EvalService get evalService => globals[EvalService] as EvalService; ExtensionService get extensionService => globals[ExtensionService] as ExtensionService; -GlobalKey get navigatorKey => - globals[GlobalKey] as GlobalKey; - /// Whether DevTools is being run in integration test mode. bool get integrationTestMode => _integrationTestMode; bool _integrationTestMode = false; @@ -83,6 +81,7 @@ void setIntegrationTestMode() { /// Whether DevTools is being run in a test environment. bool get testMode => _testMode; bool _testMode = false; +@visibleForTesting void setTestMode() { _testMode = true; } @@ -90,6 +89,7 @@ void setTestMode() { /// Whether DevTools is being run as a stager app. bool get stagerMode => _stagerMode; bool _stagerMode = false; +@visibleForTesting void setStagerMode() { if (!kReleaseMode) { _stagerMode = true; diff --git a/packages/devtools_app/lib/src/shared/http/_http_cookies.dart b/packages/devtools_app/lib/src/shared/http/_http_cookies.dart index ca49ed825c7..d0274d393b2 100644 --- a/packages/devtools_app/lib/src/shared/http/_http_cookies.dart +++ b/packages/devtools_app/lib/src/shared/http/_http_cookies.dart @@ -21,7 +21,6 @@ class Cookie { String? _name; String? _value; DateTime? expires; - int? maxAge; String? domain; String? path; bool httpOnly = false; @@ -30,16 +29,6 @@ class Cookie { String? get name => _name; String? get value => _value; - set name(String? newName) { - _validateName(newName); - _name = newName; - } - - set value(String? newValue) { - _validateValue(newValue); - _value = newValue; - } - Cookie.fromSetCookieValue(String value) { // Parse the 'set-cookie' header value. _parseSetCookieValue(value); @@ -105,8 +94,6 @@ class Cookie { } if (name == "expires") { expires = HttpDate._parseCookieDate(value); - } else if (name == "max-age") { - maxAge = int.parse(value); } else if (name == "domain") { domain = value; } else if (name == "path") { diff --git a/packages/devtools_app/lib/src/shared/http/constants.dart b/packages/devtools_app/lib/src/shared/http/constants.dart index abc7c09b687..7695a56be60 100644 --- a/packages/devtools_app/lib/src/shared/http/constants.dart +++ b/packages/devtools_app/lib/src/shared/http/constants.dart @@ -4,47 +4,20 @@ enum HttpRequestDataKeys { connectionInfo, - remoteAddress, - localPort, contentLength, - startedDateTime, - time, request, method, - url, - httpVersion, cookies, headers, - queryString, - postData, - mimeType, text, - headersSize, - bodySize, followRedirects, maxRedirects, persistentConnection, proxyDetails, - proxy, - type, error, response, - status, statusCode, - statusText, redirects, - redirectURL, - cache, - timings, - blocked, - dns, - connect, - send, - wait, - receive, - ssl, - connection, - comment, isolateId, uri, id, @@ -55,10 +28,6 @@ enum HttpRequestDataKeys { compressionState, isRedirect, reasonPhrase, - queryParameters, - content, - size, - connectionId, requestBody, responseBody, endTime, @@ -67,13 +36,3 @@ enum HttpRequestDataKeys { username, isDirect, } - -enum HttpRequestDataValues { json } - -class HttpRequestDataDefaults { - static const none = 'None'; - static const error = 'Error'; - static const httpVersion = 'HTTP/2.0'; - static const json = 'json'; - static const httpProfileRequest = '@HttpProfileRequest'; -} diff --git a/packages/devtools_app/lib/src/shared/http/http_request_data.dart b/packages/devtools_app/lib/src/shared/http/http_request_data.dart index 81ec0d35528..619db21ec71 100644 --- a/packages/devtools_app/lib/src/shared/http/http_request_data.dart +++ b/packages/devtools_app/lib/src/shared/http/http_request_data.dart @@ -315,6 +315,7 @@ class DartIOHttpRequestData extends NetworkRequest { Map? get responseHeaders => _request.response?.headers; /// The query parameters for the request. + @visibleForTesting Map? get queryParameters => _request.uri.queryParameters; @override diff --git a/packages/devtools_app/lib/src/shared/managers/banner_messages.dart b/packages/devtools_app/lib/src/shared/managers/banner_messages.dart index 536dc11c2ef..d9c32156880 100644 --- a/packages/devtools_app/lib/src/shared/managers/banner_messages.dart +++ b/packages/devtools_app/lib/src/shared/managers/banner_messages.dart @@ -319,6 +319,7 @@ class BannerWarning extends BannerMessage { }) : super(messageType: BannerMessageType.warning); } +// ignore: unused-code, this is a type of message we want to support. class BannerInfo extends BannerMessage { const BannerInfo({ required super.key, @@ -521,34 +522,6 @@ The $codeType DevTools debugger is in maintenance mode. For the best debugging e ); } -class LegacyInspectorWarningMessage extends BannerWarning { - LegacyInspectorWarningMessage({required super.screenId}) - : super( - key: buildKey(screenId), - buildTextSpans: (context) => [ - const TextSpan( - text: - 'The legacy inspector will be removed in a future release. ' - 'Please enable the new inspector in the inspector settings. ' - 'If there is an issue preventing you from using the new ' - 'inspector, please file a ', - ), - GaLinkTextSpan( - link: const GaLink( - display: 'bug', - url: 'https://github.com/flutter/devtools/issues/new', - ), - context: context, - style: Theme.of(context).linkTextStyle, - ), - const TextSpan(text: '.'), - ], - ); - - static Key buildKey(String screenId) => - Key('LegacyInspectorWarningMessage - $screenId'); -} - void maybePushDebugModePerformanceMessage(String screenId) { if (offlineDataController.showingOfflineData.value) return; if (serviceConnection.serviceManager.connectedApp?.isDebugFlutterAppNow ?? @@ -577,10 +550,6 @@ void pushDebuggerIdeRecommendationMessage(String screenId) { ); } -void pushLegacyInspectorWarning(String screenId) { - bannerMessages.addMessage(LegacyInspectorWarningMessage(screenId: screenId)); -} - extension BannerMessageThemeExtension on ThemeData { TextStyle get warningMessageLinkStyle => regularTextStyle.copyWith( decoration: TextDecoration.underline, diff --git a/packages/devtools_app/lib/src/shared/managers/script_manager.dart b/packages/devtools_app/lib/src/shared/managers/script_manager.dart index 02179f73d30..29d7a01d72c 100644 --- a/packages/devtools_app/lib/src/shared/managers/script_manager.dart +++ b/packages/devtools_app/lib/src/shared/managers/script_manager.dart @@ -76,17 +76,12 @@ class ScriptManager extends DisposableController Future getScript(ScriptRef scriptRef) { return _scriptCache.getScript(_service, _currentIsolate, scriptRef); } - - Script? getScriptByUri(String uri) { - return _scriptCache.getScriptByUri(uri); - } } class _ScriptCache { _ScriptCache(); final _scripts = {}; - final _uriToScript = {}; final _inProgress = >{}; /// Return a cached [Script] for the given [ScriptRef], returning null @@ -95,10 +90,6 @@ class _ScriptCache { return _scripts[scriptRef.id]; } - Script? getScriptByUri(String uri) { - return _uriToScript[uri]; - } - /// Retrieve the [Script] for the given [ScriptRef]. /// /// This caches the script lookup for future invocations. @@ -130,7 +121,6 @@ class _ScriptCache { unawaited( scriptFuture.then((script) { scripts[scriptId] = script; - _uriToScript[script.uri!] = script; }), ); diff --git a/packages/devtools_app/lib/src/shared/memory/class_name.dart b/packages/devtools_app/lib/src/shared/memory/class_name.dart index c1e9f7db2ce..c966b4c8a7c 100644 --- a/packages/devtools_app/lib/src/shared/memory/class_name.dart +++ b/packages/devtools_app/lib/src/shared/memory/class_name.dart @@ -143,6 +143,7 @@ class HeapClassName with Serializable { /// Whether a class can hold a reference to an object /// without preventing garbage collection. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907) false positive. late final isWeak = _isWeak(className, library); /// See [isWeak]. diff --git a/packages/devtools_app/lib/src/shared/memory/heap_data.dart b/packages/devtools_app/lib/src/shared/memory/heap_data.dart index 54fc1fb5316..5c4bf6f9117 100644 --- a/packages/devtools_app/lib/src/shared/memory/heap_data.dart +++ b/packages/devtools_app/lib/src/shared/memory/heap_data.dart @@ -25,7 +25,6 @@ class HeapData { Future get calculate => _calculated.future; final _calculated = Completer(); - bool get isCalculated => _calculated.isCompleted; ClassDataList? classes; diff --git a/packages/devtools_app/lib/src/shared/memory/heap_graph_loader.dart b/packages/devtools_app/lib/src/shared/memory/heap_graph_loader.dart index 7a9bedbe6b1..e2dea14be25 100644 --- a/packages/devtools_app/lib/src/shared/memory/heap_graph_loader.dart +++ b/packages/devtools_app/lib/src/shared/memory/heap_graph_loader.dart @@ -5,6 +5,7 @@ import 'dart:async'; import 'package:file_selector/file_selector.dart'; +import 'package:meta/meta.dart'; import 'package:vm_service/vm_service.dart'; import '../../screens/memory/shared/primitives/memory_timeline.dart'; @@ -34,6 +35,7 @@ class HeapGraphLoaderRuntime extends HeapGraphLoader { class HeapGraphLoaderFile implements HeapGraphLoader { HeapGraphLoaderFile(this.file); + @visibleForTesting HeapGraphLoaderFile.fromPath(String path) : file = XFile(path); final XFile file; diff --git a/packages/devtools_app/lib/src/shared/memory/retaining_path.dart b/packages/devtools_app/lib/src/shared/memory/retaining_path.dart index b9e7d40e9be..9e68390a9fc 100644 --- a/packages/devtools_app/lib/src/shared/memory/retaining_path.dart +++ b/packages/devtools_app/lib/src/shared/memory/retaining_path.dart @@ -3,7 +3,7 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; +import 'package:flutter/foundation.dart'; import 'package:vm_service/vm_service.dart'; import '../primitives/utils.dart'; @@ -17,12 +17,15 @@ bool Function(List? list1, List? list2) _listEquality = @visibleForTesting class DebugRetainingPathUsage { /// Path is expected to be constructed for each object. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907) false positive. int constructed = 0; /// Only unique paths are stored. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907) false positive. int stored = 0; /// Only displayed paths are stringified. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9907) false positive. int stringified = 0; } @@ -42,12 +45,10 @@ class PathFromRoot { PathFromRoot._( this.path, { @visibleForTesting bool debugOmitClassesInRetainingPath = false, - }) : assert(() { - debugUsage.constructed++; - return true; - }()), - hashCode = path.isEmpty ? _hashOfEmptyPath : Object.hashAll(path), - classes = debugOmitClassesInRetainingPath ? const {} : path.toSet(); + }) : hashCode = path.isEmpty ? _hashOfEmptyPath : Object.hashAll(path), + classes = debugOmitClassesInRetainingPath ? const {} : path.toSet() { + if (kDebugMode) debugUsage.constructed++; + } /// For objects directly referenced from root. const PathFromRoot._empty() @@ -100,11 +101,10 @@ class PathFromRoot { ); instances.add(newInstance); - assert(() { + if (kDebugMode) { debugUsage.stored++; assert(instances.length == debugUsage.stored); - return true; - }()); + } return newInstance; } @@ -208,10 +208,7 @@ class PathFromRoot { required String delimiter, required bool inverted, }) { - assert(() { - debugUsage.stringified++; - return true; - }()); + if (kDebugMode) debugUsage.stringified++; // Trailing separator is here to show object is referenced by root. data = data.joinWith( delimiter, diff --git a/packages/devtools_app/lib/src/shared/preferences/_logging_preferences.dart b/packages/devtools_app/lib/src/shared/preferences/_logging_preferences.dart index 713c6ece0ed..5257ce06fa9 100644 --- a/packages/devtools_app/lib/src/shared/preferences/_logging_preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/_logging_preferences.dart @@ -6,8 +6,6 @@ part of 'preferences.dart'; class LoggingPreferencesController extends DisposableController with AutoDisposeControllerMixin { - final retentionLimitTitle = 'Limit for the number of logs retained.'; - /// The number of logs to retain on the logging table. final retentionLimit = ValueNotifier(_defaultRetentionLimit); diff --git a/packages/devtools_app/lib/src/shared/preferences/preferences.dart b/packages/devtools_app/lib/src/shared/preferences/preferences.dart index 403c4e43319..27191349d24 100644 --- a/packages/devtools_app/lib/src/shared/preferences/preferences.dart +++ b/packages/devtools_app/lib/src/shared/preferences/preferences.dart @@ -36,9 +36,6 @@ const _thirdPartyPathSegment = 'third_party'; /// DevTools preferences for experimental features. enum _ExperimentPreferences { - /// Deprecated, we ignore this key in favor of [wasmOptOut]. - wasm, - /// Whether a user has opted out of the dart2wasm experiment. wasmOptOut; @@ -140,13 +137,6 @@ class PreferencesController extends DisposableController setGlobal(PreferencesController, this); } - /// Enables the wasm experiment in storage. - /// - /// This is used to persist the preference across reloads. - Future enableWasmInStorage() async { - await storage.setValue(_ExperimentPreferences.wasm.storageKey, 'true'); - } - Future _initDarkMode() async { final darkModeValue = await storage.getValue( _UiPreferences.darkMode.storageKey, diff --git a/packages/devtools_app/lib/src/shared/primitives/ansi_utils.dart b/packages/devtools_app/lib/src/shared/primitives/ansi_utils.dart index 397c88f20aa..dba6a6ce137 100644 --- a/packages/devtools_app/lib/src/shared/primitives/ansi_utils.dart +++ b/packages/devtools_app/lib/src/shared/primitives/ansi_utils.dart @@ -292,7 +292,6 @@ class _TextPacket { _PacketKind kind; String text = ''; - String url = ''; } /// Chunk of styled text stored in a Dart friendly format. @@ -327,31 +326,4 @@ class StyledText { final List? bgColor; bool get bold => (textStyle & kBold) == kBold; - bool get dim => (textStyle & kDim) == kDim; - bool get italic => (textStyle & kItalic) == kItalic; - bool get underline => (textStyle & kUnderline) == kUnderline; - bool get strikethrough => (textStyle & kStrikethrough) == kStrikethrough; - bool get blink => (textStyle & kBlink) == kBlink; - bool get reverse => (textStyle & kReverse) == kReverse; - bool get invisible => (textStyle & kInvisible) == kInvisible; - - bool get hasStyling => textStyle != 0 || fgColor != null || bgColor != null; - - String get describeStyle { - String hex(int value) => value.toRadixString(16).padLeft(2, '0'); - String color(List rgb) => '${hex(rgb[0])}${hex(rgb[2])}${hex(rgb[2])}'; - - return [ - if (bgColor != null) 'background #${color(bgColor!)}', - if (fgColor != null) 'color #${color(fgColor!)}', - if (bold) 'bold', - if (dim) 'dim', - if (italic) 'italic', - if (underline) 'underline', - if (strikethrough) 'strikethrough', - if (blink) 'blink', - if (reverse) 'reverse', - if (invisible) 'invisible', - ].join(', '); - } } diff --git a/packages/devtools_app/lib/src/shared/primitives/custom_pointer_scroll_view.dart b/packages/devtools_app/lib/src/shared/primitives/custom_pointer_scroll_view.dart index 3794f1c02be..caa711f1baa 100644 --- a/packages/devtools_app/lib/src/shared/primitives/custom_pointer_scroll_view.dart +++ b/packages/devtools_app/lib/src/shared/primitives/custom_pointer_scroll_view.dart @@ -3,6 +3,7 @@ // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. // ignore_for_file: avoid-explicit-type-declaration, forked code from Flutter framework. +// ignore_for_file: unused-code, forked code from Flutter framework. import 'dart:async'; import 'dart:math' as math; diff --git a/packages/devtools_app/lib/src/shared/primitives/flutter_widgets/linked_scroll_controller.dart b/packages/devtools_app/lib/src/shared/primitives/flutter_widgets/linked_scroll_controller.dart index ad1412178b0..391d7cfacb0 100644 --- a/packages/devtools_app/lib/src/shared/primitives/flutter_widgets/linked_scroll_controller.dart +++ b/packages/devtools_app/lib/src/shared/primitives/flutter_widgets/linked_scroll_controller.dart @@ -5,6 +5,8 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; +// ignore_for_file: unused-code, this is forked file, leave untouched. + // This file was originally forked from package:flutter_widgets. Note that the // source may diverge over time. diff --git a/packages/devtools_app/lib/src/shared/primitives/list_queue_value_notifier.dart b/packages/devtools_app/lib/src/shared/primitives/list_queue_value_notifier.dart index afa0bec60aa..5888d132981 100644 --- a/packages/devtools_app/lib/src/shared/primitives/list_queue_value_notifier.dart +++ b/packages/devtools_app/lib/src/shared/primitives/list_queue_value_notifier.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +// ignore_for_file: unused-code, helpful notifer class that will likely be reused. + import 'dart:collection'; import 'package:flutter/foundation.dart'; diff --git a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart index f6de6c579c3..582f0ea022a 100644 --- a/packages/devtools_app/lib/src/shared/primitives/simple_items.dart +++ b/packages/devtools_app/lib/src/shared/primitives/simple_items.dart @@ -30,7 +30,6 @@ const closureName = ''; const anonymousClosureName = ''; const _memoryDocUrl = 'https://docs.flutter.dev/tools/devtools/memory'; -const _consoleDocUrl = 'https://docs.flutter.dev/tools/devtools/console'; const _inspectorDocUrl = 'https://docs.flutter.dev/tools/devtools/inspector'; /// Some links to documentation. @@ -41,7 +40,6 @@ enum DocLinks { profile(_memoryDocUrl, 'profile-memory-tab'), diff(_memoryDocUrl, 'diff-snapshots-tab'), trace(_memoryDocUrl, 'trace-instances-tab'), - console(_consoleDocUrl, null), inspectorPackageDirectories(_inspectorDocUrl, 'package-directories'); const DocLinks(this.url, this.hash); diff --git a/packages/devtools_app/lib/src/shared/primitives/trace_event.dart b/packages/devtools_app/lib/src/shared/primitives/trace_event.dart index 2967fb6a722..105c093ce8d 100644 --- a/packages/devtools_app/lib/src/shared/primitives/trace_event.dart +++ b/packages/devtools_app/lib/src/shared/primitives/trace_event.dart @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +// ignore_for_file: unused-code, this model class follows the Chrome Trace Event format. + /// A single trace event that follows the Chrome Trace Event Format. /// /// See Chrome Trace Event Format documentation: diff --git a/packages/devtools_app/lib/src/shared/primitives/trees.dart b/packages/devtools_app/lib/src/shared/primitives/trees.dart index a86d9720849..ea8d3d358cc 100644 --- a/packages/devtools_app/lib/src/shared/primitives/trees.dart +++ b/packages/devtools_app/lib/src/shared/primitives/trees.dart @@ -2,26 +2,21 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. +// ignore_for_file: unused-code, retain methods for completeness of TreeNode model class. + import 'dart:collection'; import 'dart:math'; -/// Non-UI specific tree code should live in this file. -/// -/// This file does not have direct dependencies on dart:html and therefore -/// allows for testing to be done on the VM. - -// TODO(kenz): look into consolidating logic between this file and -// ui/trees.dart, which houses generic tree types vs the base classes in this -// file. +// Non-UI specific tree code should live in this file. +// +// This file does not have direct dependencies on dart:html and therefore +// allows for testing to be done on the VM. abstract class TreeNode> { T? parent; final children = []; - // TODO(jacobr) should impact depth. - bool indentChildren = true; - /// Index in `parent.children`. int index = -1; diff --git a/packages/devtools_app/lib/src/shared/primitives/utils.dart b/packages/devtools_app/lib/src/shared/primitives/utils.dart index a1073e882a6..892835c1864 100644 --- a/packages/devtools_app/lib/src/shared/primitives/utils.dart +++ b/packages/devtools_app/lib/src/shared/primitives/utils.dart @@ -6,7 +6,6 @@ // libraries in this package. import 'dart:async'; -import 'dart:collection'; import 'dart:convert'; import 'dart:math'; @@ -122,20 +121,6 @@ String durationText( return '$durationStr${includeUnit ? ' ${unit.display}' : ''}'; } -T? nullSafeMin(T? a, T? b) { - if (a == null || b == null) { - return a ?? b; - } - return min(a, b); -} - -T? nullSafeMax(T? a, T? b) { - if (a == null || b == null) { - return a ?? b; - } - return max(a, b); -} - double logBase({required int x, required int base}) { return log(x) / log(base); } @@ -145,20 +130,6 @@ int log2(num x) => logBase(x: x.floor(), base: 2).floor(); int roundToNearestPow10(int x) => pow(10, logBase(x: x, base: 10).ceil()).floor(); -void executeWithDelay( - Duration delay, - void Function() callback, { - bool executeNow = false, -}) { - if (executeNow || delay.inMilliseconds <= 0) { - callback(); - } else { - Timer(delay, () { - callback(); - }); - } -} - Future delayToReleaseUiThread({int micros = 0}) async { // Even with a delay of 0 microseconds, awaiting this delay is enough to free // the UI thread to update the UI. @@ -201,39 +172,6 @@ Future timeout(Future operation, int timeoutMillis) => ), ]); -String longestFittingSubstring( - String originalText, - num maxWidth, - List asciiMeasurements, - num Function(int value) slowMeasureFallback, -) { - if (originalText.isEmpty) return originalText; - - final runes = originalText.runes.toList(); - - num currentWidth = 0; - - int i = 0; - while (i < runes.length) { - final rune = runes[i]; - final charWidth = rune < 128 - ? asciiMeasurements[rune] - : slowMeasureFallback(rune); - if (currentWidth + charWidth > maxWidth) { - break; - } - // [currentWidth] is approximate due to ignoring kerning. - currentWidth += charWidth; - i++; - } - - return originalText.substring(0, i); -} - -/// Whether a given code unit is a letter (A-Z or a-z). -bool isLetter(int codeUnit) => - (codeUnit >= 65 && codeUnit <= 90) || (codeUnit >= 97 && codeUnit <= 122); - /// Returns a simplified version of a StackFrame name. /// /// Given an input such as @@ -256,87 +194,6 @@ String getSimpleStackFrameName(String? name) { return newName.split('&').last; } -/// Return a Stream that fires events whenever any of the three given parameter -/// streams fire. -Stream combineStreams(Stream a, Stream b, Stream c) { - late StreamController controller; - - StreamSubscription? asub; - StreamSubscription? bsub; - StreamSubscription? csub; - - controller = StreamController( - onListen: () { - asub = a.listen(controller.add); - bsub = b.listen(controller.add); - csub = c.listen(controller.add); - }, - onCancel: () { - unawaited(asub?.cancel()); - unawaited(bsub?.cancel()); - unawaited(csub?.cancel()); - }, - ); - - return controller.stream; -} - -class Property { - Property(this._value); - - final _changeController = StreamController.broadcast(); - T _value; - - T get value => _value; - - set value(T newValue) { - if (newValue != _value) { - _value = newValue; - _changeController.add(newValue); - } - } - - Stream get onValueChange => _changeController.stream; -} - -/// Batch up calls to the given closure. Repeated calls to [invoke] will -/// overwrite the closure to be called. We'll delay at least [minDelay] before -/// calling the closure, but will not delay more than [maxDelay]. -class DelayedTimer { - DelayedTimer(this.minDelay, this.maxDelay); - - final Duration minDelay; - final Duration maxDelay; - - VoidCallback? _closure; - - Timer? _minTimer; - Timer? _maxTimer; - - void invoke(VoidCallback closure) { - _closure = closure; - - if (_minTimer == null) { - _minTimer = Timer(minDelay, _fire); - _maxTimer = Timer(maxDelay, _fire); - } else { - _minTimer!.cancel(); - _minTimer = Timer(minDelay, _fire); - } - } - - void _fire() { - _minTimer?.cancel(); - _minTimer = null; - - _maxTimer?.cancel(); - _maxTimer = null; - - _closure!(); - _closure = null; - } -} - /// These utilities are ported from the Flutter IntelliJ plugin. /// /// With Dart's terser JSON support, these methods don't provide much value so @@ -356,7 +213,7 @@ class JsonUtils { } /// Add pretty print for a JSON payload. -extension JsonMap on Map { +extension JsonObjectExtension on Object? { String prettyPrint() => const JsonEncoder.withIndent(' ').convert(this); } @@ -574,80 +431,6 @@ double safeDivide( return ifNotFinite; } -/// A change reporter that can be listened to. -/// -/// Unlike [ChangeNotifier], [Reporter] stores listeners in a set. This allows -/// O(1) addition/removal of listeners and O(N) listener dispatch. -/// -/// For small N (~ <20), [ChangeNotifier] implementations can be faster because -/// array access is more efficient than set access. Use [Reporter] instead in -/// cases where N is larger. -/// -/// When disposing, any object with a registered listener should `unregister` -/// itself. -/// -/// Only the object that created this reporter should call [notify]. -class Reporter implements Listenable { - final _listeners = {}; - - /// Adds [callback] to this reporter. - /// - /// If [callback] is already registered to this reporter, nothing will happen. - @override - void addListener(VoidCallback callback) { - _listeners.add(callback); - } - - /// Removes the listener [callback]. - @override - void removeListener(VoidCallback callback) { - _listeners.remove(callback); - } - - /// Whether or not this object has any listeners registered. - bool get hasListeners => _listeners.isNotEmpty; - - /// Notifies all listeners of a change. - /// - /// This does not do any change propagation, so if - /// a notification callback leads to a change in the listeners, - /// only the original listeners will be called. - void notify() { - for (final callback in _listeners.toList()) { - callback(); - } - } - - @override - String toString() => describeIdentity(this); -} - -/// A [Reporter] that notifies when its [value] changes. -/// -/// Similar to [ValueNotifier], but with the same performance -/// benefits as [Reporter]. -/// -/// For small N (~ <20), [ValueNotifier] implementations can be faster because -/// array access is more efficient than set access. Use [ValueReporter] instead -/// in cases where N is larger. -class ValueReporter extends Reporter implements ValueListenable { - ValueReporter(this._value); - - @override - T get value => _value; - - set value(T value) { - if (_value == value) return; - _value = value; - notify(); - } - - T _value; - - @override - String toString() => '${describeIdentity(this)}($value)'; -} - String toStringAsFixed(double num, [int fractionDigit = 1]) { return num.toStringAsFixed(fractionDigit); } @@ -664,8 +447,10 @@ extension SafeListOperations on List { } extension SafeAccess on Iterable { + // ignore: unused-code, false positive "this getter is used but never assigned a value" T? get safeFirst => isNotEmpty ? first : null; + // ignore: unused-code, false positive "this getter is used but never assigned a value" T? get safeLast => isNotEmpty ? last : null; } @@ -707,8 +492,6 @@ class LineRange { int get size => end - begin + 1; - bool contains(num target) => target >= begin && target <= end; - @override String toString() => 'LineRange($begin, $end)'; @@ -763,80 +546,6 @@ class DebugTimingLogger { } } -/// Compute a simple moving average. -/// [averagePeriod] default period is 50 units collected. -/// [ratio] default percentage is 50% range is 0..1 -class MovingAverage { - MovingAverage({ - this.averagePeriod = 50, - this.ratio = 0.5, - List? newDataSet, - }) : assert(ratio >= 0 && ratio <= 1, 'Value ratio $ratio is not 0 to 1.') { - if (newDataSet != null) { - var initialDataSet = newDataSet; - final count = newDataSet.length; - if (count > averagePeriod) { - initialDataSet = newDataSet.sublist(count - averagePeriod); - } - - dataSet.addAll(initialDataSet); - for (final value in dataSet) { - averageSum += value; - } - } - } - - final dataSet = Queue(); - - /// Total collected items in the X axis (time) used to compute moving average. - /// Default 100 periods for memory profiler 1-2 periods / seconds. - final int averagePeriod; - - /// Ratio of first item in dataSet when comparing to last - mean - /// e.g., 2 is 50% (dataSet.first ~/ ratioSpike). - final double ratio; - - /// Sum of total heap used and external heap for unitPeriod. - int averageSum = 0; - - /// Reset moving average data. - void clear() { - dataSet.clear(); - averageSum = 0; - } - - // Update the sum to get a new mean. - void add(int value) { - averageSum += value; - dataSet.add(value); - - // Update dataSet of values to not exceede the period of the moving average - // to compute the normal mean. - if (dataSet.length > averagePeriod) { - averageSum -= dataSet.removeFirst(); - } - } - - double get mean { - final periodRange = min(averagePeriod, dataSet.length); - return periodRange > 0 ? averageSum / periodRange : 0; - } - - /// If the last - mean > ratioSpike% of first value in period we're spiking. - bool hasSpike() { - final first = dataSet.safeFirst ?? 0; - final last = dataSet.safeLast ?? 0; - - return last - mean > (first * ratio); - } - - /// If the mean @ ratioSpike% > last value in period we're dipping. - bool isDipping() { - final last = dataSet.safeLast ?? 0; - return (mean * ratio) > last; - } -} - List textSpansFromAnsi(String input, TextStyle defaultStyle) { final parser = AnsiParser(input); return parser.parse().map((entry) { @@ -1024,20 +733,6 @@ extension ListExtension on List { T get second => this[1]; T get third => this[2]; - - T get fourth => this[3]; - - T get fifth => this[4]; - - List allIndicesWhere(bool Function(T element) test) { - final indices = []; - for (var i = 0; i < length; i++) { - if (test(this[i])) { - indices.add(i); - } - } - return indices; - } } extension NullableListExtension on List? { diff --git a/packages/devtools_app/lib/src/shared/server/server.dart b/packages/devtools_app/lib/src/shared/server/server.dart index 9bf135157d6..8b40cbbf2da 100644 --- a/packages/devtools_app/lib/src/shared/server/server.dart +++ b/packages/devtools_app/lib/src/shared/server/server.dart @@ -165,8 +165,6 @@ void logWarning(Response? response, String apiType) { extension ResponseExtension on Response { bool get statusOk => statusCode == 200; - bool get statusForbidden => statusCode == 403; - bool get statusError => statusCode == 500; } class ServerConnectionStorage implements Storage { diff --git a/packages/devtools_app/lib/src/shared/table/_tree_table.dart b/packages/devtools_app/lib/src/shared/table/_tree_table.dart index 22db562d84c..8630bfb596b 100644 --- a/packages/devtools_app/lib/src/shared/table/_tree_table.dart +++ b/packages/devtools_app/lib/src/shared/table/_tree_table.dart @@ -121,6 +121,7 @@ class TreeTable> extends StatefulWidget { class TreeTableState> extends State> with TickerProviderStateMixin, AutoDisposeMixin { + @visibleForTesting FocusNode? get focusNode => _focusNode; // ignore: dispose-fields, false positive. Disposed via autoDisposeFocusNode. diff --git a/packages/devtools_app/lib/src/shared/ui/colors.dart b/packages/devtools_app/lib/src/shared/ui/colors.dart index 2232fd6d282..a330946505b 100644 --- a/packages/devtools_app/lib/src/shared/ui/colors.dart +++ b/packages/devtools_app/lib/src/shared/ui/colors.dart @@ -12,19 +12,8 @@ import 'utils.dart'; const mainUiColor = Color(0xFF88B1DE); const mainRasterColor = Color(0xFF2C5DAA); -const mainUnknownColor = Color(0xFFCAB8E9); const mainAsyncColor = Color(0xFF80CBC4); -final uiColorPalette = [ - const ColorPair(background: mainUiColor, foreground: Colors.black), - const ColorPair(background: Color(0xFF6793CD), foreground: Colors.black), -]; - -final rasterColorPalette = [ - const ColorPair(background: mainRasterColor, foreground: Colors.white), - const ColorPair(background: Color(0xFF386EB6), foreground: Colors.white), -]; - // TODO(jacobr): merge this with other color scheme extensions. extension FlameChartColorScheme on ColorScheme { Color get selectedFrameBackgroundColor => @@ -34,18 +23,6 @@ extension FlameChartColorScheme on ColorScheme { isLight ? Colors.black54 : const Color.fromARGB(255, 200, 200, 200); } -// Teal 200, 400 - see https://material.io/design/color/#tools-for-picking-colors. -const asyncColorPalette = [ - ColorPair(background: mainAsyncColor, foreground: Colors.black), - ColorPair(background: Color(0xFF26A69A), foreground: Colors.black), -]; - -// Slight variation on Deep purple 100, 300 - see https://material.io/design/color/#tools-for-picking-colors. -const unknownColorPalette = [ - ColorPair(background: mainUnknownColor, foreground: Colors.black), - ColorPair(background: Color(0xFF9D84CA), foreground: Colors.black), -]; - const uiJankColor = Color(0xFFF5846B); const rasterJankColor = Color(0xFFC3595A); const shaderCompilationColor = ColorPair( @@ -111,7 +88,6 @@ extension DevToolsColorExtension on ColorScheme { Color get grey => const Color.fromARGB(255, 128, 128, 128); Color get green => isLight ? const Color(0xFF006B5F) : const Color(0xFF54DBC8); - Color get overlayShadowColor => const Color.fromRGBO(0, 0, 0, 0.5); // Deep link header is slightly darker than the default surface color. See // comment at: https://github.com/flutter/devtools/pull/7443/files#r1538361768 Color get deeplinkTableHeaderColor => surface.darken(); diff --git a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart index dda95c8ad5d..6fd5b74fed5 100644 --- a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart +++ b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart @@ -21,7 +21,6 @@ import '../diagnostics/dart_object_node.dart'; import '../diagnostics/tree_builder.dart'; import '../framework/routing.dart'; import '../globals.dart'; -import '../primitives/flutter_widgets/linked_scroll_controller.dart'; import '../primitives/utils.dart'; import '../utils/utils.dart'; @@ -33,36 +32,6 @@ void setAssumedMonospaceCharacterWidth(double width) { _assumedMonospaceCharacterWidth = width; } -/// Creates a semibold version of [style]. -TextStyle semibold(TextStyle style) => - style.copyWith(fontWeight: FontWeight.w600); - -/// Creates a version of [style] that uses the primary color of [context]. -/// -/// When the app is in dark mode, it instead uses the accent color. -TextStyle primaryColor(TextStyle style, BuildContext context) { - final theme = Theme.of(context); - return style.copyWith( - color: (theme.brightness == Brightness.light) - ? theme.primaryColor - : theme.colorScheme.secondary, - fontWeight: FontWeight.w400, - ); -} - -/// Creates a version of [style] that uses the lighter primary color of -/// [context]. -/// -/// In dark mode, the light primary color still has enough contrast to be -/// visible, so we continue to use it. -TextStyle primaryColorLight(TextStyle style, BuildContext context) { - final theme = Theme.of(context); - return style.copyWith( - color: theme.primaryColorLight, - fontWeight: FontWeight.w300, - ); -} - class GaDevToolsButton extends DevToolsButton { GaDevToolsButton({ super.key, @@ -257,52 +226,6 @@ class StartStopRecordingButton extends GaDevToolsButton { final bool recording; } -/// Button to start recording data. -/// -/// * `recording`: Whether recording is in progress. -/// * `minScreenWidthForText`: The minimum width the button can be before the text is -/// omitted. -/// * `labelOverride`: Optional alternative text to use for the button. -/// * `onPressed`: The callback to be called upon pressing the button. -class RecordButton extends GaDevToolsButton { - RecordButton({ - super.key, - required bool recording, - required VoidCallback onPressed, - required super.gaScreen, - required super.gaSelection, - super.minScreenWidthForText, - super.tooltip = 'Start recording', - String? labelOverride, - }) : super( - onPressed: recording ? null : onPressed, - icon: Icons.fiber_manual_record, - label: labelOverride ?? 'Record', - ); -} - -/// Button to stop recording data. -/// -/// * `recording`: Whether recording is in progress. -/// * `minScreenWidthForText`: The minimum width the button can be before the text is -/// omitted. -/// * `onPressed`: The callback to be called upon pressing the button. -class StopRecordingButton extends GaDevToolsButton { - StopRecordingButton({ - super.key, - required bool recording, - required VoidCallback? onPressed, - required super.gaScreen, - required super.gaSelection, - super.minScreenWidthForText, - super.tooltip = 'Stop recording', - }) : super( - onPressed: !recording ? null : onPressed, - icon: Icons.stop, - label: 'Stop', - ); -} - class SettingsOutlinedButton extends GaDevToolsButton { SettingsOutlinedButton({ super.key, @@ -474,38 +397,6 @@ class DevToolsSwitch extends StatelessWidget { } } -class ProcessingInfo extends StatelessWidget { - const ProcessingInfo({ - super.key, - required this.progressValue, - required this.processedObject, - }); - - final double? progressValue; - - final String processedObject; - - @override - Widget build(BuildContext context) { - return Center( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - 'Processing $processedObject', - style: Theme.of(context).regularTextStyle, - ), - const SizedBox(height: defaultSpacing), - SizedBox( - width: 200.0, - child: LinearProgressIndicator(value: progressValue), - ), - ], - ), - ); - } -} - /// Common button for exiting offline mode. class ExitOfflineButton extends StatelessWidget { const ExitOfflineButton({required this.gaScreen, super.key}); @@ -741,33 +632,6 @@ abstract class ScaffoldAction extends StatelessWidget { } } -/// Button to open related information / documentation. -/// -/// [tooltip] specifies the hover text for the button. -/// [link] is the link that should be opened when the button is clicked. -class InformationButton extends StatelessWidget { - const InformationButton({ - super.key, - required this.tooltip, - required this.link, - }); - - final String tooltip; - - final String link; - - @override - Widget build(BuildContext context) { - return Tooltip( - message: tooltip, - child: IconButton( - icon: const Icon(Icons.help_outline), - onPressed: () async => await launchUrlWithErrorHandling(link), - ), - ); - } -} - class OutlinedRowGroup extends StatelessWidget { const OutlinedRowGroup({super.key, required this.children, this.borderColor}); @@ -812,29 +676,6 @@ class ThickDivider extends StatelessWidget { } } -BoxDecoration roundedBorderDecoration(BuildContext context) => BoxDecoration( - border: Border.all(color: Theme.of(context).focusColor), - borderRadius: defaultBorderRadius, -); - -class LeftBorder extends StatelessWidget { - const LeftBorder({super.key, this.child}); - - final Widget? child; - - @override - Widget build(BuildContext context) { - final leftBorder = Border( - left: BorderSide(color: Theme.of(context).focusColor), - ); - - return Container( - decoration: BoxDecoration(border: leftBorder), - child: child, - ); - } -} - /// The golden ratio. /// /// Makes for nice-looking rectangles. @@ -882,39 +723,6 @@ class CenteredCircularProgressIndicator extends StatelessWidget { } } -/// An extension on [LinkedScrollControllerGroup] to facilitate having the -/// scrolling widgets auto scroll to the bottom on new content. -/// -/// This extension serves the same function as the [ScrollControllerAutoScroll] -/// extension above, but we need to implement these methods again as an -/// extension on [LinkedScrollControllerGroup] because individual -/// [ScrollController]s are intentionally inaccessible from -/// [LinkedScrollControllerGroup]. -extension LinkedScrollControllerGroupExtension on LinkedScrollControllerGroup { - bool get atScrollBottom { - final pos = position; - return pos.pixels == pos.maxScrollExtent; - } - - /// Scroll the content to the bottom using the app's default animation - /// duration and curve.. - void autoScrollToBottom() async { - await animateTo( - position.maxScrollExtent, - duration: rapidDuration, - curve: defaultCurve, - ); - - // Scroll again if we've received new content in the interim. - if (hasAttachedControllers) { - final pos = position; - if (pos.pixels != pos.maxScrollExtent) { - jumpTo(pos.maxScrollExtent); - } - } - } -} - class BreadcrumbNavigator extends StatelessWidget { const BreadcrumbNavigator.builder({ super.key, @@ -1101,7 +909,6 @@ class JsonViewer extends StatefulWidget { class _JsonViewerState extends State { late Future _initializeTree; late DartObjectNode variable; - static const jsonEncoder = JsonEncoder.withIndent(' '); Future _buildAndExpand(DartObjectNode variable) async { // Build the root node @@ -1237,14 +1044,13 @@ class _JsonViewerState extends State { String copyJsonData(DartObjectNode copiedVariable) { // Check if service connection is active if (serviceConnection.serviceManager.connectedState.value.connected) { - return jsonEncoder.convert( - serviceConnection.serviceManager.service!.fakeServiceCache - .instanceToJson(copiedVariable.value as Instance), - ); + return serviceConnection.serviceManager.service!.fakeServiceCache + .instanceToJson(copiedVariable.value as Instance) + .prettyPrint(); } // Directly convert object to JSON if not connected - return const JsonEncoder.withIndent(' ').convert(copiedVariable.value); + return copiedVariable.value.prettyPrint(); } } @@ -1689,117 +1495,6 @@ class CheckboxSetting extends StatelessWidget { } } -/// A widget that represents a switch setting and automatically updates for -/// value changes to [notifier]. -class SwitchSetting extends StatelessWidget { - const SwitchSetting({ - super.key, - required this.notifier, - required this.title, - this.tooltip, - this.onChanged, - this.gaScreen, - this.gaItem, - this.activeColor, - this.inactiveColor, - this.minScreenWidthForText, - }); - - final ValueNotifier notifier; - - final String title; - - final String? tooltip; - - final void Function(bool newValue)? onChanged; - - final String? gaScreen; - - final String? gaItem; - - final Color? activeColor; - - final Color? inactiveColor; - - final double? minScreenWidthForText; - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return maybeWrapWithTooltip( - tooltip: tooltip, - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - if (isScreenWiderThan(context, minScreenWidthForText)) - Flexible( - child: RichText( - overflow: TextOverflow.visible, - maxLines: 3, - text: TextSpan(text: title, style: theme.regularTextStyle), - ), - ), - NotifierSwitch( - padding: const EdgeInsets.only(left: borderPadding), - activeColor: activeColor, - inactiveColor: inactiveColor, - notifier: notifier, - onChanged: (bool? value) { - final gaScreen = this.gaScreen; - final gaItem = this.gaItem; - if (gaScreen != null && gaItem != null) { - ga.select(gaScreen, '$gaItem-$value'); - } - final onChanged = this.onChanged; - if (value != null) { - onChanged?.call(value); - } - }, - ), - ], - ), - ); - } -} - -class PubWarningText extends StatelessWidget { - const PubWarningText({super.key}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final isFlutterApp = - serviceConnection.serviceManager.connectedApp!.isFlutterAppNow == true; - final sdkName = isFlutterApp ? 'Flutter' : 'Dart'; - final minSdkVersion = isFlutterApp ? '2.8.0' : '2.15.0'; - return SelectionArea( - child: Text.rich( - TextSpan( - text: - 'Warning: you should no longer be launching DevTools from' - ' pub.\n\n', - style: theme.subtleTextStyle.copyWith(color: theme.colorScheme.error), - children: [ - TextSpan( - text: - 'DevTools version 2.8.0 will be the last version to ' - 'be shipped on pub. As of $sdkName\nversion >= ' - '$minSdkVersion, DevTools should be launched by running ' - 'the ', - style: theme.subtleTextStyle, - ), - TextSpan( - text: '`dart devtools`', - style: theme.subtleFixedFontStyle, - ), - TextSpan(text: '\ncommand.', style: theme.subtleTextStyle), - ], - ), - ), - ); - } -} - class BlinkingIcon extends StatefulWidget { const BlinkingIcon({ super.key, diff --git a/packages/devtools_app/lib/src/shared/ui/filter.dart b/packages/devtools_app/lib/src/shared/ui/filter.dart index f4a517fd248..7ec4eacda1a 100644 --- a/packages/devtools_app/lib/src/shared/ui/filter.dart +++ b/packages/devtools_app/lib/src/shared/ui/filter.dart @@ -169,6 +169,7 @@ mixin FilterControllerMixin on DisposableController queryFilterArgs.forEach((key, value) => value.reset()); } + @visibleForTesting void resetFilter() { _resetToDefaultFilter(); _activeFilter.value = Filter( diff --git a/packages/devtools_app/lib/src/shared/ui/icons.dart b/packages/devtools_app/lib/src/shared/ui/icons.dart index 9feaa28877e..63da28c5ff6 100644 --- a/packages/devtools_app/lib/src/shared/ui/icons.dart +++ b/packages/devtools_app/lib/src/shared/ui/icons.dart @@ -16,40 +16,6 @@ import 'package:flutter/material.dart'; import '../../screens/inspector/layout_explorer/ui/widgets_theme.dart'; import 'colors.dart'; -class CustomIcon extends StatelessWidget { - const CustomIcon({ - super.key, - required this.kind, - required this.text, - this.isAbstract = false, - }); - - final IconKind kind; - final String text; - final bool isAbstract; - - AssetImageIcon get baseIcon => kind.icon; - - @override - Widget build(BuildContext context) { - return SizedBox( - width: baseIcon.width, - height: baseIcon.height, - child: Stack( - alignment: AlignmentDirectional.center, - children: [ - baseIcon, - Text( - text, - textAlign: TextAlign.center, - style: const TextStyle(fontSize: 9.0, color: Color(0xFF231F20)), - ), - ], - ), - ); - } -} - /// An icon with one character class CircleIcon extends StatelessWidget { const CircleIcon({ @@ -87,23 +53,6 @@ class CircleIcon extends StatelessWidget { class CustomIconMaker { final iconCache = {}; - Widget? getCustomIcon( - String fromText, { - IconKind? kind, - bool isAbstract = false, - }) { - final theKind = kind ?? IconKind.classIcon; - if (fromText.isEmpty) { - return null; - } - - final text = fromText[0].toUpperCase(); - final mapKey = '${text}_${theKind.name}_$isAbstract'; - return iconCache.putIfAbsent(mapKey, () { - return CustomIcon(kind: theKind, text: text, isAbstract: isAbstract); - }); - } - Widget? fromWidgetName(String? name) { if (name == null) { return null; @@ -131,10 +80,6 @@ class CustomIconMaker { }); } - CustomIcon fromInfo(String name) { - return getCustomIcon(name, kind: IconKind.info) as CustomIcon; - } - bool isAlphabetic(int char) { return (char < '0'.codeUnitAt(0) || char > '9'.codeUnitAt(0)) && char != '_'.codeUnitAt(0) && @@ -142,41 +87,7 @@ class CustomIconMaker { } } -class IconKind { - const IconKind(this.name, this.icon, [AssetImageIcon? abstractIcon]) - : abstractIcon = abstractIcon ?? icon; - - static IconKind classIcon = const IconKind( - 'class', - AssetImageIcon(asset: 'icons/custom/class.png'), - AssetImageIcon(asset: 'icons/custom/class_abstract.png'), - ); - static IconKind field = const IconKind( - 'fields', - AssetImageIcon(asset: 'icons/custom/fields.png'), - ); - static IconKind interface = const IconKind( - 'interface', - AssetImageIcon(asset: 'icons/custom/interface.png'), - ); - static IconKind method = const IconKind( - 'method', - AssetImageIcon(asset: 'icons/custom/method.png'), - AssetImageIcon(asset: 'icons/custom/method_abstract.png'), - ); - static IconKind property = const IconKind( - 'property', - AssetImageIcon(asset: 'icons/custom/property.png'), - ); - static IconKind info = const IconKind( - 'info', - AssetImageIcon(asset: 'icons/custom/info.png'), - ); - - final String name; - final AssetImageIcon icon; - final AssetImageIcon abstractIcon; -} +const infoIcon = AssetImageIcon(asset: 'icons/custom/info.png'); class ColorIcon extends StatelessWidget { const ColorIcon(this.color, {super.key}); @@ -281,11 +192,4 @@ class FlutterMaterialIcons { class Octicons { static const bug = IconData(61714, fontFamily: 'Octicons'); - static const info = IconData(61778, fontFamily: 'Octicons'); - static const deviceMobile = IconData(61739, fontFamily: 'Octicons'); - static const fileZip = IconData(61757, fontFamily: 'Octicons'); - static const clippy = IconData(61724, fontFamily: 'Octicons'); - static const package = IconData(61812, fontFamily: 'Octicons'); - static const dashboard = IconData(61733, fontFamily: 'Octicons'); - static const pulse = IconData(61823, fontFamily: 'Octicons'); } diff --git a/packages/devtools_app/lib/src/shared/ui/search.dart b/packages/devtools_app/lib/src/shared/ui/search.dart index cce643767ff..573d0e016cc 100644 --- a/packages/devtools_app/lib/src/shared/ui/search.dart +++ b/packages/devtools_app/lib/src/shared/ui/search.dart @@ -25,7 +25,6 @@ import 'common_widgets.dart'; /// Top 10 matches to display in auto-complete overlay. const defaultTopMatchesLimit = 10; -int topMatchesLimit = defaultTopMatchesLimit; final _log = Logger('packages/devtools_app/lib/src/shared/ui/search'); @@ -59,6 +58,7 @@ mixin SearchControllerMixin } String get search => _searchNotifier.value; + @visibleForTesting bool get isSearchInProgress => _searchInProgress.value; final _searchMatches = ValueNotifier>([]); @@ -378,12 +378,6 @@ class AutoCompleteState extends State with AutoDisposeMixin { final areaHeight = offset.dy; final maxAreaForPopup = areaHeight - tileEntryHeight; - // TODO(terry): Scrolling doesn't work so max popup height is also total - // matches to use. - topMatchesLimit = min( - defaultTopMatchesLimit, - (maxAreaForPopup / tileEntryHeight) - 1, // zero based. - ).truncate(); // Total tiles visible. final totalTiles = bottom @@ -533,7 +527,6 @@ class EditingParts { /// Parsing characters looking for valid names e.g., /// [ _ | a..z | A..Z ] [ _ | a..z | A..Z | 0..9 ]+ -const asciiSpace = 32; const ascii0 = 48; const ascii9 = 57; const asciiUnderscore = 95; diff --git a/packages/devtools_app/lib/src/shared/ui/utils.dart b/packages/devtools_app/lib/src/shared/ui/utils.dart index bf82e99d997..56f428f31f9 100644 --- a/packages/devtools_app/lib/src/shared/ui/utils.dart +++ b/packages/devtools_app/lib/src/shared/ui/utils.dart @@ -283,6 +283,7 @@ final class ScreenSize { ScreenSize._({required this.height, required this.width}); + // ignore: unused-code, fundamental part of this class. final MediaSize height; final MediaSize width; diff --git a/packages/devtools_app/lib/src/shared/utils/utils.dart b/packages/devtools_app/lib/src/shared/utils/utils.dart index b19bd582841..2d797672b94 100644 --- a/packages/devtools_app/lib/src/shared/utils/utils.dart +++ b/packages/devtools_app/lib/src/shared/utils/utils.dart @@ -12,6 +12,7 @@ import 'dart:math'; import 'package:devtools_app_shared/service.dart'; import 'package:devtools_app_shared/ui.dart'; import 'package:devtools_app_shared/utils.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -31,10 +32,7 @@ final _log = Logger('lib/src/shared/utils'); /// Logging to debug console only in debug runs. void debugLogger(String message) { - assert(() { - _log.info(message); - return true; - }()); + if (kDebugMode) _log.info(message); } /// Whether DevTools is using a dark theme. @@ -288,6 +286,7 @@ Future launchUrlWithErrorHandling(String url) async { /// /// This class may be helpful when sets of work need to be done over a list, /// while avoiding blocking the UI thread. +// ignore: unused-code, this is a helpful utility, use it where we need it next. class InterruptableChunkWorker { InterruptableChunkWorker({ int chunkSize = _defaultChunkSize, diff --git a/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_test.dart b/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_test.dart index 6a7d1ed95be..01d911527e9 100644 --- a/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_test.dart +++ b/packages/devtools_app/test/screens/cpu_profiler/profiler_screen_test.dart @@ -125,8 +125,7 @@ void main() { expect(find.byType(CpuProfilerDisabled), findsOneWidget); expect(find.byType(ProfileRecordingInstructions), findsNothing); - expect(find.byType(RecordButton), findsNothing); - expect(find.byType(StopRecordingButton), findsNothing); + expect(find.byType(StartStopRecordingButton), findsNothing); expect(find.byType(ClearButton), findsNothing); expect(find.byType(CpuSamplingRateDropdown), findsNothing); expect(find.byType(OpenSaveButtonGroup), findsNothing); diff --git a/packages/devtools_app/test/shared/ansi_output_test.dart b/packages/devtools_app/test/shared/ansi_output_test.dart index 639593cdf9d..f8f4110097d 100644 --- a/packages/devtools_app/test/shared/ansi_output_test.dart +++ b/packages/devtools_app/test/shared/ansi_output_test.dart @@ -315,3 +315,37 @@ void main() { ); }); } + +extension on StyledText { + bool get dim => (textStyle & StyledText.kDim) == StyledText.kDim; + bool get italic => (textStyle & StyledText.kItalic) == StyledText.kItalic; + bool get underline => + (textStyle & StyledText.kUnderline) == StyledText.kUnderline; + bool get strikethrough => + (textStyle & StyledText.kStrikethrough) == StyledText.kStrikethrough; + bool get blink => (textStyle & StyledText.kBlink) == StyledText.kBlink; + bool get reverse => (textStyle & StyledText.kReverse) == StyledText.kReverse; + bool get invisible => + (textStyle & StyledText.kInvisible) == StyledText.kInvisible; + + bool get hasStyling => textStyle != 0 || fgColor != null || bgColor != null; + + @visibleForTesting + String get describeStyle { + String hex(int value) => value.toRadixString(16).padLeft(2, '0'); + String color(List rgb) => '${hex(rgb[0])}${hex(rgb[2])}${hex(rgb[2])}'; + + return [ + if (bgColor != null) 'background #${color(bgColor!)}', + if (fgColor != null) 'color #${color(fgColor!)}', + if (bold) 'bold', + if (dim) 'dim', + if (italic) 'italic', + if (underline) 'underline', + if (strikethrough) 'strikethrough', + if (blink) 'blink', + if (reverse) 'reverse', + if (invisible) 'invisible', + ].join(', '); + } +} diff --git a/packages/devtools_app/test/shared/primitives/utils_test.dart b/packages/devtools_app/test/shared/primitives/utils_test.dart index 3fe14a5dd13..941165d0443 100644 --- a/packages/devtools_app/test/shared/primitives/utils_test.dart +++ b/packages/devtools_app/test/shared/primitives/utils_test.dart @@ -158,20 +158,6 @@ void main() { }); }); - test('nullSafeMin', () { - expect(nullSafeMin(1, 2), equals(1)); - expect(nullSafeMin(1, null), equals(1)); - expect(nullSafeMin(null, 2), equals(2)); - expect(nullSafeMin(null, null), equals(null)); - }); - - test('nullSafeMin', () { - expect(nullSafeMax(1, 2), equals(2)); - expect(nullSafeMax(1, null), equals(1)); - expect(nullSafeMax(null, 2), equals(2)); - expect(nullSafeMax(null, null), equals(null)); - }); - test('log2', () { expect(log2(1), equals(0)); expect(log2(1.5), equals(0)); @@ -189,47 +175,6 @@ void main() { expect(roundToNearestPow10(6581), equals(10000)); }); - test('executeWithDelay', () async { - const delayMs = 500; - int n = 1; - int start = DateTime.now().millisecondsSinceEpoch; - int? end; - - // Condition n >= 2 is false, so we should execute with a delay. - executeWithDelay(const Duration(milliseconds: 500), () { - n++; - end = DateTime.now().millisecondsSinceEpoch; - }, executeNow: n >= 2); - - expect(n, equals(1)); - expect(end, isNull); - await Future.delayed(const Duration(milliseconds: 250)); - expect(n, equals(1)); - expect(end, isNull); - await Future.delayed(const Duration(milliseconds: 250)); - expect(n, equals(2)); - expect(end, isNotNull); - - // 1000ms is arbitrary. We want to ensure it doesn't run in less time than - // we requested (checked above), but we don't want to be too strict because - // shared CI CPUs can be slow. - const epsilonMs = 1000; - expect((end! - start - delayMs).abs(), lessThan(epsilonMs)); - - // Condition n >= 2 is true, so we should not execute with a delay. - end = null; - start = DateTime.now().millisecondsSinceEpoch; - executeWithDelay(const Duration(milliseconds: 500), () { - n++; - end = DateTime.now().millisecondsSinceEpoch; - }, executeNow: true); - expect(n, equals(3)); - expect(end, isNotNull); - // 400ms is arbitrary. It is less than 500, which is what matters. This - // can be increased if this test starts to flake. - expect(end! - start, lessThan(400)); - }); - test('timeout', () async { int value = 0; Future operation() async { @@ -337,107 +282,6 @@ void main() { expect(formatDateTime(DateTime(2020, 1, 16, 13)), '13:00:00.000'); }); - test('longestFittingSubstring', () { - const asciiStr = 'ComponentElement.performRebuild'; - const nonAsciiStr = 'ԪElement.updateChildԪ'; - num slowMeasureCallback(_) => 100; - - expect( - longestFittingSubstring( - asciiStr, - 0, - asciiMeasurements, - slowMeasureCallback, - ), - equals(''), - ); - expect( - longestFittingSubstring( - asciiStr, - 50, - asciiMeasurements, - slowMeasureCallback, - ), - equals('Compo'), - ); - expect( - longestFittingSubstring( - asciiStr, - 224, - asciiMeasurements, - slowMeasureCallback, - ), - equals('ComponentElement.performRebuild'), - ); - expect( - longestFittingSubstring( - asciiStr, - 300, - asciiMeasurements, - slowMeasureCallback, - ), - equals('ComponentElement.performRebuild'), - ); - - expect(nonAsciiStr.codeUnitAt(0), greaterThanOrEqualTo(128)); - expect( - longestFittingSubstring( - nonAsciiStr, - 99, - asciiMeasurements, - slowMeasureCallback, - ), - equals(''), - ); - expect( - longestFittingSubstring( - nonAsciiStr, - 100, - asciiMeasurements, - slowMeasureCallback, - ), - equals('Ԫ'), - ); - expect( - longestFittingSubstring( - nonAsciiStr, - 230, - asciiMeasurements, - slowMeasureCallback, - ), - equals('ԪElement.updateChild'), - ); - expect( - longestFittingSubstring( - nonAsciiStr, - 329, - asciiMeasurements, - slowMeasureCallback, - ), - equals('ԪElement.updateChild'), - ); - expect( - longestFittingSubstring( - nonAsciiStr, - 330, - asciiMeasurements, - slowMeasureCallback, - ), - equals('ԪElement.updateChildԪ'), - ); - }); - - test('isLetter', () { - expect(isLetter('@'.codeUnitAt(0)), isFalse); - expect(isLetter('['.codeUnitAt(0)), isFalse); - expect(isLetter('`'.codeUnitAt(0)), isFalse); - expect(isLetter('{'.codeUnitAt(0)), isFalse); - expect(isLetter('A'.codeUnitAt(0)), isTrue); - expect(isLetter('Z'.codeUnitAt(0)), isTrue); - expect(isLetter('a'.codeUnitAt(0)), isTrue); - expect(isLetter('z'.codeUnitAt(0)), isTrue); - }); - test('getSimpleStackFrameName', () { String name = '_WidgetsFlutterBinding&BindingBase&GestureBinding&ServicesBinding&' @@ -509,89 +353,6 @@ void main() { }); }); - group('Reporter', () { - int called = 0; - late Reporter reporter; - void call() { - called++; - } - - setUp(() { - called = 0; - reporter = Reporter(); - }); - test('notifies listeners', () { - expect(reporter.hasListeners, false); - reporter.addListener(call); - expect(called, 0); - expect(reporter.hasListeners, true); - reporter.notify(); - expect(called, 1); - reporter.notify(); - reporter.notify(); - expect(called, 3); - reporter.removeListener(call); - expect(called, 3); - }); - - test('notifies multiple listeners', () { - reporter.addListener(() => called++); - reporter.addListener(() => called++); - reporter.addListener(() => called++); - reporter.notify(); - expect(called, 3); - // Note that because we passed in anonymous callbacks, there's no way - // to remove them. - }); - - test('deduplicates listeners', () { - reporter.addListener(call); - reporter.addListener(call); - reporter.notify(); - expect(called, 1); - reporter.removeListener(call); - reporter.notify(); - expect(called, 1); - }); - - test('safely removes multiple times', () { - reporter.removeListener(call); - reporter.addListener(call); - reporter.notify(); - expect(called, 1); - reporter.removeListener(call); - reporter.removeListener(call); - reporter.notify(); - expect(called, 1); - }); - }); - - group('ValueReporter', () { - int called = 0; - void call() { - called++; - } - - late ValueReporter reporter; - setUp(() { - reporter = ValueReporter(null); - }); - test('notifies listeners', () { - expect(reporter.hasListeners, false); - reporter.addListener(call); - expect(called, 0); - expect(reporter.hasListeners, true); - reporter.value = 'first call'; - expect(called, 1); - reporter.value = 'second call'; - reporter.value = 'third call'; - expect(called, 3); - reporter.removeListener(call); - reporter.value = 'fourth call'; - expect(called, 3); - }); - }); - group('SafeListOperations', () { test('safeFirst', () { final list = []; @@ -667,506 +428,207 @@ void main() { }); }); - group('MovingAverage', () { - const simpleDataSet = [ - 100, - 200, - 300, - 500, - 1000, - 2000, - 3000, - 4000, - 10000, - 100000, - ]; - - /// Data only has spikes. - const memorySizeDataSet = [ - 190432640, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 201045160, - 198200392, - 200144872, - 210110632, - 234077984, - 229029504, - 229029544, - 231396416, - 240465152, - 303434344, // Spike @ [25] (clear) - 302925712, - 356093472, - 354292096, - 400654120, - 400538848, - 402336872, - 444325760, - 444933104, - 341888120, - 406070376, - 343798216, - 392421072, - 392441080, - 481891656, - 481447920, - 433271776, - 464727280, - 494727280, - 564727280, - 524727280, - 534727280, - 564727280, - 764727280, // Spike @ [48] - 964727280, // Spike @ [49] - 1064727280, // Spike @ [50] - 1464727280, // Spike @ [51] - 2264727280, // Spike @ [52] - 2500000000, // Spike @ [53] - ]; - - /// Data has 5 spikes and 3 dips. - const dipsSpikesDataSet = [ - 190432640, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 190443808, - 5500000, // Dips @ [12] - 5600000, - 7443808, - 9043808, - 11045160, - 49800392, // Spikes @ [17] - 60144872, - 210110632, // Spikes @ [19] - 234077984, - 229029504, - 229029544, - 194000000, - 80000000, // Dips @ [24] - 100000000, - 150000000, - 240465152, // Spike @ [27] - 303434344, - 302925712, - 356093472, - 354292096, - 400654120, - 400538848, - 402336872, - 444325760, - 444933104, - 341888120, - 406070376, - 343798216, - 392421072, - 392441080, - 481891656, - 3000000, // Dips @ [43] - 3100000, - 3200000, - 330000000, // Spike @ [46] - 330000000, - 330000000, - 340000000, - 340000000, - 340000000, - 964727280, - 1064727280, - 1464727280, - 2264727280, // Spike @ [52] - 2500000000, - ]; - - void checkNewItemsAddedToDataSet(MovingAverage mA) { - mA.add(1000000); - mA.add(2000000); - mA.add(3000000); - expect(mA.dataSet.length, lessThan(mA.averagePeriod)); - expect(mA.mean.toInt(), equals(470853)); - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - } - - test('basic MA', () { - // Creation of MovingAverage statically. - final simpleMA = MovingAverage(newDataSet: simpleDataSet); - expect(simpleMA.dataSet.length, lessThan(simpleMA.averagePeriod)); - expect(simpleMA.mean.toInt(), equals(12110)); - checkNewItemsAddedToDataSet(simpleMA); - - simpleMA.clear(); - expect(simpleMA.mean, equals(0)); - - // Dynamically add data to MovingAverage data set. - for (int i = 0; i < simpleDataSet.length; i++) { - simpleMA.add(simpleDataSet[i]); - } - // Should be identical to static one from above. - expect(simpleMA.mean.toInt(), equals(12110)); - checkNewItemsAddedToDataSet(simpleMA); - }); - - test('normal static MA', () { - // Creation of MovingAverage statically. - final mA = MovingAverage(newDataSet: memorySizeDataSet); - // Mean only calculated on last averagePeriod entries (50 default). - expect(mA.mean.toInt(), equals(462271799)); - expect(mA.dataSet.length, equals(mA.averagePeriod)); - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - - mA.clear(); - expect(mA.mean, equals(0)); - expect(mA.dataSet.length, equals(0)); + group('ListExtension', () { + test('joinWith generates correct list', () { + expect([1, 2, 3, 4].joinWith(0), equals([1, 0, 2, 0, 3, 0, 4])); + expect([1].joinWith(0), equals([1])); + expect(['a', 'b'].joinWith('z'), equals(['a', 'z', 'b'])); }); + }); - test('dynamic spikes MA', () { - final mA = MovingAverage(); - - // Dynamically add data to MovingAverage data set. - for (int i = 0; i < 20; i++) { - mA.add(memorySizeDataSet[i]); - expect(mA.hasSpike(), isFalse); - expect(mA.isDipping(), isFalse); - } - expect(mA.mean.toInt(), equals(192829540)); - - for (int i = 20; i < 50; i++) { - mA.add(memorySizeDataSet[i]); - switch (i) { - case 25: - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - mA.clear(); - expect(mA.dataSet.length, 0); - break; - case 48: - case 49: - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - break; - default: - expect(mA.dataSet.length, i < 25 ? i + 1 : i - 25); - expect(mA.hasSpike(), isFalse); - expect(mA.isDipping(), isFalse); - } - } - expect(mA.mean.toInt(), equals(469047851)); - - expect(mA.dataSet.length, 24); - - for (int i = 50; i < memorySizeDataSet.length; i++) { - mA.add(memorySizeDataSet[i]); - switch (i) { - case 50: - expect(mA.mean.toInt(), equals(492875028)); - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - expect(mA.dataSet.length, equals(25)); - break; - case 51: - expect(mA.mean.toInt(), equals(530253961)); - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - expect(mA.dataSet.length, equals(26)); - break; - case 52: - expect(mA.mean.toInt(), equals(594493714)); - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - expect(mA.dataSet.length, equals(27)); - break; - case 53: - expect(mA.mean.toInt(), equals(662547510)); - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - expect(mA.dataSet.length, equals(28)); - break; - default: - expect(false, isTrue); - } - } - - // dataSet was cleared on first spike @ item 25 so - // dataSet only has the remaining 28 entries. - expect(mA.dataSet.length, 28); - expect(mA.mean.toInt(), equals(662547510)); - - mA.clear(); - expect(mA.mean, equals(0)); - expect(mA.dataSet.length, equals(0)); + group('NullableListExtension', () { + test('isNullOrEmpty', () { + List? nullableList; + expect(nullableList.isNullOrEmpty, true); + nullableList = []; + expect(nullableList.isNullOrEmpty, true); + nullableList.add(1); + expect(nullableList.isNullOrEmpty, false); }); + }); - test('dips and spikes MA', () { - final mA = MovingAverage(); - - // Dynamically add data to MovingAverage data set. - for (int i = 0; i < memorySizeDataSet.length; i++) { - mA.add(dipsSpikesDataSet[i]); - switch (i) { - case 12: - case 24: - case 43: - expect(mA.hasSpike(), isFalse); - expect(mA.isDipping(), isTrue); - break; - case 17: - case 19: - case 27: - case 46: - case 52: - expect(mA.hasSpike(), isTrue); - expect(mA.isDipping(), isFalse); - break; - default: - expect(mA.hasSpike(), isFalse); - expect(mA.isDipping(), isFalse); - } - if (mA.hasSpike() || mA.isDipping()) { - mA.clear(); - expect(mA.dataSet.length, 0); - } - } + group('SetExtension', () { + test('containsAny', () { + final test = {1, 2, 3, 4}; + final subSet = {1, 2}; + final disjointSet = {5, 6, 7}; + expect(test.containsAny(test), true); + expect(test.containsAny(subSet), true); + expect(test.containsAny(disjointSet), false); }); + }); - group('ListExtension', () { - test('joinWith generates correct list', () { - expect([1, 2, 3, 4].joinWith(0), equals([1, 0, 2, 0, 3, 0, 4])); - expect([1].joinWith(0), equals([1])); - expect(['a', 'b'].joinWith('z'), equals(['a', 'z', 'b'])); - }); - - test('allIndicesWhere', () { - final list = [1, 2, 1, 2, 3, 4]; - expect(list.allIndicesWhere((element) => element.isEven), [1, 3, 5]); - expect(list.allIndicesWhere((element) => element.isOdd), [0, 2, 4]); - expect(list.allIndicesWhere((element) => element + 2 == 3), [0, 2]); - }); + group('NullableStringExtension', () { + test('isNullOrEmpty', () { + String? str; + expect(str.isNullOrEmpty, isTrue); + str = ''; + expect(str.isNullOrEmpty, isTrue); + str = 'hello'; + expect(str.isNullOrEmpty, isFalse); + str = null; + expect(str.isNullOrEmpty, isTrue); }); + }); - group('NullableListExtension', () { - test('isNullOrEmpty', () { - List? nullableList; - expect(nullableList.isNullOrEmpty, true); - nullableList = []; - expect(nullableList.isNullOrEmpty, true); - nullableList.add(1); - expect(nullableList.isNullOrEmpty, false); - }); + group('StringExtension', () { + test('caseInsensitiveContains', () { + const str = 'This is a test string with a path/to/uri'; + expect(str.caseInsensitiveContains('test'), isTrue); + expect(str.caseInsensitiveContains('with a PATH/'), isTrue); + expect(str.caseInsensitiveContains('THIS IS A'), isTrue); + expect(str.caseInsensitiveContains('not a match'), isFalse); + expect(str.caseInsensitiveContains('test bool'), isFalse); + expect( + str.caseInsensitiveContains(RegExp('is.*path', caseSensitive: false)), + isTrue, + ); + expect( + () => str.caseInsensitiveContains(RegExp('is.*path')), + throwsAssertionError, + ); + expect( + str.caseInsensitiveContains( + RegExp('THIS IS.*TO/uri', caseSensitive: false), + ), + isTrue, + ); + expect( + str.caseInsensitiveContains( + RegExp('this.*does not match', caseSensitive: false), + ), + isFalse, + ); }); - group('SetExtension', () { - test('containsAny', () { - final test = {1, 2, 3, 4}; - final subSet = {1, 2}; - final disjointSet = {5, 6, 7}; - expect(test.containsAny(test), true); - expect(test.containsAny(subSet), true); - expect(test.containsAny(disjointSet), false); - }); - }); + test('caseInsensitiveEquals', () { + const str = 'hello, world!'; + expect(str.caseInsensitiveEquals(str), isTrue); + expect(str.caseInsensitiveEquals('HELLO, WORLD!'), isTrue); + expect(str.caseInsensitiveEquals('hElLo, WoRlD!'), isTrue); + expect(str.caseInsensitiveEquals('hello'), isFalse); + expect(str.caseInsensitiveEquals(''), isFalse); + expect(str.caseInsensitiveEquals(null), isFalse); + expect(''.caseInsensitiveEquals(''), isTrue); + expect(''.caseInsensitiveEquals(null), isFalse); - group('NullableStringExtension', () { - test('isNullOrEmpty', () { - String? str; - expect(str.isNullOrEmpty, isTrue); - str = ''; - expect(str.isNullOrEmpty, isTrue); - str = 'hello'; - expect(str.isNullOrEmpty, isFalse); - str = null; - expect(str.isNullOrEmpty, isTrue); - }); + // Complete match. + expect( + str.caseInsensitiveEquals(RegExp('h.*o.*', caseSensitive: false)), + isTrue, + ); + // Incomplete match. + expect( + str.caseInsensitiveEquals(RegExp('h.*o', caseSensitive: false)), + isFalse, + ); + // No match. + expect( + str.caseInsensitiveEquals( + RegExp('hello.* this does not match', caseSensitive: false), + ), + isFalse, + ); }); - group('StringExtension', () { - test('caseInsensitiveContains', () { - const str = 'This is a test string with a path/to/uri'; - expect(str.caseInsensitiveContains('test'), isTrue); - expect(str.caseInsensitiveContains('with a PATH/'), isTrue); - expect(str.caseInsensitiveContains('THIS IS A'), isTrue); - expect(str.caseInsensitiveContains('not a match'), isFalse); - expect(str.caseInsensitiveContains('test bool'), isFalse); - expect( - str.caseInsensitiveContains(RegExp('is.*path', caseSensitive: false)), - isTrue, - ); - expect( - () => str.caseInsensitiveContains(RegExp('is.*path')), - throwsAssertionError, - ); - expect( - str.caseInsensitiveContains( - RegExp('THIS IS.*TO/uri', caseSensitive: false), - ), - isTrue, - ); - expect( - str.caseInsensitiveContains( - RegExp('this.*does not match', caseSensitive: false), - ), - isFalse, - ); - }); - - test('caseInsensitiveEquals', () { - const str = 'hello, world!'; - expect(str.caseInsensitiveEquals(str), isTrue); - expect(str.caseInsensitiveEquals('HELLO, WORLD!'), isTrue); - expect(str.caseInsensitiveEquals('hElLo, WoRlD!'), isTrue); - expect(str.caseInsensitiveEquals('hello'), isFalse); - expect(str.caseInsensitiveEquals(''), isFalse); - expect(str.caseInsensitiveEquals(null), isFalse); - expect(''.caseInsensitiveEquals(''), isTrue); - expect(''.caseInsensitiveEquals(null), isFalse); - - // Complete match. - expect( - str.caseInsensitiveEquals(RegExp('h.*o.*', caseSensitive: false)), - isTrue, - ); - // Incomplete match. - expect( - str.caseInsensitiveEquals(RegExp('h.*o', caseSensitive: false)), - isFalse, - ); - // No match. - expect( - str.caseInsensitiveEquals( - RegExp('hello.* this does not match', caseSensitive: false), - ), - isFalse, - ); - }); + test('caseInsensitiveAllMatches', () { + const str = 'This is a TEST. Test string is "test"'; + final matches = 'test'.caseInsensitiveAllMatches(str).toList(); + expect(matches.length, equals(3)); - test('caseInsensitiveAllMatches', () { - const str = 'This is a TEST. Test string is "test"'; - final matches = 'test'.caseInsensitiveAllMatches(str).toList(); - expect(matches.length, equals(3)); + // First match: 'TEST' + expect(matches[0].start, equals(10)); + expect(matches[0].end, equals(14)); - // First match: 'TEST' - expect(matches[0].start, equals(10)); - expect(matches[0].end, equals(14)); + // Second match: 'Test' + expect(matches[1].start, equals(16)); + expect(matches[1].end, equals(20)); - // Second match: 'Test' - expect(matches[1].start, equals(16)); - expect(matches[1].end, equals(20)); + // Third match: 'test' + expect(matches[2].start, equals(32)); + expect(matches[2].end, equals(36)); - // Third match: 'test' - expect(matches[2].start, equals(32)); - expect(matches[2].end, equals(36)); + // Dart's allMatches returns 1 char matches when pattern is an empty string + expect( + ''.caseInsensitiveAllMatches('hello world').length, + equals('hello world'.length + 1), + ); + expect('*'.caseInsensitiveAllMatches('hello world'), isEmpty); + expect('test'.caseInsensitiveAllMatches(''), isEmpty); + expect('test'.caseInsensitiveAllMatches(null), isEmpty); + }); + }); - // Dart's allMatches returns 1 char matches when pattern is an empty string - expect( - ''.caseInsensitiveAllMatches('hello world').length, - equals('hello world'.length + 1), - ); - expect('*'.caseInsensitiveAllMatches('hello world'), isEmpty); - expect('test'.caseInsensitiveAllMatches(''), isEmpty); - expect('test'.caseInsensitiveAllMatches(null), isEmpty); - }); + group('BoolExtension', () { + test('boolCompare', () { + expect(true.boolCompare(true), equals(0)); + expect(false.boolCompare(false), equals(0)); + expect(true.boolCompare(false), equals(-1)); + expect(false.boolCompare(true), equals(1)); }); + }); - group('BoolExtension', () { - test('boolCompare', () { - expect(true.boolCompare(true), equals(0)); - expect(false.boolCompare(false), equals(0)); - expect(true.boolCompare(false), equals(-1)); - expect(false.boolCompare(true), equals(1)); - }); + group('subtractMaps', () { + test('subtracts non-null maps', () { + final subtract = {1: 'subtract'}; + final from = {1: 1.0, 2: 2.0}; + _SubtractionResult? elementSubtractor({ + required String? subtract, + required double? from, + }) => _SubtractionResult(subtract: subtract, from: from); + + final result = subtractMaps( + subtract: subtract, + from: from, + subtractor: elementSubtractor, + ); + + expect( + const SetEquality().equals(result.keys.toSet(), {1, 2}), + true, + ); + expect( + result[1], + equals(_SubtractionResult(subtract: 'subtract', from: 1.0)), + ); + expect(result[2], equals(_SubtractionResult(subtract: null, from: 2.0))); }); - group('subtractMaps', () { - test('subtracts non-null maps', () { - final subtract = {1: 'subtract'}; - final from = {1: 1.0, 2: 2.0}; - _SubtractionResult? elementSubtractor({ - required String? subtract, - required double? from, - }) => _SubtractionResult(subtract: subtract, from: from); - - final result = subtractMaps( - subtract: subtract, - from: from, - subtractor: elementSubtractor, - ); + test('subtracts null', () { + final from = {1: 1.0}; + _SubtractionResult? elementSubtractor({ + required String? subtract, + required double? from, + }) => _SubtractionResult(subtract: subtract, from: from); - expect( - const SetEquality().equals(result.keys.toSet(), {1, 2}), - true, - ); - expect( - result[1], - equals(_SubtractionResult(subtract: 'subtract', from: 1.0)), - ); - expect( - result[2], - equals(_SubtractionResult(subtract: null, from: 2.0)), - ); - }); + final result = subtractMaps( + subtract: null, + from: from, + subtractor: elementSubtractor, + ); - test('subtracts null', () { - final from = {1: 1.0}; - _SubtractionResult? elementSubtractor({ - required String? subtract, - required double? from, - }) => _SubtractionResult(subtract: subtract, from: from); - - final result = subtractMaps( - subtract: null, - from: from, - subtractor: elementSubtractor, - ); + expect(const SetEquality().equals(result.keys.toSet(), {1}), true); + expect(result[1], equals(_SubtractionResult(subtract: null, from: 1.0))); + }); - expect(const SetEquality().equals(result.keys.toSet(), {1}), true); - expect( - result[1], - equals(_SubtractionResult(subtract: null, from: 1.0)), - ); - }); + test('subtracts from null', () { + final subtract = {1: 'subtract'}; + _SubtractionResult? elementSubtractor({ + required String? subtract, + required double? from, + }) => _SubtractionResult(subtract: subtract, from: from); - test('subtracts from null', () { - final subtract = {1: 'subtract'}; - _SubtractionResult? elementSubtractor({ - required String? subtract, - required double? from, - }) => _SubtractionResult(subtract: subtract, from: from); - - final result = subtractMaps( - subtract: subtract, - from: null, - subtractor: elementSubtractor, - ); + final result = subtractMaps( + subtract: subtract, + from: null, + subtractor: elementSubtractor, + ); - expect(const SetEquality().equals(result.keys.toSet(), {1}), true); - expect( - result[1], - equals(_SubtractionResult(subtract: 'subtract', from: null)), - ); - }); + expect(const SetEquality().equals(result.keys.toSet(), {1}), true); + expect( + result[1], + equals(_SubtractionResult(subtract: 'subtract', from: null)), + ); }); }); diff --git a/packages/devtools_app/test/shared/ui/common_widgets_test.dart b/packages/devtools_app/test/shared/ui/common_widgets_test.dart index 6b65b52aa4b..c882092ce79 100644 --- a/packages/devtools_app/test/shared/ui/common_widgets_test.dart +++ b/packages/devtools_app/test/shared/ui/common_widgets_test.dart @@ -13,8 +13,6 @@ import 'package:flutter_test/flutter_test.dart'; // TODO(kenz): add tests for other widgets in common_widgets.dart void main() { - const windowSize = Size(1000.0, 1000.0); - setUp(() { setGlobal( DevToolsEnvironmentParameters, @@ -25,41 +23,6 @@ void main() { setGlobal(IdeTheme, IdeTheme()); }); - group('Common widgets', () { - testWidgetsWithWindowSize( - 'processingInfo builds for progressValue', - windowSize, - (WidgetTester tester) async { - await tester.pumpWidget( - wrap( - const ProcessingInfo( - progressValue: 0.0, - processedObject: 'fake object', - ), - ), - ); - - final progressIndicatorFinder = find.byType(LinearProgressIndicator); - LinearProgressIndicator progressIndicator = tester.widget( - progressIndicatorFinder, - ); - - expect(progressIndicator.value, equals(0.0)); - - await tester.pumpWidget( - wrap( - const ProcessingInfo( - progressValue: 0.5, - processedObject: 'fake object', - ), - ), - ); - progressIndicator = tester.widget(progressIndicatorFinder); - expect(progressIndicator.value, equals(0.5)); - }, - ); - }); - group('NotifierCheckbox', () { bool? findCheckboxValue() { final checkboxWidget = diff --git a/packages/devtools_app/test/shared/utils/utils_test.dart b/packages/devtools_app/test/shared/utils/utils_test.dart index b9cbdf7c9ec..ee6eeed1603 100644 --- a/packages/devtools_app/test/shared/utils/utils_test.dart +++ b/packages/devtools_app/test/shared/utils/utils_test.dart @@ -212,6 +212,10 @@ void main() { ); }); + tearDown(() { + worker.dispose(); + }); + test('0 length', () async { final result = await worker.doWork(0); expect(result, true); diff --git a/packages/devtools_app/test/standalone_ui/ide_shared/property_editor/utils_test.dart b/packages/devtools_app/test/standalone_ui/ide_shared/property_editor/utils_test.dart index 8b45772d59b..eec1e4c5843 100644 --- a/packages/devtools_app/test/standalone_ui/ide_shared/property_editor/utils_test.dart +++ b/packages/devtools_app/test/standalone_ui/ide_shared/property_editor/utils_test.dart @@ -91,8 +91,6 @@ void main() { final firstChild = children.first; final secondChild = children.second; final thirdChild = children.third; - final fourthChild = children.fourth; - final fifthChild = children.fifth; expect( text.textSpan?.toPlainText(), @@ -104,10 +102,6 @@ void main() { expect(_hasStyle(secondChild, style: fixedFontStyle), isTrue); expect(thirdChild.toPlainText(), equals(' and ')); expect(_hasStyle(thirdChild, style: regularFontStyle), isTrue); - expect(fourthChild.toPlainText(), equals('some code')); - expect(_hasStyle(fourthChild, style: fixedFontStyle), isTrue); - expect(fifthChild.toPlainText(), equals('.')); - expect(_hasStyle(fifthChild, style: regularFontStyle), isTrue); }); testWidgets('DartDocConverter handles unmatched brackets', ( From ea85f52152e00176f189fd35eccb977be00c1c33 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:25:48 -0700 Subject: [PATCH 15/19] add back fixedMinY and link bug --- .../devtools_app/lib/src/shared/charts/chart_trace.dart | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/packages/devtools_app/lib/src/shared/charts/chart_trace.dart b/packages/devtools_app/lib/src/shared/charts/chart_trace.dart index 9fa2910ce31..5e1ab4959ea 100644 --- a/packages/devtools_app/lib/src/shared/charts/chart_trace.dart +++ b/packages/devtools_app/lib/src/shared/charts/chart_trace.dart @@ -34,6 +34,7 @@ class PaintCharacteristics { this.concentricCenterDiameter = 1, this.width = 1, this.height = 1, + this.fixedMinY, this.fixedMaxY, }); @@ -47,9 +48,15 @@ class PaintCharacteristics { this.concentricCenterDiameter = 1, this.width = 1, this.height = 1, + this.fixedMinY, this.fixedMaxY, }); + /// If specified Y scale is computed and min value is fixed. + /// Will assert if new data point is less than min specified. + // ignore: unused-code, TODO(https://github.com/flutter/devtools/issues/9910) seems like a bug. + double? fixedMinY; + /// If specified Y scale is computed and max value is fixed. /// Will assert if new data point is more than max specified. double? fixedMaxY; From 38c92e211057063c03a9c54ccbcc27641ad852ed Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:47:39 -0700 Subject: [PATCH 16/19] fix pretty print review comment --- .../devtools_app/benchmark/devtools_benchmarks_test.dart | 2 +- .../benchmark/scripts/compare_benchmarks.dart | 2 +- .../lib/src/screens/debugger/span_parser.dart | 4 ++-- .../lib/src/screens/logging/logging_controller.dart | 3 +-- .../_framework_initialize_desktop.dart | 2 +- .../devtools_app/lib/src/shared/primitives/utils.dart | 7 +++---- .../devtools_app/lib/src/shared/ui/common_widgets.dart | 9 +++++---- 7 files changed, 14 insertions(+), 15 deletions(-) diff --git a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart index 78bab65b0cc..6b64940f19b 100644 --- a/packages/devtools_app/benchmark/devtools_benchmarks_test.dart +++ b/packages/devtools_app/benchmark/devtools_benchmarks_test.dart @@ -92,7 +92,7 @@ Future _runBenchmarks({bool useWasm = false}) async { stdout.writeln('Web benchmark tests finished.'); - expect(taskResult.toJson().prettyPrint(), isA()); + expect(prettyPrintJson(taskResult.toJson()), isA()); expect(taskResult.scores.keys, hasLength(DevToolsBenchmark.values.length)); for (final devToolsBenchmark in DevToolsBenchmark.values) { diff --git a/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart b/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart index 68e9c1c9f90..25c49634514 100644 --- a/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart +++ b/packages/devtools_app/benchmark/scripts/compare_benchmarks.dart @@ -62,6 +62,6 @@ void compareBenchmarks( stdout.writeln('Baseline comparison finished.'); stdout ..writeln('==== Comparison with baseline $baselineSource ====') - ..writeln(delta.toJson().prettyPrint()) + ..writeln(prettyPrintJson(delta.toJson())) ..writeln('==== End of baseline comparison ===='); } diff --git a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart index b5a92c54a26..e1bf02884f1 100644 --- a/packages/devtools_app/lib/src/screens/debugger/span_parser.dart +++ b/packages/devtools_app/lib/src/screens/debugger/span_parser.dart @@ -69,12 +69,12 @@ class Grammar { @override String toString() { - return { + return prettyPrintJson({ 'name': name, 'scopeName': scopeName, 'topLevelMatcher': topLevelMatcher.toJson(), 'repository': repository.toJson(), - }.prettyPrint(); + }); } } diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart index 06d65020970..eada1530cdf 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -1038,8 +1038,7 @@ class LogData with SearchableDataMixin { } try { - return (jsonDecode(details!) as Object?) - .prettyPrint() + return prettyPrintJson(jsonDecode(details!) as Object?) .replaceAll(r'\n', '\n') .trim(); } catch (_) { diff --git a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart index 494869a8123..1c8710aa9d8 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/framework_initialize/_framework_initialize_desktop.dart @@ -37,7 +37,7 @@ class FlutterDesktopStorage implements Storage { File(_preferencesFile.path).createSync(recursive: true); _fileAndDirVerified = true; } - _preferencesFile.writeAsStringSync('${_values.prettyPrint()}\n'); + _preferencesFile.writeAsStringSync('${prettyPrintJson(_values)}\n'); } Map _readValues() { diff --git a/packages/devtools_app/lib/src/shared/primitives/utils.dart b/packages/devtools_app/lib/src/shared/primitives/utils.dart index 892835c1864..d09c45a3a5b 100644 --- a/packages/devtools_app/lib/src/shared/primitives/utils.dart +++ b/packages/devtools_app/lib/src/shared/primitives/utils.dart @@ -212,10 +212,9 @@ class JsonUtils { } } -/// Add pretty print for a JSON payload. -extension JsonObjectExtension on Object? { - String prettyPrint() => const JsonEncoder.withIndent(' ').convert(this); -} +/// Returns a pretty-printed representation of a JSON payload. +String prettyPrintJson(Object? json) => + const JsonEncoder.withIndent(' ').convert(json); typedef RateLimiterCallback = Future Function(); diff --git a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart index 6fd5b74fed5..16741157204 100644 --- a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart +++ b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart @@ -1044,13 +1044,14 @@ class _JsonViewerState extends State { String copyJsonData(DartObjectNode copiedVariable) { // Check if service connection is active if (serviceConnection.serviceManager.connectedState.value.connected) { - return serviceConnection.serviceManager.service!.fakeServiceCache - .instanceToJson(copiedVariable.value as Instance) - .prettyPrint(); + return prettyPrintJson( + serviceConnection.serviceManager.service!.fakeServiceCache + .instanceToJson(copiedVariable.value as Instance), + ); } // Directly convert object to JSON if not connected - return copiedVariable.value.prettyPrint(); + return prettyPrintJson(copiedVariable.value); } } From ff90e914f137e5072baa09d5d7ff10da520282a6 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 13:50:44 -0700 Subject: [PATCH 17/19] formatting --- .../src/screens/inspector/inspector_tree_controller.dart | 3 +-- .../lib/src/screens/logging/logging_controller.dart | 6 +++--- .../config_specific/post_message/_post_message_web.dart | 3 +-- .../lib/src/shared/console/eval/inspector_tree.dart | 8 +++----- .../devtools_app/lib/src/shared/primitives/trees.dart | 2 +- .../devtools_app/lib/src/shared/ui/common_widgets.dart | 2 +- packages/devtools_app/lib/src/shared/ui/icons.dart | 2 +- 7 files changed, 11 insertions(+), 15 deletions(-) diff --git a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart index 1d57584ef96..de13f6173f2 100644 --- a/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart +++ b/packages/devtools_app/lib/src/screens/inspector/inspector_tree_controller.dart @@ -120,8 +120,7 @@ class InspectorTreeController extends DisposableController /// [InspectorTreeController]. final int? gaId; - InspectorTreeNode createNode() => - InspectorTreeNode(); + InspectorTreeNode createNode() => InspectorTreeNode(); SearchTargetType _searchTarget = SearchTargetType.widget; int _rootSetCount = 0; diff --git a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart index eada1530cdf..3c570845d71 100644 --- a/packages/devtools_app/lib/src/screens/logging/logging_controller.dart +++ b/packages/devtools_app/lib/src/screens/logging/logging_controller.dart @@ -1038,9 +1038,9 @@ class LogData with SearchableDataMixin { } try { - return prettyPrintJson(jsonDecode(details!) as Object?) - .replaceAll(r'\n', '\n') - .trim(); + return prettyPrintJson( + jsonDecode(details!) as Object?, + ).replaceAll(r'\n', '\n').trim(); } catch (_) { return details?.trim(); } diff --git a/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart b/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart index 0bbc6edeaa1..423c7da52f3 100644 --- a/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart +++ b/packages/devtools_app/lib/src/shared/config_specific/post_message/_post_message_web.dart @@ -12,8 +12,7 @@ import 'post_message.dart'; Stream get onPostMessage { return window.onMessage.map( - (message) => - PostMessageEvent(data: message.data.dartify()), + (message) => PostMessageEvent(data: message.data.dartify()), ); } diff --git a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart index 9751df42200..2d699439e92 100644 --- a/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart +++ b/packages/devtools_app/lib/src/shared/console/eval/inspector_tree.dart @@ -33,11 +33,9 @@ const inspectorRowHeight = 20.0; /// specific as that is the only case we care about. // TODO(kenz): extend TreeNode class to share tree logic. class InspectorTreeNode { - InspectorTreeNode({ - this.parent, - bool expandChildren = true, - }) : _children = [], - _isExpanded = expandChildren; + InspectorTreeNode({this.parent, bool expandChildren = true}) + : _children = [], + _isExpanded = expandChildren; bool get showLinesToChildren { return _children.length > 1 && !_children.last.isProperty; diff --git a/packages/devtools_app/lib/src/shared/primitives/trees.dart b/packages/devtools_app/lib/src/shared/primitives/trees.dart index ea8d3d358cc..d41fc08f97b 100644 --- a/packages/devtools_app/lib/src/shared/primitives/trees.dart +++ b/packages/devtools_app/lib/src/shared/primitives/trees.dart @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file or at https://developers.google.com/open-source/licenses/bsd. -// ignore_for_file: unused-code, retain methods for completeness of TreeNode model class. +// ignore_for_file: unused-code, retain methods for completeness of TreeNode model class. import 'dart:collection'; import 'dart:math'; diff --git a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart index 16741157204..d26a6cb4487 100644 --- a/packages/devtools_app/lib/src/shared/ui/common_widgets.dart +++ b/packages/devtools_app/lib/src/shared/ui/common_widgets.dart @@ -1046,7 +1046,7 @@ class _JsonViewerState extends State { if (serviceConnection.serviceManager.connectedState.value.connected) { return prettyPrintJson( serviceConnection.serviceManager.service!.fakeServiceCache - .instanceToJson(copiedVariable.value as Instance), + .instanceToJson(copiedVariable.value as Instance), ); } diff --git a/packages/devtools_app/lib/src/shared/ui/icons.dart b/packages/devtools_app/lib/src/shared/ui/icons.dart index 63da28c5ff6..543b0cb5d9b 100644 --- a/packages/devtools_app/lib/src/shared/ui/icons.dart +++ b/packages/devtools_app/lib/src/shared/ui/icons.dart @@ -87,7 +87,7 @@ class CustomIconMaker { } } -const infoIcon = AssetImageIcon(asset: 'icons/custom/info.png'); +const infoIcon = AssetImageIcon(asset: 'icons/custom/info.png'); class ColorIcon extends StatelessWidget { const ColorIcon(this.color, {super.key}); From 9115264944f6cecce6ebd723cef4bf6033213863 Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 14:30:12 -0700 Subject: [PATCH 18/19] fix json bug --- packages/devtools_app/lib/src/shared/framework/routing.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/framework/routing.dart b/packages/devtools_app/lib/src/shared/framework/routing.dart index eb4f84f9bc9..a8bd115b6b7 100644 --- a/packages/devtools_app/lib/src/shared/framework/routing.dart +++ b/packages/devtools_app/lib/src/shared/framework/routing.dart @@ -76,7 +76,7 @@ class DevToolsRouteInformationParser params.removeWhere((key, value) => value == null); return RouteInformation( uri: Uri(path: path, queryParameters: params), - state: configuration.state, + state: configuration.state?.state, ); } From 7edfd60806bec2233e524d9b314e96a60991325c Mon Sep 17 00:00:00 2001 From: Kenzie Davisson Date: Mon, 27 Jul 2026 14:54:30 -0700 Subject: [PATCH 19/19] Add back toJson method --- packages/devtools_app/lib/src/shared/framework/routing.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/devtools_app/lib/src/shared/framework/routing.dart b/packages/devtools_app/lib/src/shared/framework/routing.dart index a8bd115b6b7..5de3eabe6d6 100644 --- a/packages/devtools_app/lib/src/shared/framework/routing.dart +++ b/packages/devtools_app/lib/src/shared/framework/routing.dart @@ -76,7 +76,7 @@ class DevToolsRouteInformationParser params.removeWhere((key, value) => value == null); return RouteInformation( uri: Uri(path: path, queryParameters: params), - state: configuration.state?.state, + state: configuration.state, ); } @@ -383,6 +383,9 @@ class DevToolsNavigationState { @override String toString() => _state.toString(); + + // ignore: unused-code, implicit method used in JSON serialization. + Map toJson() => _state; } /// Mixin that gives controllers the ability to respond to changes in router